int main() { setupDefault(); while(1) { // if(eepromReadByte(0x03, 0x10)) // { // usartSendString(" Received:"); // usartSend(i2c_received_byte); // blinkDbgLed(DBG_LED1); // } // else // { // blinkDbgLed(DBG_LED3); // i2cRecover(); // } if(eepromReadPage(0x03)) { uint8_t itr = 0; while(itr != 0xff) { usartSend(eeprom_page[itr]); itr++; } blinkDbgLed(DBG_LED1); } else { blinkDbgLed(DBG_LED3); i2cRecover(); } usartSendString(" XXXXXX"); } }
int main (void) { initI2C1 (); initUsart (); #if 0 /* * +----------------+ * | Initialization | * +----------------+ */ accelgyro.initialize(); setClockSource(MPU6050_CLOCK_PLL_XGYRO/*0x01*/); /* * Excerpt from domcumentation : Upon power up, the MPU-60X0 clock source defaults to the internal oscillator. * However, it is highly recommended that the device be configured to use one of the gyroscopes. Below is the code * which does it: */ I2Cdev::writeBits(devAddr, MPU6050_RA_PWR_MGMT_1/*0x6B*/, MPU6050_PWR1_CLKSEL_BIT/*2*/, MPU6050_PWR1_CLKSEL_LENGTH/*3*/, source/*MPU6050_CLOCK_PLL_XGYRO 0x01*/); setFullScaleGyroRange(MPU6050_GYRO_FS_250/*0x00*/); /* * 0x1b register is used to trigger gyroscope self-test and configure the gyroscopes’ full scale range. Below * we set ful scale to be +/- 250 units (seconds?) */ I2Cdev::writeBits(devAddr, MPU6050_RA_GYRO_CONFIG/*0x1B*/, MPU6050_GCONFIG_FS_SEL_BIT/*4*/, MPU6050_GCONFIG_FS_SEL_LENGTH/*2*/, range/*0x00*/); setFullScaleAccelRange(MPU6050_ACCEL_FS_2/*0x00*/); /* * Set accelerometer full scale to be +/- 2g. */ I2Cdev::writeBits(devAddr, MPU6050_RA_ACCEL_CONFIG/*0x1C*/, MPU6050_ACONFIG_AFS_SEL_BIT/*4*/, MPU6050_ACONFIG_AFS_SEL_LENGTH/*2*/, range/*0*/); setSleepEnabled(false); // thanks to Jack Elston for pointing this one out! /* * By default MPU6050 is in sleep mode after powering up. Below we are waking it back on. This * is done using the same register as in first line, */ I2Cdev::writeBit(devAddr, MPU6050_RA_PWR_MGMT_1/*0x6B*/, MPU6050_PWR1_SLEEP_BIT/*6*/, enabled/*false*/); accelgyro.testConnection() getDeviceID() == 0x34; /* * This register is used to verify the identity of the device. The contents of WHO_AM_I are * the upper 6 bits of the MPU-60X0’s 7-bit I C address. The Power-On-Reset value of Bit6:Bit1 is 0b110100 == 0x34. */ I2Cdev::readBits(devAddr, MPU6050_RA_WHO_AM_I/*0x75*/, MPU6050_WHO_AM_I_BIT/*6*/, MPU6050_WHO_AM_I_LENGTH/*6*/, buffer); return buffer[0]; /* * +----------------+ * | Main loop | * +----------------+ */ int16_t ax, ay, az; int16_t gx, gy, gz; accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz); /* * In MPU-6000 and MPU-6050 Product Specification Rev 3.3 on pages 36 and 37 we read, that I²C reads and writes * can be performed with single byte or multiple bytes. In single byte mode, we issue (after sending slave * address ofcourse) a register address, and send or receive one byte of data. Multiple byte reads and writes, at the * other hand consist of slave address, regiser address and multiple consecutive bytes od data. Slave puts or gets * first byte from the register with the address we've just sent, and increases this addres by 1 after each byte. * * This is very useful in case of accelerometer and gyroscope because manufacturer has set up the apropriate registers * cnsecutively, so one can read accel, internal temp and gyro data in one read command. Below is the code which does * exactly this: */ I2Cdev::readBytes(devAddr, MPU6050_RA_ACCEL_XOUT_H/*0x3B*/, 14, buffer); *ax = (((int16_t)buffer[0]) << 8) | buffer[1]; *ay = (((int16_t)buffer[2]) << 8) | buffer[3]; *az = (((int16_t)buffer[4]) << 8) | buffer[5]; *gx = (((int16_t)buffer[8]) << 8) | buffer[9]; *gy = (((int16_t)buffer[10]) << 8) | buffer[11]; *gz = (((int16_t)buffer[12]) << 8) | buffer[13]; #endif // Configuration: I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter); // start a transmission in Master transmitter mode I2C_write_slow (I2C1, MPU6050_RA_PWR_MGMT_1); // Register address I2C_write (I2C1, MPU6050_CLOCK_PLL_XGYRO); // Register value = 0x01. Which means, that DEVICE_RESET, SLEEP, CYCLE and TEMP_DIS are all 0. I2C_stop (I2C1); I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter); I2C_write (I2C1, MPU6050_RA_GYRO_CONFIG); I2C_write (I2C1, MPU6050_GYRO_FS_250); // All bits set to zero. I2C_stop (I2C1); I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter); I2C_write (I2C1, MPU6050_RA_ACCEL_CONFIG); I2C_write (I2C1, MPU6050_ACCEL_FS_2); // All bits set to zero. I2C_stop (I2C1); // Simple test if communication is working I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter); I2C_write (I2C1, MPU6050_RA_WHO_AM_I); I2C_stop (I2C1); I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Receiver); uint8_t whoAmI = I2C_read_nack (I2C1); // read one byte and don't request another byte I2C_stop (I2C1); if (whoAmI == 0x34) { usartSendString (USART1, "Accelerometer has been found!\r\n"); } else { usartSendString (USART1, "*NO* Accelerometer has been found!\r\n"); } while (1) { I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Transmitter); I2C_write (I2C1, MPU6050_RA_ACCEL_XOUT_H); I2C_stop (I2C1); I2C_start (I2C1, MPU6050_ADDRESS_AD0_LOW, I2C_Direction_Receiver); uint16_t ax = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1); uint16_t ay = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1); uint16_t az = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1); uint16_t temp = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1); uint16_t gx = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1); uint16_t gy = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_ack (I2C1); uint16_t gz = ((uint16_t)I2C_read_ack (I2C1) << 8) | I2C_read_nack (I2C1); I2C_stop (I2C1); printf ("Accel : (%d, %d, %d), temperature : %d, gyro : (%d, %d, %d)\r\n", ax, ay, az, temp, gx, gy, gz); } }
int receiveCoapMsg(uint8_t* packet, uint16_t port, CoapMsg *coapMsg) { coapMsg->coapHdr = (CoapHdr*) packet; //Receive UDP request from browser coapMsg->coapHdr->udp.destPort = 0; do { GetPacket(UDPPROTOCOL, packet); } while (!(coapMsg->coapHdr->udp.destPort == (uint16_t) HTONS(port))); //Parse Token uint8_t token[coapMsg->coapHdr->tokenLength]; coapMsg->token = token; memcpy(coapMsg->token, packet + sizeof(CoapHdr), coapMsg->coapHdr->tokenLength); //Parse options uint16_t totalLen; //Total UDP packet length totalLen = HTONS(coapMsg->coapHdr->udp.ip.len) + sizeof(EtherNetII) - 2; //-2 Added to make it work with Copper who adds two bytes at the end of the options value uint8_t* inputPtr = packet + sizeof(CoapHdr) + coapMsg->coapHdr->tokenLength; uint8_t* endPtr = packet + totalLen; uint16_t optionNumber = 0; coapMsg->options = (CoapOptions) COAP_OPTIONS_INITIALISATION; while (inputPtr < endPtr && inputPtr[0] != 0xFF) { uint8_t optionByte = inputPtr[0]; uint16_t optionDelta = optionByte >> 4; uint16_t optionLength = optionByte & 0x0F; //Process option delta switch (optionDelta) { case 13: inputPtr++; optionDelta = (*(inputPtr) - 13) & 0xff; break; case 14: inputPtr++; optionDelta = *(inputPtr) - 269; inputPtr++; break; case 15: usartSendString("Error: payload marker detected in option delta\r"); return -1; break; default: break; } //Process option length switch (optionLength) { case 13: inputPtr++; optionLength = (*(inputPtr) - 13) & 0xff; break; case 14: inputPtr++; optionLength = *(inputPtr) - 269; inputPtr++; break; case 15: usartSendString("Error: message format error\r"); return -1; break; default: break; } //Process the option uint8_t *optionValue = ++inputPtr; optionNumber += optionDelta; switch (optionNumber) { case COAP_OPTION_URI_PATH: coapMsg->options.uriPath.optionLength = optionLength; coapMsg->options.uriPath.optionValue = optionValue; break; case COAP_OPTION_CONTENT_FORMAT: coapMsg->options.contentFormat.optionLength = optionLength; coapMsg->options.contentFormat.optionValue = optionValue; case COAP_OPTION_URI_QUERY: coapMsg->options.uriQuery.optionLength = optionLength; coapMsg->options.uriQuery.optionValue = optionValue; case COAP_OPTION_ACCEPT: coapMsg->options.accept.optionLength = optionLength; coapMsg->options.accept.optionValue = optionValue; break; case COAP_OPTION_IF_MATCH: case COAP_OPTION_URI_HOST: case COAP_OPTION_ETAG: case COAP_OPTION_IF_NONE: case COAP_OPTION_URI_PORT: case COAP_OPTION_LOCATION_PATH: case COAP_OPTION_MAX_AGE: case COAP_OPTION_LOCATION_QUERY: case COAP_OPTION_PROXY_URI: case COAP_OPTION_PROXY_SCHEME: case COAP_OPTION_SIZE1: default: usartSendString("Error: Option not supported\r"); return -1; break; } //Update pointer to next option inputPtr += optionLength; } usartSendString("\rCoAP message received OK\r"); return 0; }
void sendCoapMsg(uint8_t* packet, CoapMsg* coapMsg, char *payload) { coapMsg->coapHdr = (CoapHdr*) packet; //Reset options coapMsg->options = (CoapOptions) COAP_OPTIONS_INITIALISATION; //Swap source and destination MAC addresses memcpy(coapMsg->coapHdr->udp.ip.eth.DestAddrs, coapMsg->coapHdr->udp.ip.eth.SrcAddrs, sizeof(deviceMAC)); memcpy(coapMsg->coapHdr->udp.ip.eth.SrcAddrs, deviceMAC, sizeof(deviceMAC)); //Swap source and destination IP addresses memcpy(coapMsg->coapHdr->udp.ip.dest, coapMsg->coapHdr->udp.ip.source, sizeof(deviceIP)); memcpy(coapMsg->coapHdr->udp.ip.source, deviceIP, sizeof(deviceIP)); //Swap ports uint16_t destPort = coapMsg->coapHdr->udp.destPort; coapMsg->coapHdr->udp.destPort = coapMsg->coapHdr->udp.sourcePort; coapMsg->coapHdr->udp.sourcePort = destPort; //Setup CoAP response if (coapMsg->coapHdr->type == COAP_TYPE_CONFIRMABLE) coapMsg->coapHdr->type = COAP_TYPE_ACKNOWLEDGEMENT; coapMsg->coapHdr->code = COAP_CODE_CONTENT; //Payload marker uint8_t ff = 0xFF; printf("Token length: %u\r", coapMsg->coapHdr->tokenLength); memcpy(packet + sizeof(CoapHdr) + coapMsg->coapHdr->tokenLength, &ff, 1); //Payload uint8_t payloadLen = strlen(payload); memcpy(packet + sizeof(CoapHdr) + coapMsg->coapHdr->tokenLength + 1, payload, payloadLen); //Total packet length uint16_t len = sizeof(CoapHdr) + coapMsg->coapHdr->tokenLength + 1 + payloadLen; //Setup UDP packet coapMsg->coapHdr->udp.len = (uint16_t) HTONS((len-sizeof(IPhdr))); coapMsg->coapHdr->udp.ip.len = (uint16_t) HTONS((len-sizeof(EtherNetII))); coapMsg->coapHdr->udp.ip.ident = 0xdeee; //Calculate UDP and IP checksums coapMsg->coapHdr->udp.chksum = 0; coapMsg->coapHdr->udp.ip.chksum = 0; uint16_t pseudochksum = (uint16_t) chksum(UDPPROTOCOL + len - sizeof(IPhdr), coapMsg->coapHdr->udp.ip.source, sizeof(deviceIP) * 2); uint16_t chk1, chk2; chk1 = ~(chksum(pseudochksum, packet + sizeof(IPhdr), len - sizeof(IPhdr))); coapMsg->coapHdr->udp.chksum = (uint16_t) HTONS(chk1); chk2 = ~(chksum(0, packet + sizeof(EtherNetII), sizeof(IPhdr) - sizeof(EtherNetII))); coapMsg->coapHdr->udp.ip.chksum = (uint16_t) HTONS(chk2); //Send packet enc28j60_send_packet(packet, len); usartSendString("\rCoAP message sent OK\r"); }
void printCoapMsg(CoapMsg coapMsg) { int i; //Print type usartSendString("Type: "); switch (coapMsg.coapHdr->type) { case COAP_TYPE_CONFIRMABLE: usartSendString("Confirmable\r"); break; case COAP_TYPE_NON_CONFIRMABLE: usartSendString("Non-confirmable\r"); break; case COAP_TYPE_ACKNOWLEDGEMENT: usartSendString("Acknowledgement\r"); break; case COAP_TYPE_RESET: usartSendString("Reset\r"); break; default: usartSendString("Print error: Type not recognized\r"); break; } //Print code usartSendString("Code: "); switch (coapMsg.coapHdr->code) { case COAP_CODE_EMPTY: usartSendString("EMPTY\r"); break; case COAP_CODE_GET: usartSendString("GET\r"); break; case COAP_CODE_POST: usartSendString("POST\r"); break; case COAP_CODE_PUT: usartSendString("PUT\r"); break; case COAP_CODE_DELETE: usartSendString("DELETE\r"); break; case COAP_CODE_CONTENT: usartSendString("CONTENT\r"); break; default: usartSendString("Print error: Method code not recognized\r"); break; } //Print message ID usartSendString("MID: "); printf("%u\r", (uint16_t) HTONS(coapMsg.coapHdr->msgID)); //Print token if (coapMsg.coapHdr->tokenLength) { usartSendString("Token: "); for (i = 0; i < coapMsg.coapHdr->tokenLength; i++) printf("%u", coapMsg.token[i]); usartSendString("\r"); } //Print options if (coapMsg.options.uriPath.optionLength) { usartSendString("Option: Uri-Path\r"); usartSendString("Option value: "); for (i = 0; i < coapMsg.options.uriPath.optionLength; i++) usartSend8(coapMsg.options.uriPath.optionValue[i]); usartSendString("\r"); } if (coapMsg.options.contentFormat.optionLength) { usartSendString("Option: Content-Format\r"); usartSendString("Option value: "); for (i = 0; i < coapMsg.options.contentFormat.optionLength; i++) printf("%u", coapMsg.options.contentFormat.optionValue[i]); usartSendString("\r"); } if (coapMsg.options.uriQuery.optionLength) { usartSendString("Option: Uri-Query\r"); usartSendString("Option value: "); for (i = 0; i < coapMsg.options.uriQuery.optionLength; i++) printf("%u", coapMsg.options.uriQuery.optionValue[i]); usartSendString("\r"); } if (coapMsg.options.accept.optionLength) { usartSendString("Option: Accept\r"); usartSendString("Option value: "); for (i = 0; i < coapMsg.options.accept.optionLength; i++) printf("%u", coapMsg.options.accept.optionValue[i]); usartSendString("\r"); } }
// Called once at startup // void mainInit(void) { xdata uint8 thisByte = 0xFF; xdata uint16 blockSize; setIntCount = 23; // This is only necessary for cases where you want to load firmware into the RAM of an FX2 that // has already loaded firmware from an EEPROM. It should definitely be removed for firmwares // which are themselves to be loaded from EEPROM. #ifndef EEPROM RENUMERATE_UNCOND(); #endif // Disable alternate functions for PORTA 0,1,3 & 7. PORTACFG = 0x00; // Return FIFO setings back to default just in case previous firmware messed with them. SYNCDELAY; PINFLAGSAB = 0x00; SYNCDELAY; PINFLAGSCD = 0x00; SYNCDELAY; FIFOPINPOLAR = 0x00; // Global settings SYNCDELAY; REVCTL = (bmDYN_OUT | bmENH_PKT); SYNCDELAY; CPUCS = bmCLKSPD1; // 48MHz // Drive IFCLK at 48MHz, enable slave FIFOs //SYNCDELAY; IFCONFIG = (bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmFIFOS); SYNCDELAY; IFCONFIG = (bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmPORTS); // EP4 & EP8 are unused SYNCDELAY; EP4CFG = 0x00; SYNCDELAY; EP8CFG = 0x00; SYNCDELAY; EP4FIFOCFG = 0x00; SYNCDELAY; EP8FIFOCFG = 0x00; // EP1OUT & EP1IN SYNCDELAY; EP1OUTCFG = (bmVALID | bmBULK); SYNCDELAY; EP1INCFG = (bmVALID | bmBULK); // EP2OUT & EP6IN are quad-buffered bulk endpoints SYNCDELAY; EP2CFG = (bmVALID | bmBULK); SYNCDELAY; EP6CFG = (bmVALID | bmBULK | bmDIR); // Reset FIFOs for EP2OUT & EP6IN SYNCDELAY; FIFORESET = bmNAKALL; SYNCDELAY; FIFORESET = 2; // reset EP2OUT SYNCDELAY; FIFORESET = 6; // reset EP6IN SYNCDELAY; FIFORESET = 0x00; // Arm EP1OUT EP1OUTBC = 0x00; // Arm the EP2OUT buffers. Done four times because it's quad-buffered SYNCDELAY; OUTPKTEND = bmSKIP | 2; // EP2OUT SYNCDELAY; OUTPKTEND = bmSKIP | 2; SYNCDELAY; OUTPKTEND = bmSKIP | 2; SYNCDELAY; OUTPKTEND = bmSKIP | 2; // EP2OUT & EP6IN automatically commit packets SYNCDELAY; EP2FIFOCFG = bmAUTOOUT; SYNCDELAY; EP6FIFOCFG = bmAUTOIN; // Auto-commit 512-byte packets from EP6IN (master may commit early by asserting PKTEND) SYNCDELAY; EP6AUTOINLENH = 0x02; SYNCDELAY; EP6AUTOINLENL = 0x00; // Turbo I2C I2CTL |= bm400KHZ; // Auto-pointers AUTOPTRSETUP = bmAPTREN | bmAPTR1INC | bmAPTR2INC; // Port lines all inputs... IOA = 0xFF; OEA = 0x00; IOB = 0xFF; OEB = 0x00; IOC = 0xFF; OEC = 0x00; IOD = 0xFF; OED = 0x00; IOE = 0xFF; OEE = 0x00; #ifdef EEPROM #include "init.inc" #endif #ifdef DEBUG usartInit(); usartSendString("MakeStuff FPGALink/FX2 v1.1\r"); #endif }
// Read "length" bytes from RAM at "buf", and write them to the attached EEPROM at address "addr". // bool promWrite(bool bank, uint16 addr, uint8 length, const __xdata uint8 *buf) { __xdata uint8 i; const __xdata uint8 i2cAddr = bank ? BANK_1 : BANK_0; #ifdef DEBUG usartSendString("promWrite("); usartSendByte(bank?'1':'0'); usartSendByte(','); usartSendWordHex(addr); usartSendByte(','); usartSendWordHex(length); usartSendByte(')'); usartSendByte('\r'); #endif // Wait for I2C idle // while ( I2CS & bmSTOP ); // Send the WRITE command // I2CS = bmSTART; I2DAT = i2cAddr; // Write I2C address byte (WRITE) if ( promWaitForAck() ) { return true; } // Send the address, MSB first // I2DAT = MSB(addr); // Write MSB of address if ( promWaitForAck() ) { return true; } I2DAT = LSB(addr); // Write LSB of address if ( promWaitForAck() ) { return true; } // Write the data // for ( i = 0; i < length; i++ ) { I2DAT = *buf++; if ( promWaitForDone() ) { return true; } } I2CS |= bmSTOP; // Wait for I2C idle // while ( I2CS & bmSTOP ); do { I2CS = bmSTART; I2DAT = i2cAddr; // Write I2C address byte (WRITE) if ( promWaitForDone() ) { return true; } I2CS |= bmSTOP; while ( I2CS & bmSTOP ); } while ( !(I2CS & bmACK) ); return false; }
// Read "length" bytes from address "addr" in the attached EEPROM, and write them to RAM at "buf". // bool promRead(bool bank, uint16 addr, uint8 length, __xdata uint8 *buf) { __xdata uint8 i; const __xdata uint8 i2cAddr = bank ? BANK_1 : BANK_0; #ifdef DEBUG usartSendString("promRead("); usartSendByte(bank?'1':'0'); usartSendByte(','); usartSendWordHex(addr); usartSendByte(','); usartSendWordHex(length); usartSendByte(')'); usartSendByte('\r'); #endif // Wait for I2C idle // while ( I2CS & bmSTOP ); // Send the WRITE command // I2CS = bmSTART; I2DAT = i2cAddr; // Write I2C address byte (WRITE) if ( promWaitForAck() ) { return true; } // Send the address, MSB first // I2DAT = MSB(addr); // Write MSB of address if ( promWaitForAck() ) { return true; } I2DAT = LSB(addr); // Write LSB of address if ( promWaitForAck() ) { return true; } // Send the READ command // I2CS = bmSTART; I2DAT = (i2cAddr | READ); // Write I2C address byte (READ) if ( promWaitForDone() ) { return true; } // Read dummy byte // i = I2DAT; if ( promWaitForDone() ) { return true; } // Now get the actual data // for ( i = 0; i < (length-1); i++ ) { buf[i] = I2DAT; if ( promWaitForDone() ) { return true; } } // Terminate the read operation and get last byte // I2CS = bmLASTRD; if ( promWaitForDone() ) { return true; } buf[i] = I2DAT; if ( promWaitForDone() ) { return true; } I2CS = bmSTOP; i = I2DAT; return false; }
// Called once at startup // void mainInit(void) { xdata uint8 thisByte = 0xFF; xdata uint16 blockSize; // This is only necessary for cases where you want to load firmware into the RAM of an FX2 that // has already loaded firmware from an EEPROM. It should definitely be removed for firmwares // which are themselves to be loaded from EEPROM. #ifndef EEPROM RENUMERATE_UNCOND(); #endif // Disable alternate functions for PORTA 0,1,3 & 7. PORTACFG = 0x00; // Return FIFO setings back to default just in case previous firmware messed with them. SYNCDELAY; PINFLAGSAB = 0x00; SYNCDELAY; PINFLAGSCD = 0x00; SYNCDELAY; FIFOPINPOLAR = 0x00; // Global settings SYNCDELAY; REVCTL = (bmDYN_OUT | bmENH_PKT); SYNCDELAY; CPUCS = bmCLKSPD1; // 48MHz // Drive IFCLK at 48MHz, enable slave FIFOs SYNCDELAY; IFCONFIG = (bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | bmFIFOS); // EP4 & EP8 are unused SYNCDELAY; EP4CFG = 0x00; SYNCDELAY; EP8CFG = 0x00; SYNCDELAY; EP4FIFOCFG = 0x00; SYNCDELAY; EP8FIFOCFG = 0x00; // EP1OUT & EP1IN SYNCDELAY; EP1OUTCFG = (bmVALID | bmBULK); SYNCDELAY; EP1INCFG = (bmVALID | bmBULK); // EP2OUT & EP6IN are quad-buffered bulk endpoints SYNCDELAY; EP2CFG = (bmVALID | bmBULK); SYNCDELAY; EP6CFG = (bmVALID | bmBULK | bmDIR); // Reset FIFOs for EP2OUT & EP6IN SYNCDELAY; FIFORESET = bmNAKALL; SYNCDELAY; FIFORESET = 2; // reset EP2OUT SYNCDELAY; FIFORESET = 6; // reset EP6IN SYNCDELAY; FIFORESET = 0x00; // Arm EP1OUT EP1OUTBC = 0x00; // Arm the EP2OUT buffers. Done four times because it's quad-buffered SYNCDELAY; OUTPKTEND = bmSKIP | 2; // EP2OUT SYNCDELAY; OUTPKTEND = bmSKIP | 2; SYNCDELAY; OUTPKTEND = bmSKIP | 2; SYNCDELAY; OUTPKTEND = bmSKIP | 2; // EP2OUT & EP6IN automatically commit packets SYNCDELAY; EP2FIFOCFG = bmAUTOOUT; SYNCDELAY; EP6FIFOCFG = bmAUTOIN; // Auto-commit 512-byte packets from EP6IN (master may commit early by asserting PKTEND) SYNCDELAY; EP6AUTOINLENH = 0x02; SYNCDELAY; EP6AUTOINLENL = 0x00; // Turbo I2C I2CTL |= bm400KHZ; // Auto-pointers AUTOPTRSETUP = bmAPTREN | bmAPTR1INC | bmAPTR2INC; // Port lines... IOA = 0x00; OEA = 0x00; IOC = 0x00; OEC = 0x00; IOD = 0x00; OED = 0x00; IOE = 0x00; OEE = 0x00; // Disable JTAG mode by default (i.e don't drive JTAG pins) jtagSetEnabled(false); #ifdef BOOT promStartRead(false, 0x0000); if ( promPeekByte() == 0xC2 ) { promNextByte(); // VID(L) promNextByte(); // VID(H) promNextByte(); // PID(L) promNextByte(); // PID(H) promNextByte(); // DID(L) promNextByte(); // DID(H) promNextByte(); // Config byte promNextByte(); // Length(H) thisByte = promPeekByte(); while ( !(thisByte & 0x80) ) { blockSize = thisByte; blockSize <<= 8; promNextByte(); // Length(L) blockSize |= promPeekByte(); blockSize += 2; // Space taken by address while ( blockSize-- ) { promNextByte(); } promNextByte(); // Length(H) thisByte = promPeekByte(); } promNextByte(); // Length(L) promNextByte(); // Address(H) promNextByte(); // Address(L) promNextByte(); // Last byte promNextByte(); // First byte after the end of the firmware } jtagSetEnabled(true); jtagCsvfInit(); m_diagnosticCode = jtagCsvfPlay(); jtagSetEnabled(false); thisByte = promPeekByte(); promNextByte(); blockSize = promPeekByte(); promNextByte(); blockSize <<= 8; blockSize |= promPeekByte(); promNextByte(); if ( thisByte ) { if ( blockSize ) { fifoSendPromData(0x10000UL + blockSize); } } else if ( blockSize ) { fifoSendPromData(blockSize); } promStopRead(); USBCS &= ~bmDISCON; #endif #ifdef DEBUG usartInit(); usartSendString("MakeStuff FPGALink/FX2 v1.1\r"); #endif initPorts(); }