39 #include "avrmalloc.h"
68 static void spii_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
70 static uint8_t spi_intr_read (VDevice *dev,
int addr);
71 static void spi_intr_write (VDevice *dev,
int addr, uint8_t val);
72 static void spi_intr_reset (VDevice *dev);
73 static int spi_intr_cb (uint64_t time, AvrClass *data);
80 return (VDevice *)spi_intr_new (addr, name);
84 spi_intr_new (
int addr,
char *name)
104 spi_intr_reset, spii_add_addr);
106 spii_add_addr ((VDevice *)spi, addr, name, 0, NULL);
107 spi_intr_reset ((VDevice *)spi);
111 spii_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
void *data)
113 SPIIntr_T *spi = (SPIIntr_T *)vdev;
115 if (strncmp (
"SPCR", name, 4) == 0)
117 spi->spcr_addr = addr;
120 else if (strncmp (
"SPSR", name, 4) == 0)
122 spi->spsr_addr = addr;
127 avr_error (
"invalid ADC register name: '%s' @ 0x%04x", name, addr);
143 spi_intr_read (VDevice *dev,
int addr)
145 SPIIntr_T *spi = (SPIIntr_T *)dev;
147 if (addr == spi->spcr_addr)
152 else if (addr == spi->spsr_addr)
154 if (spi->spsr & mask_SPIF)
155 spi->spsr_read |= mask_SPIF;
156 if (spi->spsr & mask_WCOL)
157 spi->spsr_read |= mask_WCOL;
170 spi_intr_write (VDevice *dev,
int addr, uint8_t val)
172 SPIIntr_T *spi = (SPIIntr_T *)dev;
175 if (addr == spi->spcr_addr)
178 if (spi->spcr & mask_SPE)
181 cb = callback_new (spi_intr_cb, (AvrClass *)spi);
199 spi_intr_reset (VDevice *dev)
201 SPIIntr_T *spi = (SPIIntr_T *)dev;
211 spi_intr_cb (uint64_t time, AvrClass *data)
213 SPIIntr_T *spi = (SPIIntr_T *)data;
215 if (spi->intr_cb == NULL)
216 return CB_RET_REMOVE;
218 if ((spi->spcr & mask_SPE) && (spi->spcr & mask_SPIE)
219 && (spi->spsr & mask_SPIF))
224 spi->spsr &= ~mask_SPIF;
228 return CB_RET_RETAIN;
237 static void spi_add_addr (VDevice *vdev,
int addr,
char *name,
int rel_addr,
239 static uint8_t spi_read (VDevice *dev,
int addr);
240 static void spi_write (VDevice *dev,
int addr, uint8_t val);
241 static void spi_reset (VDevice *dev);
242 static int spi_clk_incr_cb (uint64_t ck, AvrClass *data);
249 return (VDevice *)spi_new (addr, name, rel_addr);
253 spi_new (
int addr,
char *name,
int rel_addr)
275 spi_add_addr ((VDevice *)spi, addr, name, 0, NULL);
277 spi->rel_addr = rel_addr;
278 spi_reset ((VDevice *)spi);
282 spi_add_addr (VDevice *vdev,
int addr,
char *name,
int ref_addr,
void *data)
284 SPI_T *spi = (SPI_T *)vdev;
286 if (strncmp (
"SPDR", name, 4) == 0)
288 spi->spdr_addr = addr;
293 avr_error (
"invalid SPI register name: '%s' @ 0x%04x", name, addr);
309 spi_read (VDevice *dev,
int addr)
311 SPI_T *spi = (SPI_T *)dev;
320 if (addr == spi->spdr_addr)
322 if (spi_ti->spsr_read)
324 spi_ti->spsr &= ~spi_ti->spsr_read;
325 spi_ti->spsr_read = 0;
340 spi_write (VDevice *dev,
int addr, uint8_t val)
342 SPI_T *spi = (SPI_T *)dev;
352 if (addr == spi->spdr_addr)
354 if (spi_ti->spsr_read)
356 spi_ti->spsr &= ~spi_ti->spsr_read;
357 spi_ti->spsr_read = 0;
362 spi_ti->spsr |= mask_WCOL;
372 switch ((spi_ti->spcr) & (mask_SPR0 | mask_SPR1))
391 if (spi->clk_cb == NULL)
393 cb = callback_new (spi_clk_incr_cb, (AvrClass *)spi);
399 spi->spdr_in = spi_port_rd (addr);
408 spi_reset (VDevice *dev)
410 SPI_T *spi = (SPI_T *)dev;
421 spi_clk_incr_cb (uint64_t ck, AvrClass *data)
423 SPI_T *spi = (SPI_T *)data;
424 uint8_t last = spi->tcnt;
433 if (spi->clk_cb == NULL)
434 return CB_RET_REMOVE;
436 if (spi->divisor <= 0)
437 avr_error (
"Bad divisor value: %d", spi->divisor);
442 spi->tcnt -= ((ck & (spi->divisor - 1)) == 0);
444 if (spi->tcnt != last)
448 spi_ti->spsr |= mask_SPIF;
450 spi_port_wr (spi->spdr);
451 spi->spdr = spi->spdr_in;
454 return CB_RET_REMOVE;
458 return CB_RET_RETAIN;
465 spi_port_rd (
int addr)
473 "\nEnter a byte of hex data to read into the SPI at"
474 " address 0x%04x: ", addr);
477 if (fgets (line,
sizeof (line), stdin) == NULL)
481 if (sscanf (line,
"%x\n", &data) != 1)
487 return (uint8_t) (data & 0xff);
491 spi_port_wr (uint8_t val)
493 fprintf (stderr,
"wrote 0x%02x to SPI\n", val);