Xmega Application Note


spi_driver.c
Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00070 #include "spi_driver.h"
00071 
00072 
00073 
00090 void SPI_MasterInit(SPI_Master_t *spi,
00091                     SPI_t *module,
00092                     PORT_t *port,
00093                     bool lsbFirst,
00094                     SPI_MODE_t mode,
00095                     SPI_INTLVL_t intLevel,
00096                     bool clk2x,
00097                     SPI_PRESCALER_t clockDivision)
00098 {
00099         spi->module         = module;
00100         spi->port           = port;
00101         spi->interrupted    = false;
00102 
00103         spi->module->CTRL   = clockDivision |                  /* SPI prescaler. */
00104                               (clk2x ? SPI_CLK2X_bm : 0) |     /* SPI Clock double. */
00105                               SPI_ENABLE_bm |                  /* Enable SPI module. */
00106                               (lsbFirst ? SPI_DORD_bm  : 0) |  /* Data order. */
00107                               SPI_MASTER_bm |                  /* SPI master. */
00108                               mode;                            /* SPI mode. */
00109 
00110         /* Interrupt level. */
00111         spi->module->INTCTRL = intLevel;
00112 
00113         /* No assigned data packet. */
00114         spi->dataPacket = NULL;
00115 
00116         /* MOSI and SCK as output. */
00117         spi->port->DIRSET  = SPI_MOSI_bm | SPI_SCK_bm;
00118 }
00119 
00120 
00121 
00135 void SPI_SlaveInit(SPI_Slave_t *spi,
00136                    SPI_t *module,
00137                    PORT_t *port,
00138                    bool lsbFirst,
00139                    SPI_MODE_t mode,
00140                    SPI_INTLVL_t intLevel)
00141 {
00142         /* SPI module. */
00143         spi->module       = module;
00144         spi->port         = port;
00145 
00146         spi->module->CTRL = SPI_ENABLE_bm |                /* Enable SPI module. */
00147                             (lsbFirst ? SPI_DORD_bm : 0) | /* Data order. */
00148                             mode;                          /* SPI mode. */
00149 
00150         /* Interrupt level. */
00151         spi->module->INTCTRL = intLevel;
00152 
00153         /* MISO as output. */
00154         spi->port->DIRSET = SPI_MISO_bm;
00155 }
00156 
00157 
00158 
00176 void SPI_MasterCreateDataPacket(SPI_DataPacket_t *dataPacket,
00177                                 const uint8_t *transmitData,
00178                                 uint8_t *receiveData,
00179                                 uint8_t bytesToTransceive,
00180                                 PORT_t *ssPort,
00181                                 uint8_t ssPinMask)
00182 {
00183         dataPacket->ssPort            = ssPort;
00184         dataPacket->ssPinMask         = ssPinMask;
00185         dataPacket->transmitData      = transmitData;
00186         dataPacket->receiveData       = receiveData;
00187         dataPacket->bytesToTransceive  = bytesToTransceive;
00188         dataPacket->bytesTransceived   = 0;
00189         dataPacket->complete          = false;
00190 }
00191 
00192 
00193 
00202 void SPI_MasterInterruptHandler(SPI_Master_t *spi)
00203 {
00204         uint8_t data;
00205         uint8_t bytesTransceived = spi->dataPacket->bytesTransceived;
00206 
00207         /* If SS pin interrupt (SS used and pulled low).
00208         *  No data received at this point. */
00209         if ( !(spi->module->CTRL & SPI_MASTER_bm) ) {
00210                 spi->interrupted = true;
00211         }
00212 
00213         else {  /* Data interrupt. */
00214 
00215                 /* Store received data. */
00216                 data = spi->module->DATA;
00217                 spi->dataPacket->receiveData[bytesTransceived] = data;
00218 
00219                 /* Next byte. */
00220                 bytesTransceived++;
00221 
00222                 /* If more data. */
00223                 if (bytesTransceived < spi->dataPacket->bytesToTransceive) {
00224                         /* Put data byte in transmit data register. */
00225                         data = spi->dataPacket->transmitData[bytesTransceived];
00226                         spi->module->DATA = data;
00227                 }
00228 
00229                 /* Transmission complete. */
00230                 else {
00231 
00232                         /* Release SS to slave(s). */
00233                         uint8_t ssPinMask = spi->dataPacket->ssPinMask;
00234                         SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask);
00235 
00236                         spi->dataPacket->complete = true;
00237                 }
00238         }
00239         /* Write back bytesTransceived to data packet. */
00240         spi->dataPacket->bytesTransceived = bytesTransceived;
00241 }
00242 
00243 
00244 
00258 uint8_t SPI_MasterInterruptTransceivePacket(SPI_Master_t *spi,
00259                                             SPI_DataPacket_t *dataPacket)
00260 {
00261         uint8_t data;
00262         bool interrupted = spi->interrupted;
00263 
00264         /* If no packets sent so far. */
00265         if (spi->dataPacket == NULL) {
00266                 spi->dataPacket = dataPacket;
00267         }
00268 
00269         /* If ongoing transmission. */
00270         else if (spi->dataPacket->complete == false) {
00271                 return (SPI_BUSY);
00272         }
00273 
00274         /* If interrupted by other master. */
00275         else if (interrupted) {
00276                 /* If SS released. */
00277                 if (spi->port->OUT & SPI_SS_bm) {
00278                         /* No longer interrupted. */
00279                         interrupted = false;
00280                 }
00281                 else {
00282                         return (SPI_INTERRUPTED);
00283                 }
00284         }
00285 
00286         /* NOT interrupted by other master.
00287         * Start transmission. */
00288         spi->dataPacket = dataPacket;
00289         spi->dataPacket->complete = false;
00290         spi->interrupted = false;
00291 
00292         /* SS to slave(s) low.*/
00293         uint8_t ssPinMask = spi->dataPacket->ssPinMask;
00294         SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask);
00295 
00296         spi->dataPacket->bytesTransceived = 0;
00297 
00298         /* Start sending data. */
00299         data = spi->dataPacket->transmitData[0];
00300         spi->module->DATA = data;
00301 
00302         /* Successs */
00303         return (SPI_OK);
00304 }
00305 
00306 
00327 uint8_t SPI_MasterTransceiveByte(SPI_Master_t *spi, uint8_t TXdata)
00328 {
00329         /* Send pattern. */
00330         spi->module->DATA = TXdata;
00331 
00332         /* Wait for transmission complete. */
00333         while(!(spi->module->STATUS & SPI_IF_bm)) {
00334 
00335         }
00336         /* Read received data. */
00337         uint8_t result = spi->module->DATA;
00338 
00339         return(result);
00340 }
00341 
00342 
00343 
00357 bool SPI_MasterTransceivePacket(SPI_Master_t *spi,
00358                                 SPI_DataPacket_t *dataPacket)
00359 {
00360         /* Check if data packet has been created. */
00361         if(dataPacket == NULL) {
00362                 return false;
00363         }
00364 
00365         /* Assign datapacket to SPI module. */
00366         spi->dataPacket = dataPacket;
00367 
00368         uint8_t ssPinMask = spi->dataPacket->ssPinMask;
00369 
00370         /* If SS signal to slave(s). */
00371         if (spi->dataPacket->ssPort != NULL) {
00372                 /* SS to slave(s) low. */
00373                 SPI_MasterSSLow(spi->dataPacket->ssPort, ssPinMask);
00374         }
00375 
00376         /* Transceive bytes. */
00377         uint8_t bytesTransceived = 0;
00378         uint8_t bytesToTransceive = dataPacket->bytesToTransceive;
00379         while (bytesTransceived < bytesToTransceive) {
00380 
00381                 /* Send pattern. */
00382                 uint8_t data = spi->dataPacket->transmitData[bytesTransceived];
00383                 spi->module->DATA = data;
00384 
00385                 /* Wait for transmission complete. */
00386                 while(!(spi->module->STATUS & SPI_IF_bm)) {
00387 
00388                 }
00389                 /* Read received data. */
00390                 data = spi->module->DATA;
00391                 spi->dataPacket->receiveData[bytesTransceived] = data;
00392 
00393                 bytesTransceived++;
00394         }
00395 
00396         /* If SS signal to slave(s). */
00397         if (spi->dataPacket->ssPort != NULL) {
00398                 /* Release SS to slave(s). */
00399                 SPI_MasterSSHigh(spi->dataPacket->ssPort, ssPinMask);
00400         }
00401 
00402         /* Set variables to indicate that transmission is complete. */
00403         spi->dataPacket->bytesTransceived = bytesTransceived;
00404         spi->dataPacket->complete = true;
00405 
00406         /* Report success. */
00407         return true;
00408 }