/* dv-m68hc11spi.c -- Simulation of the 68HC11 SPI
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2002 Free Software Foundation, Inc.
Written by Stephane Carrez (stcarrez@worldnet.fr)
(From a driver model Contributed by Cygnus Solutions.)
attach_m68hc11spi_regs (struct hw *me,
struct m68hc11spi *controller)
{
- hw_attach_address (hw_parent (me), 0, io_map,
+ hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
M6811_SPI_FIRST_REG,
M6811_SPI_LAST_REG - M6811_SPI_FIRST_REG + 1,
me);
struct m68hc11spi *controller;
controller = HW_ZALLOC (me, struct m68hc11spi);
- me->overlap_mode_hw = 1;
set_hw_data (me, controller);
set_hw_io_read_buffer (me, m68hc11spi_io_read_buffer);
set_hw_io_write_buffer (me, m68hc11spi_io_write_buffer);
static void
set_bit_port (struct hw *me, sim_cpu *cpu, int port, int mask, int value)
{
- /* TODO: Post an event to inform other devices that pin 'port' changes.
- This has only a sense if we provide some device that is logically
- connected to these pin ports (SCLK and MOSI) and that handles
- the SPI protocol. */
+ uint8 val;
+
if (value)
- cpu->ios[port] |= mask;
+ val = cpu->ios[port] | mask;
else
- cpu->ios[port] &= ~mask;
+ val = cpu->ios[port] & ~mask;
+
+ /* Set the new value and post an event to inform other devices
+ that pin 'port' changed. */
+ m68hc11cpu_set_port (me, cpu, port, val);
}
*/
-#define SPI_START_BIT 0
-#define SPI_MIDDLE_BIT 1
+#define SPI_START_BYTE 0
+#define SPI_START_BIT 1
+#define SPI_MIDDLE_BIT 2
void
m68hc11spi_clock (struct hw *me, void *data)
controller->tx_bit--;
controller->mode = SPI_MIDDLE_BIT;
}
- else
+ else if (controller->mode == SPI_MIDDLE_BIT)
{
controller->mode = SPI_START_BIT;
}
- /* Change the SPI clock at each event on bit 4 of port D. */
- controller->clk_pin = ~controller->clk_pin;
- set_bit_port (me, cpu, M6811_PORTD, (1 << 4), controller->clk_pin);
+ if (controller->mode == SPI_START_BYTE)
+ {
+ /* Start a new SPI transfer. */
+ /* TBD: clear SS output. */
+ controller->mode = SPI_START_BIT;
+ controller->tx_bit = 7;
+ set_bit_port (me, cpu, M6811_PORTD, (1 << 4), ~controller->clk_pin);
+ }
+ else
+ {
+ /* Change the SPI clock at each event on bit 4 of port D. */
+ controller->clk_pin = ~controller->clk_pin;
+ set_bit_port (me, cpu, M6811_PORTD, (1 << 4), controller->clk_pin);
+ }
+
/* Transmit is now complete for this byte. */
if (controller->mode == SPI_START_BIT && controller->tx_bit < 0)
{
{
signed64 t;
+ sim_io_printf (sd, " SPI has %d bits to send\n",
+ controller->tx_bit + 1);
t = hw_event_remain_time (me, controller->spi_event);
- sim_io_printf (sd, " SPI operation finished in %ld cycles\n",
- (long) t);
+ sim_io_printf (sd, " SPI current bit-cycle finished in %s\n",
+ cycle_to_string (cpu, t));
+
+ t += (controller->tx_bit + 1) * 2 * controller->clock;
+ sim_io_printf (sd, " SPI operation finished in %s\n",
+ cycle_to_string (cpu, t));
}
}
{
cpu->ios[M6811_SPSR] &= ~controller->rx_clear_scsr;
controller->rx_clear_scsr = 0;
+ interrupts_update_pending (&cpu->cpu_interrupts);
}
val = controller->rx_char;
break;
return 0;
}
+ if (controller->rx_clear_scsr)
+ {
+ cpu->ios[M6811_SPSR] &= ~controller->rx_clear_scsr;
+ controller->rx_clear_scsr = 0;
+ interrupts_update_pending (&cpu->cpu_interrupts);
+ }
+
/* If transfer is taking place, a write to SPDR
generates a collision. */
if (controller->spi_event)
/* Prepare to send a byte. */
controller->tx_char = val;
- controller->tx_bit = 7;
- controller->mode = 0;
+ controller->mode = SPI_START_BYTE;
/* Toggle clock pin internal value when CPHA is 0 so that
it will really change in the middle of a bit. */
const struct hw_descriptor dv_m68hc11spi_descriptor[] = {
- { "m68hc11spi", m68hc11spi_finish, },
+ { "m68hc11spi", m68hc11spi_finish },
+ { "m68hc12spi", m68hc11spi_finish },
{ NULL },
};