![]() |
Wixel SDK
|
00001 00006 #include <cc2511_map.h> 00007 #include <cc2511_types.h> 00008 00009 #if defined(__CDT_PARSER__) 00010 #define SPI0 00011 #endif 00012 00013 #if defined(SPI0) 00014 #include <spi0_master.h> 00015 #define INTERRUPT_PRIORITY_GROUP 2 00016 #define ISR_URX() ISR(URX0, 0) 00017 #define URXNIF URX0IF 00018 #define URXNIE URX0IE 00019 #define UNGCR U0GCR 00020 #define UNBAUD U0BAUD 00021 #define UNDBUF U0DBUF 00022 #define spiNMasterInit spi0MasterInit 00023 #define spiNMasterSetFrequency spi0MasterSetFrequency 00024 #define spiNMasterSetClockPolarity spi0MasterSetClockPolarity 00025 #define spiNMasterSetClockPhase spi0MasterSetClockPhase 00026 #define spiNMasterSetBitOrder spi0MasterSetBitOrder 00027 #define spiNMasterBusy spi0MasterBusy 00028 #define spiNMasterBytesLeft spi0MasterBytesLeft 00029 #define spiNMasterTransfer spi0MasterTransfer 00030 #define spiNMasterSendByte spi0MasterSendByte 00031 #define spiNMasterReceiveByte spi0MasterReceiveByte 00032 00033 #elif defined(SPI1) 00034 #include <spi1_master.h> 00035 #define INTERRUPT_PRIORITY_GROUP 3 00036 #define ISR_URX() ISR(URX1, 0) 00037 #define URXNIF URX1IF 00038 #define URXNIE URX1IE 00039 #define UNGCR U1GCR 00040 #define UNBAUD U1BAUD 00041 #define UNDBUF U1DBUF 00042 #define spiNMasterInit spi1MasterInit 00043 #define spiNMasterSetFrequency spi1MasterSetFrequency 00044 #define spiNMasterSetClockPolarity spi1MasterSetClockPolarity 00045 #define spiNMasterSetClockPhase spi1MasterSetClockPhase 00046 #define spiNMasterSetBitOrder spi1MasterSetBitOrder 00047 #define spiNMasterBusy spi1MasterBusy 00048 #define spiNMasterBytesLeft spi1MasterBytesLeft 00049 #define spiNMasterTransfer spi1MasterTransfer 00050 #define spiNMasterSendByte spi1MasterSendByte 00051 #define spiNMasterReceiveByte spi1MasterReceiveByte 00052 #endif 00053 00054 // txPointer points to the last byte that was written to SPI. 00055 static volatile const uint8 XDATA * DATA txPointer = 0; 00056 00057 // rxPointer points to the location to store the next byte received from SPI. 00058 static volatile uint8 XDATA * DATA rxPointer = 0; 00059 00060 // bytesLeft is the number of bytes we still need to send to/receive from SPI. 00061 static volatile uint16 DATA bytesLeft = 0; 00062 00063 void spiNMasterInit(void) 00064 { 00065 /* From datasheet Table 50 */ 00066 00067 /* USART0 SPI Alt. 1: 00068 * SCK = P0_5 00069 * MOSI = P0_3 00070 * MISO = P0_2 00071 */ 00072 00073 /* USART1 SPI Alt. 2: 00074 * SCK = P1_5 00075 * MOSI = P1_6 00076 * MISO = P1_7 00077 */ 00078 00079 /* 12.14.2.1: In SPI master mode, only the MOSI, MISO, and SCK should be 00080 * configured as peripherals (see Section 12.4.6.1 and Section 12.4.6.2). If 00081 * the external slave requires a slave select signal (SSN) this can be 00082 * implemented by using a general-purpose I/O pin and control from SW. 00083 */ 00084 00085 // Note: We do NOT set the mode of the RX pin to "peripheral function" 00086 // because that seems to have no benefits, and is actually bad because 00087 // it disables the internal pull-up resistor. 00088 00089 #ifdef SPI0 00090 P2DIR &= ~0xC0; // P2DIR.PRIP0 (7:6) = 00 : USART0 takes priority over USART1. 00091 PERCFG &= ~0x01; // PERCFG.U0CFG (0) = 0 (Alt. 1) : USART0 uses alt. location 1. 00092 #else 00093 P2SEL |= 0x40; // USART1 takes priority over USART0 on Port 1. 00094 PERCFG |= 0x02; // PERCFG.U1CFG (1) = 1 (Alt. 2) : USART1 uses alt. location 2. 00095 #endif 00096 00097 // Assumption: The MODE and SLAVE bits in U0CSR/U1CSR are 0 (the default) so 00098 // the USART is already in SPI Master mode. 00099 00100 // Set the mode of the SCK and MOSI pins to "peripheral function". 00101 #ifdef SPI0 00102 P0SEL |= ((1<<5) | (1<<3)); // P0SEL.SELP0_5 = 1, P0SEL.SELP0_3 = 1 00103 #else 00104 P1SEL |= ((1<<5) | (1<<6)); // P1SEL.SELP1_5 = 1, P1SEL.SELP1_6 = 1 00105 #endif 00106 00107 // Below, we set the priority of the RX and TX interrupts to be 1 (second lowest priority). 00108 // They need to be higher than the RF interrupt because that one could take a long time. 00109 // The SPI0 interrupts are grouped with the T2 interrupt, so its priority also gets set. 00110 // The SPI1 interrupts are grouped with the T3 interrupts, so its priority also gets set. 00111 IP0 |= (1<<INTERRUPT_PRIORITY_GROUP); 00112 IP1 &= ~(1<<INTERRUPT_PRIORITY_GROUP); 00113 00114 URXNIF = 0; // Clear RX flag. 00115 EA = 1; // Enable interrupts in general. 00116 } 00117 00118 void spiNMasterSetFrequency(uint32 freq) 00119 { 00120 uint32 baudMPlus256; 00121 uint8 baudE = 0; 00122 00123 // max baud rate is 3000000 (F/8); min is 23 (baudM = 1) 00124 if (freq < 23 || freq > 3000000) 00125 return; 00126 00127 // 495782 is the largest value that will not overflow the following calculation 00128 while (freq > 495782) 00129 { 00130 baudE++; 00131 freq /= 2; 00132 } 00133 00134 // calculate baud rate - see datasheet 12.14.3 00135 // this is derived from (baudM + 256) = baud * 2^28 / 24000000 00136 baudMPlus256 = (freq * 11) + (freq * 8663 / 46875); 00137 00138 // get baudMPlus256 into the range 256-511 (so BAUD_M is in the range 0-255) 00139 while (baudMPlus256 > 0x1ff) 00140 { 00141 baudE++; 00142 baudMPlus256 /= 2; 00143 } 00144 UNGCR &= 0xE0; // preserve CPOL, CPHA, ORDER (7:5) 00145 UNGCR |= baudE; // UNGCR.BAUD_E (4:0) 00146 UNBAUD = baudMPlus256; // UNBAUD.BAUD_M (7:0) - only the lowest 8 bits of baudMPlus256 are used, so this is effectively baudMPlus256 - 256 00147 } 00148 00149 void spiNMasterSetClockPolarity(BIT polarity) 00150 { 00151 if (polarity == SPI_POLARITY_IDLE_LOW) 00152 { 00153 UNGCR &= ~(1<<7); // SCK idle low (negative polarity) 00154 } 00155 else 00156 { 00157 UNGCR |= (1<<7); // SCK idle high (positive polarity) 00158 } 00159 } 00160 00161 void spiNMasterSetClockPhase(BIT phase) 00162 { 00163 if (phase == SPI_PHASE_EDGE_LEADING) 00164 { 00165 UNGCR &= ~(1<<6); // data centered on leading (first) edge - rising for idle low, falling for idle high 00166 } 00167 else 00168 { 00169 UNGCR |= (1<<6); // data centered on trailing (second) edge - falling for idle low, rising for idle high 00170 } 00171 } 00172 00173 void spiNMasterSetBitOrder(BIT bitOrder) 00174 { 00175 if (bitOrder == SPI_BIT_ORDER_LSB_FIRST) 00176 { 00177 UNGCR &= ~(1<<5); // LSB first 00178 } 00179 else 00180 { 00181 UNGCR |= (1<<5); // MSB first 00182 } 00183 } 00184 00185 BIT spiNMasterBusy(void) 00186 { 00187 return URXNIE; 00188 } 00189 00190 uint16 spiNMasterBytesLeft(void) 00191 { 00192 uint16 bytes; 00193 00194 // bytesLeft is 16 bits, so it takes more than one instruction to read. Disable interrupts so it's not updated while we do this 00195 URXNIE = 0; 00196 bytes = bytesLeft; 00197 if (bytes) URXNIE = 1; 00198 00199 return bytes; 00200 } 00201 00202 void spiNMasterTransfer(const uint8 XDATA * txBuffer, uint8 XDATA * rxBuffer, uint16 size) 00203 { 00204 if (size) 00205 { 00206 txPointer = txBuffer; 00207 rxPointer = rxBuffer; 00208 bytesLeft = size; 00209 00210 UNDBUF = *txBuffer; // transmit first byte 00211 URXNIE = 1; // Enable RX interrupt. 00212 } 00213 } 00214 00215 uint8 spiNMasterSendByte(uint8 XDATA byte) 00216 { 00217 uint8 XDATA rxByte; 00218 00219 rxPointer = &rxByte; 00220 bytesLeft = 1; 00221 00222 UNDBUF = byte; 00223 URXNIE = 1; // Enable RX interrupt. 00224 00225 while (bytesLeft); 00226 return rxByte; 00227 } 00228 00229 uint8 spiNMasterReceiveByte(void) 00230 { 00231 return spiNMasterSendByte(0xFF); 00232 } 00233 00234 ISR_URX() 00235 { 00236 URXNIF = 0; 00237 00238 *rxPointer = UNDBUF; 00239 rxPointer++; 00240 bytesLeft--; 00241 00242 if (bytesLeft) 00243 { 00244 txPointer++; 00245 UNDBUF = *txPointer; 00246 } 00247 else 00248 { 00249 URXNIE = 0; 00250 } 00251 }
1.7.4