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