C51 COMPILER V7.05 L1C8051 10/08/2005 13:53:10 PAGE 1 C51 COMPILER V7.05, COMPILATION OF MODULE L1C8051 OBJECT MODULE PLACED IN L1C8051.OBJ COMPILER INVOKED BY: C:\Disk2\SiLabs\MCU\IDEfiles\C51\BIN\C51.exe L1C8051.c DB OE stmt level source 1 //----------------------------------------------------------------------------- 2 // L1C8051.c 3 //----------------------------------------------------------------------------- 4 // L1 SPI to USB interface 5 // The SPI interface is configured in 3-wire master mode 6 // 7 // Port usage: 8 // P0.0 SPI SCK, out 9 // P0.1 SPI MISO, in 10 // P0.2 SPI MOSI, out 11 // P0.3 Slave reset, in 12 // P0.4 INT0, in 13 // P0.5 L1ResetOut, out 14 // P0.6 Slave reset, out 15 // 16 // P1.7 Analogue, in 17 // 18 // P2.2 LED1 19 // P2.3 LED2 20 // 21 //----------------------------------------------------------------------------- 22 // Includes 23 //----------------------------------------------------------------------------- 24 #include 25 #include 26 #include "USB_API.h" 27 #include "l1c8051.h" 28 29 //----------------------------------------------------------------------------- 30 // Global CONSTANTS 31 //----------------------------------------------------------------------------- 32 33 sbit PINT0 = P0 ^ 4; 34 sbit SPISlaveResetOut = P0^6; // Assert to reset slave 35 sbit SPISlaveResetIn_b = P0^3; // ='1' when slave is ready 36 sbit Led1 = P2^2; // LED='1' means OFF 37 sbit Led2 = P2^3; 38 sbit P20 = P2^0; 39 sbit P21 = P2^1; 40 sbit L1ResetOut = P0^5; // Fast DAQ reset 41 42 code const BYTE VendorString[] = {0x2a,0x03,'C',0,'a',0,'v',0,'e',0,'n',0,'d',0,'i',0,'s',0,'h',0,' ',0,'L -',0,'a',0,'b',0,'.',0,' ',0,'(',0,'H',0,'E',0,'P',0,')',0}; 43 code const BYTE ProductString[] = {0x12,0x03,'L',0,'1',0,' ',0,'R',0,'e',0,'v',0,' ',0,'3',0}; 44 // Serial[] is the USB serial number used in enumeration 45 code const BYTE Serial[] = {0x0A,0x03,'0',0,'0',0,'0',0,'3',0}; 46 // serialNumber and ipoffset are loaded into slave register 31 on 47 // reset. The two highest IP octets are hard-coded in the FPGA. The two 48 // low octets are computed as (ipoffset + serialNumber)&0x7f 49 code const BYTE serialNumber = 3; 50 code const unsigned short ipoffset = 0x210; 51 code const BYTE MaxPower = 15; // Max current = 16 mA (8 * 2) 52 code const BYTE PwAttributes = 0x80; // Self-powered, remote wakeup not supported 53 code const UINT bcdDevice = 0x100; // Device release number 1.00 54 C51 COMPILER V7.05 L1C8051 10/08/2005 13:53:10 PAGE 2 55 code const unsigned char maxRegisters = 32; 56 57 unsigned short nByte; 58 devicePacket_t packet; 59 devicePacketISR_t packet_isr; 60 unsigned char rxInterrupt = 0; 61 //unsigned char txInterrupt = 0; 62 unsigned char int0_pending = 0; 63 unsigned char resetRequest = 0; 64 unsigned char waitUSB = 1; 65 unsigned short seq = 0; 66 unsigned char txSlots[2] = {0}; 67 unsigned char nextSlot = 0; 68 unsigned char nextSlotISR = 0; 69 70 //----------------------------------------------------------------------------- 71 // Main Routine 72 //----------------------------------------------------------------------------- 73 void main(void) 74 { 75 1 unsigned rc; 76 1 unsigned char txPending = 0; 77 1 unsigned char registerId; 78 1 unsigned char dummy; 79 1 unsigned char byteNumber; 80 1 BYTE cmd; 81 1 unsigned char writeMode; 82 1 unsigned short iplow16; 83 1 84 1 PCA0MD &= ~0x40; // Disable Watchdog timer 85 1 86 1 USB_Init(0xCBCB,0x0003,VendorString,ProductString,Serial,MaxPower,PwAttributes,bcdDevice); 87 1 OSCICN |= 0x3; // System clock divide. Set for fastest system clock speed. 88 1 Initialize(); 89 1 USB_Int_Enable(); 90 1 91 1 Led1 = 1; 92 1 Led2 = 1; 93 1 94 1 // Wait for the USB to be ready 95 1 96 1 while ( waitUSB == 1 ) ; 97 1 98 1 while ( SPISlaveResetIn_b == 0 ) ; // Wait until the slave is ready 99 1 100 1 Led1 = 0; 101 1 102 1 // All USB packets to the host have 64 byte payload 103 1 104 1 packet.length.uc[0] = 64; 105 1 packet.length.uc[1] = 0; 106 1 107 1 // Continuous transaction loop 108 1 109 1 while ( 1 ) 110 1 { 111 2 112 2 L1ResetOut = 0; 113 2 SPISlaveResetOut = 1; 114 2 while ( SPISlaveResetIn_b == 1 ) ; // Wait until the slave is reset 115 2 SPISlaveResetOut = 0; 116 2 while ( SPISlaveResetIn_b == 0 ) ; // Wait until the slave is ready C51 COMPILER V7.05 L1C8051 10/08/2005 13:53:10 PAGE 3 117 2 118 2 resetRequest = 0; 119 2 120 2 // Cause an initial configuration message to be sent containing the 121 2 // board serial number and IP source address. 122 2 123 2 iplow16 = 0x7fff & (ipoffset + serialNumber); 124 2 packet_isr.cmd = ConfigurationData; 125 2 packet_isr.cdata[0] = 31; 126 2 packet_isr.cdata[3] = 0x80 | (iplow16>>8); 127 2 packet_isr.cdata[2] = 0xff & iplow16; 128 2 rxInterrupt = 1; 129 2 130 2 while ( (SPISlaveResetOut == 0) && (resetRequest == 0) ) // Jump out when the reset is asserted (from IS -R) 131 2 { 132 3 133 3 if ( int0_pending == 1 ) 134 3 { 135 4 int0_pending = 0; 136 4 packet.cmd = Int0; 137 4 138 4 txPending = 1; 139 4 } 140 3 141 3 if ( (txPending == 1) && (txSlots[nextSlot] == 0) ) 142 3 { 143 4 txSlots[nextSlot] = 1; 144 4 nextSlot ^= 0x1; 145 4 rc = Block_Write( (BYTE *)&packet, 68 ); 146 4 txPending = 0; // Transmit packet queued 147 4 } 148 3 149 3 if ( rxInterrupt == 1 ) 150 3 { 151 4 rxInterrupt = 0; 152 4 153 4 if ( (packet_isr.cmd == StatusRequest) || (packet_isr.cmd == ConfigurationData) ) 154 4 { 155 5 for ( registerId=0; registerId < maxRegisters; registerId++ ) 156 5 { 157 6 writeMode = (packet_isr.cmd == ConfigurationData) && (registerId == packet_isr.cdata[0]) ? 1 : - 0; 158 6 for ( byteNumber=0; byteNumber < 4; byteNumber++ ) 159 6 { 160 7 161 7 if ( writeMode == 1 ) 162 7 { 163 8 SPI0DAT = registerId | 0x40; // Slave register ID (write) 164 8 } 165 7 else 166 7 { 167 8 SPI0DAT = registerId; // Slave register ID (read) 168 8 } 169 7 while ( SPIF == 0 ); // Wait for transaction end 170 7 SPIF = 0; 171 7 dummy = SPI0DAT; // Should be Idle character 172 7 173 7 SPI0DAT = Idle; // Idle character 174 7 while ( SPIF == 0 ); // Wait for transaction end 175 7 SPIF = 0; 176 7 dummy = SPI0DAT; // Should be echoed register ID C51 COMPILER V7.05 L1C8051 10/08/2005 13:53:10 PAGE 4 177 7 // packet.cdata[2*registerId] = SPI0DAT; // D[0] from slave 178 7 179 7 SPI0DAT = packet_isr.cdata[3]; // D[0] to slave 180 7 while ( SPIF == 0 ); // Wait for transaction end 181 7 SPIF = 0; 182 7 packet.cdata[2*registerId+1] = SPI0DAT; // D[0] from slave 183 7 // dummy = SPI0DAT; // Should be echoed register ID 184 7 185 7 SPI0DAT = packet_isr.cdata[2]; // D[1] to slave 186 7 while ( SPIF == 0 ); // Wait for transaction end 187 7 SPIF = 0; 188 7 packet.cdata[2*registerId] = SPI0DAT; // D[1] from slave 189 7 } 190 6 } 191 5 192 5 // Update also the status from the MCU 193 5 194 5 // packet.cdata[0] = P0; // Port 0 195 5 // packet.cdata[1] = P1; // Port 1 196 5 // packet.cdata[2] = P2; // Port 2 197 5 // packet.cdata[3] = seq++; // Sequence counter 198 5 199 5 packet.cmd = Status; 200 5 201 5 txPending = 1; // Packet is ready for transmission 202 5 } 203 4 204 4 packet_isr.cmd = Idle; 205 4 206 4 } 207 3 else 208 3 { 209 4 SPI0DAT = Idle; 210 4 while ( SPIF == 0 ); // Wait for transaction end 211 4 SPIF = 0; 212 4 cmd = SPI0DAT; 213 4 } 214 3 215 3 216 3 switch ( cmd ) 217 3 { 218 4 case Idle: 219 4 case Idle2: 220 4 break; 221 4 222 4 default: 223 4 break; 224 4 } 225 3 226 3 } 227 2 228 2 } 229 1 } 230 231 //----------------------------------------------------------------------------- 232 // Initialization Subroutines 233 //----------------------------------------------------------------------------- 234 235 //------------------------- 236 // Port_Init 237 //------------------------- 238 // Port Initialization C51 COMPILER V7.05 L1C8051 10/08/2005 13:53:10 PAGE 5 239 // - Configure the Crossbar and GPIO ports for SPI. 240 // Note: open-drain outputs are high-impedance when the corresponding bit in th Pn register is set. 241 // 242 void Port_Init(void) 243 { 244 1 IT01CF = 0x0c; // P0.4 INT0, active high 245 1 IT0 = 0; // INT0 type: 0=level 1=edge sensitive 246 1 EX0 = 0; // Disable INT0 247 1 248 1 // Port 0 249 1 P0MDIN = 0xFF; // P0.0-7 set digital input 250 1 P0MDOUT = 0x65; // P0.0,2,6 set push-pull (SCK,MOSI,L1ResetOut,ResetOut) 251 1 P0 = ~0x65; // Open-drain outputs set high impedance 252 1 // Port 1 253 1 /* 254 1 P1MDIN = 0x7F; // P1.7 set as analog input 255 1 P1MDOUT = 0x00; // P1.0-7 set open-drain 256 1 P1SKIP = 0x80; // P1.7 skipped by crossbar 257 1 P1 = 0xFF; // Open drain outputs set high impedance 258 1 */ 259 1 260 1 P1MDIN = 0xFF; // All digital input 261 1 P1MDOUT = 0xF0; // Upper push pull, lower open drain 262 1 P1 = ~0xF0; // Set lower to high impedance (inputs) 263 1 264 1 // Port 2 265 1 P2MDIN = 0xFF; // P2.0-7 set digital input 266 1 P2MDOUT = 0x0F; // P2.2,3 set push-pull (LEDs) 267 1 P2 = ~0x0F; // Open-drain outputs set high impedance 268 1 269 1 XBR0 = 0x02; // Enable SPI IO 270 1 XBR1 = 0x40; // Enable Crossbar 271 1 } 272 273 // SPI0_Init 274 275 void SPI0_Init(void) 276 { 277 1 SPI0CFG = 0x40; // MSTEN=1, CKPHA=0, CKPOL=0 278 1 SPI0CKR = 0x0; // Max. SPI clock rate = SYSCLK/2 279 1 ESPI0 = 0; // Disable SPI0 interrupt (we do not use it) 280 1 SPI0CN = 0x1; // Enable 281 1 } 282 283 //------------------------- 284 // Suspend_Device 285 //------------------------- 286 // Called when a DEV_SUSPEND interrupt is received. 287 // - Calls USB_Suspend() 288 // 289 void Suspend_Device(void) 290 { 291 1 // Don't disable peripherals. Device is self-powered. 292 1 293 1 USB_Suspend(); // Put the device in suspend state 294 1 } 295 296 //------------------------- 297 // Initialize 298 //------------------------- 299 300 void Initialize(void) C51 COMPILER V7.05 L1C8051 10/08/2005 13:53:10 PAGE 6 301 { 302 1 303 1 SPI0_Init(); // Initialize SPI 304 1 Port_Init(); // Initialize crossbar and GPIO 305 1 306 1 } 307 308 // Int0_ISR 309 // Called on external interrupt. 310 311 void Int0_ISR(void) interrupt 0 312 { 313 1 int0_pending = 1; 314 1 EX0 = 0; 315 1 } 316 317 318 // USB ISR 319 320 void USB_Device_ISR(void) interrupt 16 321 { 322 1 BYTE INTVAL = Get_Interrupt_Source(); 323 1 324 1 if (INTVAL & RX_COMPLETE) 325 1 { 326 2 Block_Read( (BYTE *)&packet_isr, 8 ); 327 2 switch ( packet_isr.cmd ) 328 2 { 329 3 case StatusRequest: // Status request. 330 3 case ConfigurationData: // Update config register 331 3 rxInterrupt = 1; 332 3 break; 333 3 case PIOWrite: // Write to port 1,2 334 3 // Make sure lower (open drain) input bits are forced to high-Z 335 3 P1 = packet_isr.cdata[1] | 0xf; 336 3 // P2 = packet_isr.cdata[2]; 337 3 break; 338 3 case Int0Enable: 339 3 EX0 = 1; 340 3 break; 341 3 case Int0Disable: 342 3 EX0 = 0; 343 3 break; 344 3 case ResetRequest: 345 3 resetRequest = 1; 346 3 break; 347 3 case L1ResetRequest: 348 3 L1ResetOut = 1; 349 3 L1ResetOut = 0; 350 3 break; 351 3 default: 352 3 break; 353 3 } 354 2 355 2 } 356 1 357 1 if (INTVAL & TX_COMPLETE) 358 1 { 359 2 if ( txSlots[nextSlotISR] == 1 ) 360 2 { 361 3 txSlots[nextSlotISR] = 0; 362 3 nextSlotISR ^= 0x1; C51 COMPILER V7.05 L1C8051 10/08/2005 13:53:10 PAGE 7 363 3 } 364 2 } 365 1 366 1 if (INTVAL & DEV_SUSPEND) 367 1 { 368 2 Suspend_Device(); 369 2 } 370 1 371 1 if (INTVAL & DEV_CONFIGURED) 372 1 { 373 2 waitUSB = 0; 374 2 // Initialize(); 375 2 } 376 1 377 1 } MODULE INFORMATION: STATIC OVERLAYABLE CODE SIZE = 601 ---- CONSTANT SIZE = 78 ---- XDATA SIZE = ---- ---- PDATA SIZE = ---- ---- DATA SIZE = 92 5 IDATA SIZE = ---- ---- BIT SIZE = ---- ---- END OF MODULE INFORMATION. C51 COMPILATION COMPLETE. 0 WARNING(S), 0 ERROR(S)