00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #include <config.h>
00033
00034 #include <stdio.h>
00035 #include <stdlib.h>
00036 #include <string.h>
00037
00038 #include "avrerror.h"
00039 #include "avrmalloc.h"
00040 #include "avrclass.h"
00041 #include "utils.h"
00042 #include "callback.h"
00043 #include "op_names.h"
00044
00045 #include "storage.h"
00046 #include "flash.h"
00047
00048 #include "vdevs.h"
00049 #include "memory.h"
00050 #include "stack.h"
00051 #include "register.h"
00052 #include "sram.h"
00053 #include "eeprom.h"
00054 #include "timers.h"
00055 #include "ports.h"
00056 #include "spi.h"
00057
00058 #include "avrcore.h"
00059
00060 #include "intvects.h"
00061
00062
00063
00064
00065
00066
00067
00068 static void spii_add_addr (VDevice *vdev, int addr, char *name, int rel_addr,
00069 void *data);
00070 static uint8_t spi_intr_read (VDevice *dev, int addr);
00071 static void spi_intr_write (VDevice *dev, int addr, uint8_t val);
00072 static void spi_intr_reset (VDevice *dev);
00073 static int spi_intr_cb (uint64_t time, AvrClass *data);
00074
00075
00076
00077 VDevice *
00078 spii_create (int addr, char *name, int rel_addr, void *data)
00079 {
00080 return (VDevice *)spi_intr_new (addr, name);
00081 }
00082
00083 SPIIntr_T *
00084 spi_intr_new (int addr, char *name)
00085 {
00086 SPIIntr_T *spi;
00087
00088 spi = avr_new (SPIIntr_T, 1);
00089 spi_intr_construct (spi, addr, name);
00090 class_overload_destroy ((AvrClass *)spi, spi_intr_destroy);
00091
00092 return spi;
00093 }
00094
00095
00096
00097 void
00098 spi_intr_construct (SPIIntr_T *spi, int addr, char *name)
00099 {
00100 if (spi == NULL)
00101 avr_error ("passed null ptr");
00102
00103 vdev_construct ((VDevice *)spi, spi_intr_read, spi_intr_write,
00104 spi_intr_reset, spii_add_addr);
00105
00106 spii_add_addr ((VDevice *)spi, addr, name, 0, NULL);
00107 spi_intr_reset ((VDevice *)spi);
00108 }
00109
00110 static void
00111 spii_add_addr (VDevice *vdev, int addr, char *name, int rel_addr, void *data)
00112 {
00113 SPIIntr_T *spi = (SPIIntr_T *)vdev;
00114
00115 if (strncmp ("SPCR", name, 4) == 0)
00116 {
00117 spi->spcr_addr = addr;
00118 }
00119
00120 else if (strncmp ("SPSR", name, 4) == 0)
00121 {
00122 spi->spsr_addr = addr;
00123 }
00124
00125 else
00126 {
00127 avr_error ("invalid ADC register name: '%s' @ 0x%04x", name, addr);
00128 }
00129 }
00130
00131
00132
00133 void
00134 spi_intr_destroy (void *spi)
00135 {
00136 if (spi == NULL)
00137 return;
00138
00139 vdev_destroy (spi);
00140 }
00141
00142 static uint8_t
00143 spi_intr_read (VDevice *dev, int addr)
00144 {
00145 SPIIntr_T *spi = (SPIIntr_T *)dev;
00146
00147 if (addr == spi->spcr_addr)
00148 {
00149 return (spi->spcr);
00150 }
00151
00152 else if (addr == spi->spsr_addr)
00153 {
00154 if (spi->spsr & mask_SPIF)
00155 spi->spsr_read |= mask_SPIF;
00156 if (spi->spsr & mask_WCOL)
00157 spi->spsr_read |= mask_WCOL;
00158 return (spi->spsr);
00159 }
00160
00161 else
00162 {
00163 avr_error ("Bad address: 0x%04x", addr);
00164 }
00165
00166 return 0;
00167 }
00168
00169 static void
00170 spi_intr_write (VDevice *dev, int addr, uint8_t val)
00171 {
00172 SPIIntr_T *spi = (SPIIntr_T *)dev;
00173 CallBack *cb;
00174
00175 if (addr == spi->spcr_addr)
00176 {
00177 spi->spcr = val;
00178 if (spi->spcr & mask_SPE)
00179 {
00180
00181 cb = callback_new (spi_intr_cb, (AvrClass *)spi);
00182 spi->intr_cb = cb;
00183 avr_core_async_cb_add ((AvrCore *)vdev_get_core (dev), cb);
00184 }
00185 else
00186 {
00187 spi->intr_cb = NULL;
00188
00189 }
00190 }
00191
00192 else
00193 {
00194 avr_error ("Bad address: 0x%04x", addr);
00195 }
00196 }
00197
00198 static void
00199 spi_intr_reset (VDevice *dev)
00200 {
00201 SPIIntr_T *spi = (SPIIntr_T *)dev;
00202
00203 spi->intr_cb = NULL;
00204
00205 spi->spcr = 0;
00206 spi->spsr = 0;
00207 spi->spsr_read = 0;
00208 }
00209
00210 static int
00211 spi_intr_cb (uint64_t time, AvrClass *data)
00212 {
00213 SPIIntr_T *spi = (SPIIntr_T *)data;
00214
00215 if (spi->intr_cb == NULL)
00216 return CB_RET_REMOVE;
00217
00218 if ((spi->spcr & mask_SPE) && (spi->spcr & mask_SPIE)
00219 && (spi->spsr & mask_SPIF))
00220 {
00221
00222 AvrCore *core = (AvrCore *)vdev_get_core ((VDevice *)spi);
00223 avr_core_irq_raise (core, irq_vect_table_index (SPI_STC));
00224 spi->spsr &= ~mask_SPIF;
00225 spi->spsr = 0;
00226 }
00227
00228 return CB_RET_RETAIN;
00229 }
00230
00231
00232
00233
00234
00235
00236
00237 static void spi_add_addr (VDevice *vdev, int addr, char *name, int rel_addr,
00238 void *data);
00239 static uint8_t spi_read (VDevice *dev, int addr);
00240 static void spi_write (VDevice *dev, int addr, uint8_t val);
00241 static void spi_reset (VDevice *dev);
00242 static int spi_clk_incr_cb (uint64_t ck, AvrClass *data);
00243
00244
00245
00246 VDevice *
00247 spi_create (int addr, char *name, int rel_addr, void *data)
00248 {
00249 return (VDevice *)spi_new (addr, name, rel_addr);
00250 }
00251
00252 SPI_T *
00253 spi_new (int addr, char *name, int rel_addr)
00254 {
00255 SPI_T *spi;
00256
00257 spi = avr_new (SPI_T, 1);
00258 spi_construct (spi, addr, name, rel_addr);
00259 class_overload_destroy ((AvrClass *)spi, spi_destroy);
00260
00261 return spi;
00262 }
00263
00264
00265
00266 void
00267 spi_construct (SPI_T *spi, int addr, char *name, int rel_addr)
00268 {
00269 if (spi == NULL)
00270 avr_error ("passed null ptr");
00271
00272 vdev_construct ((VDevice *)spi, spi_read, spi_write, spi_reset,
00273 spi_add_addr);
00274
00275 spi_add_addr ((VDevice *)spi, addr, name, 0, NULL);
00276 if (rel_addr)
00277 spi->rel_addr = rel_addr;
00278 spi_reset ((VDevice *)spi);
00279 }
00280
00281 static void
00282 spi_add_addr (VDevice *vdev, int addr, char *name, int ref_addr, void *data)
00283 {
00284 SPI_T *spi = (SPI_T *)vdev;
00285
00286 if (strncmp ("SPDR", name, 4) == 0)
00287 {
00288 spi->spdr_addr = addr;
00289 }
00290
00291 else
00292 {
00293 avr_error ("invalid SPI register name: '%s' @ 0x%04x", name, addr);
00294 }
00295 }
00296
00297
00298
00299 void
00300 spi_destroy (void *spi)
00301 {
00302 if (spi == NULL)
00303 return;
00304
00305 vdev_destroy (spi);
00306 }
00307
00308 static uint8_t
00309 spi_read (VDevice *dev, int addr)
00310 {
00311 SPI_T *spi = (SPI_T *)dev;
00312 SPIIntr_T *spi_ti;
00313
00314 spi_ti =
00315 (SPIIntr_T *)avr_core_get_vdev_by_addr ((AvrCore *)
00316 vdev_get_core ((VDevice *)
00317 spi),
00318 spi->rel_addr);
00319
00320 if (addr == spi->spdr_addr)
00321 {
00322 if (spi_ti->spsr_read)
00323 {
00324 spi_ti->spsr &= ~spi_ti->spsr_read;
00325 spi_ti->spsr_read = 0;
00326 }
00327 return spi->spdr;
00328
00329 }
00330
00331 else
00332 {
00333 avr_error ("Bad address: 0x%04x", addr);
00334 }
00335
00336 return 0;
00337 }
00338
00339 static void
00340 spi_write (VDevice *dev, int addr, uint8_t val)
00341 {
00342 SPI_T *spi = (SPI_T *)dev;
00343 CallBack *cb;
00344 SPIIntr_T *spi_ti;
00345
00346 spi_ti =
00347 (SPIIntr_T *)avr_core_get_vdev_by_addr ((AvrCore *)
00348 vdev_get_core ((VDevice *)
00349 spi),
00350 spi->rel_addr);
00351
00352 if (addr == spi->spdr_addr)
00353 {
00354 if (spi_ti->spsr_read)
00355 {
00356 spi_ti->spsr &= ~spi_ti->spsr_read;
00357 spi_ti->spsr_read = 0;
00358 }
00359
00360 if (spi->tcnt != 0)
00361 {
00362 spi_ti->spsr |= mask_WCOL;
00363 }
00364
00365 spi->spdr = val;
00366
00367
00368
00369
00370
00371
00372 switch ((spi_ti->spcr) & (mask_SPR0 | mask_SPR1))
00373 {
00374 case SPI_CK_4:
00375 spi->divisor = 4;
00376 break;
00377 case SPI_CK_16:
00378 spi->divisor = 16;
00379 break;
00380 case SPI_CK_64:
00381 spi->divisor = 64;
00382 break;
00383 case SPI_CK_128:
00384 spi->divisor = 128;
00385 break;
00386 default:
00387 avr_error ("The impossible happened!");
00388 }
00389
00390
00391 if (spi->clk_cb == NULL)
00392 {
00393 cb = callback_new (spi_clk_incr_cb, (AvrClass *)spi);
00394 spi->clk_cb = cb;
00395 avr_core_clk_cb_add ((AvrCore *)vdev_get_core ((VDevice *)spi),
00396 cb);
00397 }
00398 spi->tcnt = 8;
00399 spi->spdr_in = spi_port_rd (addr);
00400 }
00401 else
00402 {
00403 avr_error ("Bad address: 0x%04x", addr);
00404 }
00405 }
00406
00407 static void
00408 spi_reset (VDevice *dev)
00409 {
00410 SPI_T *spi = (SPI_T *)dev;
00411
00412 spi->clk_cb = NULL;
00413
00414 spi->spdr = 0;
00415 spi->tcnt = 0;
00416
00417 spi->divisor = 0;
00418 }
00419
00420 static int
00421 spi_clk_incr_cb (uint64_t ck, AvrClass *data)
00422 {
00423 SPI_T *spi = (SPI_T *)data;
00424 uint8_t last = spi->tcnt;
00425 SPIIntr_T *spi_ti;
00426
00427 spi_ti =
00428 (SPIIntr_T *)avr_core_get_vdev_by_addr ((AvrCore *)
00429 vdev_get_core ((VDevice *)
00430 spi),
00431 spi->rel_addr);
00432
00433 if (spi->clk_cb == NULL)
00434 return CB_RET_REMOVE;
00435
00436 if (spi->divisor <= 0)
00437 avr_error ("Bad divisor value: %d", spi->divisor);
00438
00439
00440
00441
00442 spi->tcnt -= ((ck & (spi->divisor - 1)) == 0);
00443
00444 if (spi->tcnt != last)
00445 {
00446 if (spi->tcnt == 0)
00447 {
00448 spi_ti->spsr |= mask_SPIF;
00449
00450 spi_port_wr (spi->spdr);
00451 spi->spdr = spi->spdr_in;
00452
00453 spi->clk_cb = NULL;
00454 return CB_RET_REMOVE;
00455 }
00456 }
00457
00458 return CB_RET_RETAIN;
00459 }
00460
00461
00462
00463
00464 uint8_t
00465 spi_port_rd (int addr)
00466 {
00467 int data;
00468 char line[80];
00469
00470 while (1)
00471 {
00472 fprintf (stderr,
00473 "\nEnter a byte of hex data to read into the SPI at"
00474 " address 0x%04x: ", addr);
00475
00476
00477 if (fgets (line, sizeof (line), stdin) == NULL)
00478 continue;
00479
00480
00481 if (sscanf (line, "%x\n", &data) != 1)
00482 continue;
00483
00484 break;
00485 }
00486
00487 return (uint8_t) (data & 0xff);
00488 }
00489
00490 void
00491 spi_port_wr (uint8_t val)
00492 {
00493 fprintf (stderr, "wrote 0x%02x to SPI\n", val);
00494 }