#define AVRDEVCODE02 0x56 /* ATtiny15 */\r
#define AVRDEVCODE03 0x5E /* ATtiny261 */\r
#define AVRDEVCODE04 0x76 /* ATmega8 */\r
-#define AVRDEVCODE05 0x74 /*ATmega16 */\r
+#define AVRDEVCODE05 0x74 /* ATmega16 */\r
#define AVRDEVCODE06 0x72 /* ATmega32 */\r
#define AVRDEVCODE07 0x45 /* ATmega64 */\r
#define AVRDEVCODE08 0x74 /* ATmega644 */\r
/** Flag to indicate if the USART is currently transmitting data from the Rx_Buffer circular buffer. */\r
volatile bool Transmitting = false;\r
\r
-\r
/* some global variables used throughout */\r
-uint8_t tempIOreg = 0;\r
-uint8_t tempIOreg2 = 0;\r
-uint8_t tempIOreg3 = 0;\r
-uint8_t tempIOreg4 = 0;\r
-uint8_t dataWidth = 0;\r
-uint8_t firstRun = 1;\r
-uint8_t deviceCode = 0;\r
-uint8_t tempByte = 0;\r
uint16_t currAddress = 0;\r
-uint16_t timerval = 0;\r
-\r
-\r
\r
/** Main program entry point. This routine configures the hardware required by the application, then\r
starts the scheduler to run the application tasks.\r
MCUSR &= ~(1 << WDRF);\r
wdt_disable();\r
\r
- /* Disable Clock Division */\r
- SetSystemClockPrescaler(0);\r
+ /* Disable clock division */\r
+ clock_prescale_set(clock_div_1);\r
\r
/* Hardware Initialization */\r
LEDs_Init();\r
ReconfigureSPI();\r
- // prepare PortB\r
- DDRB = 0;\r
- PORTB = 0;\r
+\r
DDRC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2\r
// PC2 is also used for RESET, so set it HIGH initially - note 'P' command sets it to LOW (Active)\r
PORTC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2\r
PORTB |= (1 << PB0);\r
// make sure DataFlash devices to not interfere - deselect them by setting PE0 and PE1 HIGH:\r
PORTE = 0xFF;\r
- DDRE = 0xFF;\r
-\r
- // initialize Timer1 for use in delay function\r
- TCCR1A = 0;\r
- //TCCR1B = (1 << CS10); // no prescaling, use CLK\r
- TCCR1B = ((1 << CS12) | (1 << CS10)); // prescale by CLK/1024\r
- // 8MHz/1024 = 7813 ticks per second --> ~8 ticks per millisecond (ms)\r
- timerval = TCNT1; // start timer1\r
-\r
+ DDRE = 0xFF;\r
\r
/* Ringbuffer Initialization */\r
Buffer_Initialize(&Rx_Buffer);\r
case REQ_GetLineEncoding:\r
if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))\r
{ \r
- /* Acknowedge the SETUP packet, ready for data transfer */\r
+ /* Acknowledge the SETUP packet, ready for data transfer */\r
Endpoint_ClearSetupReceived();\r
\r
/* Write the line coding data to the control endpoint */\r
case REQ_SetLineEncoding:\r
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
{\r
- /* Acknowedge the SETUP packet, ready for data transfer */\r
+ /* Acknowledge the SETUP packet, ready for data transfer */\r
Endpoint_ClearSetupReceived();\r
\r
/* Read the line coding data in from the host into the global struct */\r
case REQ_SetControlLineState:\r
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))\r
{\r
-#if 0\r
- /* NOTE: Here you can read in the line state mask from the host, to get the current state of the output handshake\r
- lines. The mask is read in from the wValue parameter, and can be masked against the CONTROL_LINE_OUT_* masks\r
- to determine the RTS and DTR line states using the following code:\r
- */\r
-\r
- uint16_t wIndex = Endpoint_Read_Word_LE();\r
- \r
- // Do something with the given line states in wIndex\r
-#endif\r
- \r
- /* Acknowedge the SETUP packet, ready for data transfer */\r
+ /* Acknowledge the SETUP packet, ready for data transfer */\r
Endpoint_ClearSetupReceived();\r
\r
- /* Send an empty packet to acknowedge the command */\r
+ /* Acknowledge status stage */\r
+ while (!(Endpoint_IsSetupINReady()));\r
Endpoint_ClearSetupIN();\r
}\r
\r
{\r
if (USB_IsConnected)\r
{\r
-#if 0\r
- /* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232\r
- handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:\r
- */\r
-\r
- USB_Notification_Header_t Notification = (USB_Notification_Header_t)\r
- {\r
- NotificationType: (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),\r
- Notification: NOTIF_SerialState,\r
- wValue: 0,\r
- wIndex: 0,\r
- wLength: sizeof(uint16_t),\r
- };\r
- \r
- uint16_t LineStateMask;\r
- \r
- // Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host\r
- \r
- Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);\r
- Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));\r
- Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));\r
- Endpoint_ClearCurrentBank();\r
-#endif\r
-\r
/* Select the Serial Rx Endpoint */\r
Endpoint_SelectEndpoint(CDC_RX_EPNUM);\r
\r
/* Store each character from the endpoint */\r
Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());\r
\r
-\r
-\r
-\r
- /* Each time there is an element, check which comand should be\r
- run and if enough data is available to run that command.\r
- There are 1-byte, 2-byte, 3-byte, 4-byte commands, and 5-byte commands\r
- Remember that the "which command" byte counts as 1 */\r
- if (Rx_Buffer.Elements == 0) {\r
- // do nothing, wait for data\r
- } else {\r
- tempByte = Buffer_PeekElement(&Rx_Buffer); // peek at first element\r
-\r
- /* make sure the issued command and associated data are all ready */\r
- if (Rx_Buffer.Elements == 1) { // zero data byte command\r
- if ((tempByte == 'P') | (tempByte == 'a') | (tempByte == 'm') |\r
- (tempByte == 'R') | (tempByte == 'd') | (tempByte == 'e') |\r
- (tempByte == 'L') | (tempByte == 's') | (tempByte == 't') | \r
- (tempByte == 'S') | (tempByte == 'V') | (tempByte == 'v') |\r
- (tempByte == 'p') | (tempByte == 'F')) {\r
- processHostSPIRequest(); // command has enough data, process it\r
- }\r
- } else if (Rx_Buffer.Elements == 2) { // one data byte command\r
- if ((tempByte == 'T') | (tempByte == 'c') | (tempByte == 'C') |\r
- (tempByte == 'D') | (tempByte == 'l') | (tempByte == 'f') |\r
- (tempByte == 'x') | (tempByte == 'y')) {\r
- processHostSPIRequest(); // command has enough data, process it\r
- }\r
- } else if (Rx_Buffer.Elements == 3) { // two data byte command\r
- if ((tempByte == 'A') | (tempByte == 'Z')) {\r
- processHostSPIRequest(); // command has enough data, process it\r
- }\r
- } else if (Rx_Buffer.Elements == 4) { // three data byte command\r
- if ((tempByte == ':')) {\r
- processHostSPIRequest(); // command has enough data, process it\r
- }\r
- } else if (Rx_Buffer.Elements == 5) { // four data byte command\r
- if ((tempByte == '.')) {\r
- processHostSPIRequest(); // command has enough data, process it\r
- }\r
- } else {\r
- // do nothing\r
- }\r
+ /* Run the given command once enough data is available. */\r
+ if (Rx_Buffer.Elements)\r
+ {\r
+ const uint8_t ZeroDataByteCommands[] = {'P', 'a', 'm', 'R', 'd', 'e', 'L', 's', 't', 'S', 'V', 'v', 'p', 'F'};\r
+ const uint8_t OneDataByteCommands[] = {'T', 'c', 'C', 'D', 'l', 'f', 'x', 'y'};\r
+ const uint8_t TwoDataByteCommands[] = {'A', 'Z'};\r
+ const uint8_t ThreeDataByteCommands[] = {':'};\r
+ const uint8_t FourDataByteCommands[] = {'.'};\r
+ \r
+ const struct\r
+ {\r
+ const uint8_t TotalCommands;\r
+ const uint8_t* CommandBytes;\r
+ } AVR910Commands[] = {{sizeof(ZeroDataByteCommands), ZeroDataByteCommands},\r
+ {sizeof(OneDataByteCommands), OneDataByteCommands},\r
+ {sizeof(TwoDataByteCommands), TwoDataByteCommands},\r
+ {sizeof(ThreeDataByteCommands), ThreeDataByteCommands},\r
+ {sizeof(FourDataByteCommands), FourDataByteCommands}};\r
+ \r
+ /* Determine the data length of the issued command */\r
+ uint8_t CommandDataLength = (Rx_Buffer.Elements - 1);\r
+ \r
+ /* Loop through each of the possible command bytes allowable from the given command data length */\r
+ for (uint8_t CurrentCommand = 0; CurrentCommand < AVR910Commands[CommandDataLength].TotalCommands; CurrentCommand++)\r
+ {\r
+ /* If issues command matches an allowable command, process it */\r
+ if (Buffer_PeekElement(&Rx_Buffer) == AVR910Commands[CommandDataLength].CommandBytes[CurrentCommand])\r
+ processHostSPIRequest();\r
+ }\r
}\r
-\r
-\r
-\r
}\r
\r
/* Clear the endpoint buffer */\r
Endpoint_ClearCurrentBank();\r
}\r
- \r
- /* Check if Rx buffer contains data */\r
- if (Rx_Buffer.Elements)\r
- {\r
- /* Initiate the transmission of the buffer contents if USART idle */\r
- if (!(Transmitting))\r
- {\r
- Transmitting = true;\r
- /* The following flushes the receive buffer to prepare for new data and commands */\r
- /* Need to flush the buffer as the command byte which is peeked above needs to be */\r
- /* dealt with, otherwise the command bytes will overflow the buffer eventually */\r
- //Buffer_GetElement(&Rx_Buffer); // works also\r
- Buffer_Initialize(&Rx_Buffer);\r
- }\r
- }\r
\r
/* Select the Serial Tx Endpoint */\r
Endpoint_SelectEndpoint(CDC_TX_EPNUM);\r
}\r
}\r
\r
-\r
-\r
/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to\r
- log to a serial port, or anything else that is suitable for status updates.\r
+ * log to a serial port, or anything else that is suitable for status updates.\r
*\r
- \param CurrentStatus Current status of the system, from the USBtoSerial_StatusCodes_t enum\r
+ * \param CurrentStatus Current status of the system, from the USBtoSerial_StatusCodes_t enum\r
*/\r
void UpdateStatus(uint8_t CurrentStatus)\r
{\r
LEDs_SetAllLEDs(LEDMask);\r
}\r
\r
-\r
/** Reconfigures SPI to match the current serial port settings issued by the host. */\r
void ReconfigureSPI(void)\r
{\r
uint8_t SPCRmask = (1 << SPE) | (1 << MSTR); // always enable SPI as Master\r
uint8_t SPSRmask = 0;\r
\r
- /* Determine data width */\r
- if (LineCoding.ParityType == Parity_Odd) {\r
- dataWidth = 16;\r
- } else if (LineCoding.ParityType == Parity_Even) {\r
- dataWidth = 32;\r
- } else if (LineCoding.ParityType == Parity_None) {\r
- dataWidth = 8;\r
- }\r
-\r
/* Determine stop bits - 1.5 stop bits is set as 1 stop bit due to hardware limitations */\r
/* For SPI, determine whether format is LSB or MSB */\r
if (LineCoding.CharFormat == TwoStopBits) { \r
\r
SPCR = SPCRmask;\r
SPSR = SPSRmask;\r
-\r
- // only read if first run\r
- if (firstRun) {\r
- tempIOreg = SPSR; //need to read to initiliaze\r
- tempIOreg = SPDR; //need to read to initiliaze\r
- firstRun = 0;\r
- }\r
-\r
}\r
\r
\r
//PORTB = 0; // set clock to zero\r
RESETPORT = (1 << RESETPIN); // set RESET pin on target to 1\r
RESETPORT2 = (1 << RESETPIN2);\r
- delay_ms(DELAY_SHORT);\r
+ _delay_ms(DELAY_SHORT);\r
//RESETPORT = (RESETPORT & ~(1 << RESETPIN)); // set RESET pin on target to 0 - Active\r
RESETPORT = 0x00;\r
RESETPORT2 = 0;\r
- delay_ms(DELAY_SHORT);\r
+ _delay_ms(DELAY_SHORT);\r
SPI_SendByte(0xAC);\r
SPI_SendByte(0x53);\r
SPI_SendByte(0x00);\r
SPI_SendByte(0x00);\r
- delay_ms(DELAY_VERYSHORT);\r
+ _delay_ms(DELAY_VERYSHORT);\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == 'T') { // Select device type\r
- deviceCode = Buffer_GetElement(&Rx_Buffer); // set device type\r
+ Buffer_GetElement(&Rx_Buffer); // set device type\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == 'a') { // Report autoincrement address\r
SPI_SendByte((currAddress >> 8)); // high byte\r
SPI_SendByte((currAddress)); // low byte\r
SPI_SendByte(readByte1); // data\r
- delay_ms(DELAY_MEDIUM); // certain MCUs require a delay of about 24585 cycles\r
+ _delay_ms(DELAY_MEDIUM); // certain MCUs require a delay of about 24585 cycles\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == 'C') { // Write program memory, high byte\r
SPI_SendByte((currAddress >> 8)); // high byte\r
SPI_SendByte((currAddress)); // low byte\r
SPI_SendByte(0x00);\r
- delay_ms(DELAY_LONG);\r
+ _delay_ms(DELAY_LONG);\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == 'R') { // Read Program Memory\r
SPI_SendByte((currAddress >> 8)); // high byte\r
SPI_SendByte((currAddress)); // low byte\r
SPI_SendByte(readByte1); // data\r
- delay_ms(DELAY_MEDIUM);\r
+ _delay_ms(DELAY_MEDIUM);\r
currAddress++; // increment currAddress\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
SPI_SendByte(0x80);\r
SPI_SendByte(0x04);\r
SPI_SendByte(0x00);\r
- delay_ms(DELAY_LONG);\r
+ _delay_ms(DELAY_LONG);\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == 'l') { // write lock bits\r
SPI_SendByte(((0x06 & readByte1) | 0xE0)); // TODO - is this correct???\r
SPI_SendByte(0x00);\r
SPI_SendByte(0x00);\r
- delay_ms(DELAY_MEDIUM);\r
+ _delay_ms(DELAY_MEDIUM);\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == 'f') { // write fuse bits\r
SPI_SendByte(readByte3);\r
readByte1 = SPI_TransferByte(0x00);\r
Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- delay_ms(DELAY_MEDIUM);\r
+ _delay_ms(DELAY_MEDIUM);\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == '.') { // New Universal Command\r
SPI_SendByte(readByte3);\r
readByte1 = SPI_TransferByte(readByte4);\r
Buffer_StoreElement(&Tx_Buffer, readByte1);\r
- delay_ms(DELAY_MEDIUM);\r
+ _delay_ms(DELAY_MEDIUM);\r
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful\r
\r
} else if (firstByte == 'Z') { // Special test command\r
}\r
}\r
\r
-\r
-void delay_ms(uint8_t dly) {\r
- uint16_t endtime = 0;\r
-\r
- endtime = TCNT1;\r
- if (endtime > 63486) {\r
- endtime = (dly * DELAY_MULTIPLE);\r
- } else {\r
- endtime += (dly * DELAY_MULTIPLE);\r
- }\r
-\r
- timerval = TCNT1;\r
- while (timerval < endtime) {\r
- timerval = TCNT1;\r
- }\r
-}\r