Xmega Application Note


spi_driver.c

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