forked from mfulz_github/qmk_firmware
Moved all source to the trunk directory.
This commit is contained in:
parent
6a10d6b465
commit
032a83e9e1
|
@ -0,0 +1,176 @@
|
|||
Instructions for converting the LUFA USBtoSerial Demo to an AVR ISP Programmer.
|
||||
By Opendous Inc., Copyright under the Creative Commons Attribution License:
|
||||
http://creativecommons.org/licenses/by/3.0/
|
||||
|
||||
1) Start with the LUFA/Demos/USBtoSerial firmware.
|
||||
- rename USBtoSerial.c, USBtoSerial.h, and USBtoSerial.aps to
|
||||
AVRISP_Programmer.*
|
||||
- edit AVRISP_Programmer.aps and rename all instances of "USBtoSerial" to
|
||||
"AVRISP_Programmer"
|
||||
- copy AVRISP_Programmer.txt from an older version of AVRISP_Programmer
|
||||
|
||||
2) Edit makefile by changing TARGET from "USBtoSerial" to "AVRISP_Programmer"
|
||||
|
||||
3) Edit AVRISP_Programmer.h:
|
||||
- change ifdef _USB_TO_SERIAL_H to _AVRISP_PROGRAMMER_H_
|
||||
- rename ReconfigureUSART(void) to ReconfigureSPI(void)
|
||||
- add void processHostSPIRequest(void); & void delay_ms(uint8_t dly);
|
||||
- replace the define for Serial.h with one for SPI.h:
|
||||
#include <libs/LUFA/Drivers/AT90USBXXX/SPI.h>
|
||||
|
||||
4) Make alterations to Descriptors.c
|
||||
- change manufacturer string to "www.AVRopendous.org", length=19
|
||||
- change product string to "LUFA-Based AVR ISP Programmer", length=29
|
||||
|
||||
5) Edit Ringbuff.h to enable the Peek Command: #define BUFF_USEPEEK
|
||||
|
||||
6) Edit AVRISP_Programmer.c:
|
||||
- change #include "USBtoSerial.h" to #include "AVRISP_Programmer.h"
|
||||
- change BUTTLOADTAG(ProjName to "LUFA AVR910 ISP Programmer"
|
||||
- in main(), rename ReconfigureUSART() to Reconfigure();
|
||||
- in EVENT_HANDLER(USB_UnhandledControlPacket), rename ReconfigureUSART
|
||||
- delete the ISRs: ISR(USART1_RX_vect) & ISR(USART1_TX_vect)
|
||||
- delete ReconfigureUSART(void)
|
||||
- add void ReconfigureSPI(void), void processHostSPIRequest(void),
|
||||
and void delay_ms(uint8_t dly) from a previous version
|
||||
- add Timer1 and SPI initialization code to main():
|
||||
/* Hardware Initialization */
|
||||
//LEDs_Init();
|
||||
DDRB = 0;
|
||||
PORTB = 0;
|
||||
DDRC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
|
||||
// PC2 is also used for RESET, so set it HIGH initially - note 'P' command sets it to LOW (Active)
|
||||
PORTC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
|
||||
DDRD = 0;
|
||||
PORTD = (1 << PB7); // only PB7(HWB) should be High as this is the bootloader pin
|
||||
// Prepare PortB for SPI - set PB0(^SS), PB1(SCK), PB2(MOSI) as output as well as all other pins except PB3(MISO)
|
||||
DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (0 << PB3) | (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7);
|
||||
PORTB |= (1 << PB0);
|
||||
|
||||
// initialize Timer1 for use in delay function
|
||||
TCCR1A = 0;
|
||||
//TCCR1B = (1 << CS10); // no prescaling, use CLK
|
||||
TCCR1B = ((1 << CS12) | (1 << CS10)); // prescale by CLK/1024
|
||||
// 8MHz/1024 = 7813 ticks per second --> ~8 ticks per millisecond (ms)
|
||||
timerval = TCNT1; // start timer1
|
||||
|
||||
- In TASK(CDC_Task) in the
|
||||
if (USB_IsConnected) {
|
||||
if (Endpoint_ReadWriteAllowed()) {
|
||||
while (Endpoint_BytesInEndpoint()) {
|
||||
...
|
||||
structure, after Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte()):
|
||||
|
||||
/* Each time there is an element, check which comand should be
|
||||
run and if enough data is available to run that command.
|
||||
There are 1-byte, 2-byte, 3-byte, 4-byte commands, and 5-byte commands
|
||||
Remember that the "which command" byte counts as 1 */
|
||||
if (Rx_Buffer.Elements == 0) {
|
||||
// do nothing, wait for data
|
||||
} else {
|
||||
tempByte = Buffer_PeekElement(&Rx_Buffer); // peek at first element
|
||||
|
||||
/* make sure the issued command and associated data are all ready */
|
||||
if (Rx_Buffer.Elements == 1) { // zero data byte command
|
||||
if ((tempByte == 'P') | (tempByte == 'a') | (tempByte == 'm') |
|
||||
(tempByte == 'R') | (tempByte == 'd') | (tempByte == 'e') |
|
||||
(tempByte == 'L') | (tempByte == 's') | (tempByte == 't') |
|
||||
(tempByte == 'S') | (tempByte == 'V') | (tempByte == 'v') |
|
||||
(tempByte == 'p') | (tempByte == 'F')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 2) { // one data byte command
|
||||
if ((tempByte == 'T') | (tempByte == 'c') | (tempByte == 'C') |
|
||||
(tempByte == 'D') | (tempByte == 'l') | (tempByte == 'f') |
|
||||
(tempByte == 'x') | (tempByte == 'y')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 3) { // two data byte command
|
||||
if ((tempByte == 'A') | (tempByte == 'Z')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 4) { // three data byte command
|
||||
if ((tempByte == ':')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 5) { // four data byte command
|
||||
if ((tempByte == '.')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
- need to add code to flush the buffer. Change:
|
||||
/* Check if Rx buffer contains data */
|
||||
if (Rx_Buffer.Elements)
|
||||
{
|
||||
/* Initiate the transmission of the buffer contents if USART idle*/
|
||||
if (!(Transmitting))
|
||||
{
|
||||
Transmitting = true;
|
||||
Serial_TxByte(Buffer_GetElement(&Rx_Buffer));
|
||||
}
|
||||
}
|
||||
To:
|
||||
/* Check if Rx buffer contains data */
|
||||
if (Rx_Buffer.Elements)
|
||||
{
|
||||
/* Initiate the transmission of the buffer contents if USART idle*/
|
||||
if (!(Transmitting))
|
||||
{
|
||||
Transmitting = true;
|
||||
/* The following flushes the receive buffer to prepare for new
|
||||
data and commands. Need to flush the buffer as the command
|
||||
byte which is peeked above needs to be dealt with, otherwise
|
||||
the command bytes will overflow the buffer eventually */
|
||||
//Buffer_GetElement(&Rx_Buffer); // also works
|
||||
Buffer_Initialize(&Rx_Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
- need to add the following defines and globals:
|
||||
#define RESETPORT PORTB
|
||||
#define RESETPIN PB0
|
||||
#define RESETPORT2 PORTC
|
||||
#define RESETPIN2 PC2
|
||||
#define CR_HEX '\r'
|
||||
|
||||
#define DELAY_VERYSHORT 0x01
|
||||
#define DELAY_SHORT 0x02
|
||||
#define DELAY_MEDIUM 0x03
|
||||
#define DELAY_LONG 0x05
|
||||
#define DELAY_MULTIPLE 0x04
|
||||
|
||||
/* AVR Device Codes - Can have a maximum of 14 but can be any you want.
|
||||
Note that these are completely irrelevent. If AVRdude supports a
|
||||
device, then that device is programmable. Use -F switch to ignore
|
||||
device codes. */
|
||||
#define AVRDEVCODE01 0x55 /* ATtiny12 */
|
||||
#define AVRDEVCODE02 0x56 /* ATtiny15 */
|
||||
#define AVRDEVCODE03 0x5E /* ATtiny261 */
|
||||
#define AVRDEVCODE04 0x76 /* ATmega8 */
|
||||
#define AVRDEVCODE05 0x74 /* ATmega16 */
|
||||
#define AVRDEVCODE06 0x72 /* ATmega32 */
|
||||
#define AVRDEVCODE07 0x45 /* ATmega64 */
|
||||
#define AVRDEVCODE08 0x74 /* ATmega644 */
|
||||
#define AVRDEVCODE09 0x43 /* ATmega128 */
|
||||
#define AVRDEVCODE10 0x63 /* ATmega162 */
|
||||
#define AVRDEVCODE11 0x78 /* ATmega169 */
|
||||
#define AVRDEVCODE12 0x6C /* AT90S4434 */
|
||||
#define AVRDEVCODE13 0x38 /* AT90S8515A */
|
||||
#define AVRDEVCODE14 0x65 /* AT90S8555 */
|
||||
|
||||
/* some global variables used throughout */
|
||||
uint8_t tempIOreg = 0;
|
||||
uint8_t tempIOreg2 = 0;
|
||||
uint8_t tempIOreg3 = 0;
|
||||
uint8_t tempIOreg4 = 0;
|
||||
uint8_t dataWidth = 0;
|
||||
uint8_t firstRun = 1;
|
||||
uint8_t deviceCode = 0;
|
||||
uint8_t tempByte = 0;
|
||||
uint16_t currAddress = 0;
|
||||
uint16_t timerval = 0;
|
||||
|
|
@ -0,0 +1 @@
|
|||
<AVRStudio><MANAGEMENT><ProjectName>AVRISP_Programmer</ProjectName><Created>30-Sep-2008 14:18:39</Created><LastEdit>30-Sep-2008 14:18:52</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>30-Sep-2008 14:18:39</Created><Version>4</Version><Build>4, 14, 0, 589</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile></ObjectFile><EntryFile></EntryFile><SaveFolder>C:\Users\Dean\Documents\Electronics\Projects\WORK\MyUSBWORK\Demos\AVRISP_Programmer\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET></CURRENT_TARGET><CURRENT_PART></CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>Descriptors.c</SOURCEFILE><SOURCEFILE>RingBuff.c</SOURCEFILE><SOURCEFILE>AVRISP_Programmer.c</SOURCEFILE><HEADERFILE>Descriptors.h</HEADERFILE><HEADERFILE>RingBuff.h</HEADERFILE><HEADERFILE>AVRISP_Programmer.h</HEADERFILE><OTHERFILE>makefile</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>YES</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE>makefile</EXTERNALMAKEFILE><PART>atmega128</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>AVRISP_Programmer.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS/><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR-20080512\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR-20080512\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>
|
|
@ -0,0 +1,886 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
AVR ISP Programmer code Copyright 2009 Opendous Inc. (www.opendous.org)
|
||||
For more info and usage instructions for this firmware, visit:
|
||||
http://code.google.com/p/avropendous/wiki/AVR_ISP_Programmer
|
||||
|
||||
Note that this firmware is designed to work with AVRdude:
|
||||
http://savannah.nongnu.org/projects/avrdude
|
||||
But should work with other software that supports the AVR910 ISP
|
||||
programmer or STK200 hardware.
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/*
|
||||
Usage:
|
||||
avrdude -vv -F -P COM7 -c avr910 -p t261
|
||||
Note -F flag which overrides signature check and enables programming
|
||||
of any "In-System Programmable via SPI Port" AVR MCU. Part number,
|
||||
t261, should be set to your target device.
|
||||
avrdude -vv -F -P COM7 -c avr910 -p t261 -U flash:w:PROG.hex
|
||||
PROG.hex is the hex file to program your t261 AVR with
|
||||
avrdude -vv -F -P COM7 -b 115200 -c avr910 -p t261 -U flash:w:test.hex
|
||||
The -b 115200 sets the SPI clock to 62.5kHz from the default 125kHz and may
|
||||
work when the default programming speed fails.
|
||||
AVROSP.exe -dATtiny261 -cCOM7 -rf
|
||||
AVRosp is the Open Source AVR ISP Programming Software available from Atmel.com
|
||||
|
||||
Note: on Linux systems, COM7 should be replaced with someting like /dev/ttyACM0
|
||||
You can determine this value by running dmesg after plugging in the device
|
||||
Note: you must RESET the programmer after each use (AVRdude session).
|
||||
|
||||
Note: If you experience errors with older devices, try changing the DELAY defines
|
||||
|
||||
MISO, MOSI, and SCK are connected directly from the AVRopendous board
|
||||
to the pin of the same functionality on the target. RESET pin on the target
|
||||
can be connected either to SS (PB0), or PC2. Do not have any other pins
|
||||
connected - especially HWB pin, to avoid unintentional behaviour.
|
||||
|
||||
AVR910 functionality was overlayed on USBtoSerial functionality.
|
||||
Keep this in mind when looking over the code.
|
||||
Default target speed is 125kHz and corresponds to 19200 baud, which
|
||||
is the default setting for AVRdude.
|
||||
|
||||
Changing "Baud-Rate" will change the SPI speed. Defualt SPI clock speed
|
||||
is 8Mhz / 4 = 2MHz. 8Mhz is the device clock speed. This is the setting at
|
||||
9600 baud. The following is a table of baud-rate vs. SPI Speed that will result
|
||||
9600 = 2Mhz
|
||||
14400 = 1MHz
|
||||
19200 = 125kHz (AVRdude Default)
|
||||
38400 = 250kHz
|
||||
57600 = 500kHz
|
||||
115200 = 62.5kHz
|
||||
|
||||
Before running, you will need to install the INF file that
|
||||
is located in the project directory. This will enable
|
||||
Windows to use its inbuilt CDC drivers, negating the need
|
||||
for special Windows drivers for the device. To install,
|
||||
right-click the .INF file and choose the Install option.
|
||||
*/
|
||||
|
||||
/* TODO: - fix the requirement that a RESET must be performed after each session, which
|
||||
is only an issue under Windows. Everything works fine under Linux
|
||||
*/
|
||||
|
||||
#include "AVRISP_Programmer.h"
|
||||
|
||||
/* Project Tags, for reading out using the ButtLoad project */
|
||||
BUTTLOADTAG(ProjName, "LUFA AVR910 ISP Programmer");
|
||||
BUTTLOADTAG(BuildTime, __TIME__);
|
||||
BUTTLOADTAG(BuildDate, __DATE__);
|
||||
BUTTLOADTAG(LUFAVersion, "LUFA V" LUFA_VERSION_STRING);
|
||||
|
||||
|
||||
#define RESETPORT PORTB
|
||||
#define RESETPIN PB0
|
||||
#define RESETPORT2 PORTC
|
||||
#define RESETPIN2 PC2
|
||||
#define CR_HEX '\r'
|
||||
|
||||
#define DELAY_VERYSHORT 0x01
|
||||
#define DELAY_SHORT 0x02
|
||||
#define DELAY_MEDIUM 0x03
|
||||
#define DELAY_LONG 0x05
|
||||
#define DELAY_MULTIPLE 0x02
|
||||
|
||||
|
||||
/* AVR Device Codes - Can have a maximum of 14 but can be any you want.
|
||||
Note that these are completely irrelevent. If AVRdude supports a device,
|
||||
then that device is programmable. Use -F switch to ignore device codes. */
|
||||
#define AVRDEVCODE01 0x55 /* ATtiny12 */
|
||||
#define AVRDEVCODE02 0x56 /* ATtiny15 */
|
||||
#define AVRDEVCODE03 0x5E /* ATtiny261 */
|
||||
#define AVRDEVCODE04 0x76 /* ATmega8 */
|
||||
#define AVRDEVCODE05 0x74 /*ATmega16 */
|
||||
#define AVRDEVCODE06 0x72 /* ATmega32 */
|
||||
#define AVRDEVCODE07 0x45 /* ATmega64 */
|
||||
#define AVRDEVCODE08 0x74 /* ATmega644 */
|
||||
#define AVRDEVCODE09 0x43 /* ATmega128 */
|
||||
#define AVRDEVCODE10 0x63 /* ATmega162 */
|
||||
#define AVRDEVCODE11 0x78 /* ATmega169 */
|
||||
#define AVRDEVCODE12 0x6C /* AT90S4434 */
|
||||
#define AVRDEVCODE13 0x38 /* AT90S8515A */
|
||||
#define AVRDEVCODE14 0x65 /* AT90S8555 */
|
||||
|
||||
|
||||
/* Scheduler Task List */
|
||||
TASK_LIST
|
||||
{
|
||||
{ Task: USB_USBTask , TaskStatus: TASK_STOP },
|
||||
{ Task: CDC_Task , TaskStatus: TASK_STOP },
|
||||
};
|
||||
|
||||
/* Globals: */
|
||||
/** Contains the current baud rate and other settings of the virtual serial port.
|
||||
*
|
||||
These values are set by the host via a class-specific request, and the physical USART should be reconfigured to match the
|
||||
new settings each time they are changed by the host.
|
||||
*/
|
||||
CDC_Line_Coding_t LineCoding = { BaudRateBPS: 9600,
|
||||
CharFormat: OneStopBit,
|
||||
ParityType: Parity_None,
|
||||
DataBits: 8 };
|
||||
|
||||
/** Ring (circular) buffer to hold the RX data - data from the host to the attached device on the serial port. */
|
||||
RingBuff_t Rx_Buffer;
|
||||
|
||||
/** Ring (circular) buffer to hold the TX data - data from the attached device on the serial port to the host. */
|
||||
RingBuff_t Tx_Buffer;
|
||||
|
||||
/** Flag to indicate if the USART is currently transmitting data from the Rx_Buffer circular buffer. */
|
||||
volatile bool Transmitting = false;
|
||||
|
||||
|
||||
/* some global variables used throughout */
|
||||
uint8_t tempIOreg = 0;
|
||||
uint8_t tempIOreg2 = 0;
|
||||
uint8_t tempIOreg3 = 0;
|
||||
uint8_t tempIOreg4 = 0;
|
||||
uint8_t dataWidth = 0;
|
||||
uint8_t firstRun = 1;
|
||||
uint8_t deviceCode = 0;
|
||||
uint8_t tempByte = 0;
|
||||
uint16_t currAddress = 0;
|
||||
uint16_t timerval = 0;
|
||||
|
||||
|
||||
|
||||
/** Main program entry point. This routine configures the hardware required by the application, then
|
||||
starts the scheduler to run the application tasks.
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
/* Disable watchdog if enabled by bootloader/fuses */
|
||||
MCUSR &= ~(1 << WDRF);
|
||||
wdt_disable();
|
||||
|
||||
/* Disable Clock Division */
|
||||
SetSystemClockPrescaler(0);
|
||||
|
||||
/* Hardware Initialization */
|
||||
LEDs_Init();
|
||||
ReconfigureSPI();
|
||||
// prepare PortB
|
||||
DDRB = 0;
|
||||
PORTB = 0;
|
||||
DDRC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
|
||||
// PC2 is also used for RESET, so set it HIGH initially - note 'P' command sets it to LOW (Active)
|
||||
PORTC |= ((1 << PC2) | (1 << PC4) | (1 << PC5) | (1 << PC6) | (1 << PC7)); //AT90USBxx2
|
||||
DDRD = 0;
|
||||
PORTD = (1 << PB7); // only PB7(HWB) should be High as this is the bootloader pin
|
||||
// Prepare PortB for SPI - set PB0(^SS), PB1(SCK), PB2(MOSI) as output as well as all other pins except PB3(MISO)
|
||||
DDRB = (1 << PB0) | (1 << PB1) | (1 << PB2) | (0 << PB3) | (1 << PB4) | (1 << PB5) | (1 << PB6) | (1 << PB7);
|
||||
PORTB |= (1 << PB0);
|
||||
// make sure DataFlash devices to not interfere - deselect them by setting PE0 and PE1 HIGH:
|
||||
PORTE = 0xFF;
|
||||
DDRE = 0xFF;
|
||||
|
||||
// initialize Timer1 for use in delay function
|
||||
TCCR1A = 0;
|
||||
//TCCR1B = (1 << CS10); // no prescaling, use CLK
|
||||
TCCR1B = ((1 << CS12) | (1 << CS10)); // prescale by CLK/1024
|
||||
// 8MHz/1024 = 7813 ticks per second --> ~8 ticks per millisecond (ms)
|
||||
timerval = TCNT1; // start timer1
|
||||
|
||||
|
||||
/* Ringbuffer Initialization */
|
||||
Buffer_Initialize(&Rx_Buffer);
|
||||
Buffer_Initialize(&Tx_Buffer);
|
||||
|
||||
/* Indicate USB not ready */
|
||||
UpdateStatus(Status_USBNotReady);
|
||||
|
||||
/* Initialize Scheduler so that it can be used */
|
||||
Scheduler_Init();
|
||||
|
||||
/* Initialize USB Subsystem */
|
||||
USB_Init();
|
||||
|
||||
/* Scheduling - routine never returns, so put this last in the main function */
|
||||
Scheduler_Start();
|
||||
}
|
||||
|
||||
/** Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
|
||||
starts the library USB task to begin the enumeration and USB management process.
|
||||
*/
|
||||
EVENT_HANDLER(USB_Connect)
|
||||
{
|
||||
/* Start USB management task */
|
||||
Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
|
||||
|
||||
/* Indicate USB enumerating */
|
||||
UpdateStatus(Status_USBEnumerating);
|
||||
}
|
||||
|
||||
/** Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
|
||||
the status LEDs and stops the USB management and CDC management tasks.
|
||||
*/
|
||||
EVENT_HANDLER(USB_Disconnect)
|
||||
{
|
||||
/* Stop running CDC and USB management tasks */
|
||||
Scheduler_SetTaskMode(CDC_Task, TASK_STOP);
|
||||
Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
|
||||
|
||||
/* Indicate USB not ready */
|
||||
UpdateStatus(Status_USBNotReady);
|
||||
}
|
||||
|
||||
/** Event handler for the USB_ConfigurationChanged event. This is fired when the host set the current configuration
|
||||
of the USB device after enumeration - the device endpoints are configured and the CDC management task started.
|
||||
*/
|
||||
EVENT_HANDLER(USB_ConfigurationChanged)
|
||||
{
|
||||
/* Setup CDC Notification, Rx and Tx Endpoints */
|
||||
Endpoint_ConfigureEndpoint(CDC_NOTIFICATION_EPNUM, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, CDC_NOTIFICATION_EPSIZE,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
|
||||
Endpoint_ConfigureEndpoint(CDC_TX_EPNUM, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_IN, CDC_TXRX_EPSIZE,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
|
||||
Endpoint_ConfigureEndpoint(CDC_RX_EPNUM, EP_TYPE_BULK,
|
||||
ENDPOINT_DIR_OUT, CDC_TXRX_EPSIZE,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
|
||||
/* Indicate USB connected and ready */
|
||||
UpdateStatus(Status_USBReady);
|
||||
|
||||
/* Start CDC task */
|
||||
Scheduler_SetTaskMode(CDC_Task, TASK_RUN);
|
||||
}
|
||||
|
||||
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
|
||||
control requests that are not handled internally by the USB library (including the CDC control commands,
|
||||
which are all issued via the control endpoint), so that they can be handled appropriately for the application.
|
||||
*/
|
||||
EVENT_HANDLER(USB_UnhandledControlPacket)
|
||||
{
|
||||
uint8_t* LineCodingData = (uint8_t*)&LineCoding;
|
||||
|
||||
/* Process CDC specific control requests */
|
||||
switch (bRequest)
|
||||
{
|
||||
case REQ_GetLineEncoding:
|
||||
if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
/* Acknowedge the SETUP packet, ready for data transfer */
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Write the line coding data to the control endpoint */
|
||||
Endpoint_Write_Control_Stream_LE(LineCodingData, sizeof(LineCoding));
|
||||
|
||||
/* Finalize the stream transfer to send the last packet or clear the host abort */
|
||||
Endpoint_ClearSetupOUT();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetLineEncoding:
|
||||
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
/* Acknowedge the SETUP packet, ready for data transfer */
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Read the line coding data in from the host into the global struct */
|
||||
Endpoint_Read_Control_Stream_LE(LineCodingData, sizeof(LineCoding));
|
||||
|
||||
/* Finalize the stream transfer to clear the last packet from the host */
|
||||
Endpoint_ClearSetupIN();
|
||||
|
||||
/* Reconfigure the USART with the new settings */
|
||||
ReconfigureSPI();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetControlLineState:
|
||||
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
#if 0
|
||||
/* NOTE: Here you can read in the line state mask from the host, to get the current state of the output handshake
|
||||
lines. The mask is read in from the wValue parameter, and can be masked against the CONTROL_LINE_OUT_* masks
|
||||
to determine the RTS and DTR line states using the following code:
|
||||
*/
|
||||
|
||||
uint16_t wIndex = Endpoint_Read_Word_LE();
|
||||
|
||||
// Do something with the given line states in wIndex
|
||||
#endif
|
||||
|
||||
/* Acknowedge the SETUP packet, ready for data transfer */
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Send an empty packet to acknowedge the command */
|
||||
Endpoint_ClearSetupIN();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Task to manage CDC data transmission and reception to and from the host, from and to the physical USART. */
|
||||
TASK(CDC_Task)
|
||||
{
|
||||
if (USB_IsConnected)
|
||||
{
|
||||
#if 0
|
||||
/* NOTE: Here you can use the notification endpoint to send back line state changes to the host, for the special RS-232
|
||||
handshake signal lines (and some error states), via the CONTROL_LINE_IN_* masks and the following code:
|
||||
*/
|
||||
|
||||
USB_Notification_Header_t Notification = (USB_Notification_Header_t)
|
||||
{
|
||||
NotificationType: (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE),
|
||||
Notification: NOTIF_SerialState,
|
||||
wValue: 0,
|
||||
wIndex: 0,
|
||||
wLength: sizeof(uint16_t),
|
||||
};
|
||||
|
||||
uint16_t LineStateMask;
|
||||
|
||||
// Set LineStateMask here to a mask of CONTROL_LINE_IN_* masks to set the input handshake line states to send to the host
|
||||
|
||||
Endpoint_SelectEndpoint(CDC_NOTIFICATION_EPNUM);
|
||||
Endpoint_Write_Stream_LE(&Notification, sizeof(Notification));
|
||||
Endpoint_Write_Stream_LE(&LineStateMask, sizeof(LineStateMask));
|
||||
Endpoint_ClearCurrentBank();
|
||||
#endif
|
||||
|
||||
/* Select the Serial Rx Endpoint */
|
||||
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
|
||||
|
||||
if (Endpoint_ReadWriteAllowed())
|
||||
{
|
||||
/* Read the received data endpoint into the transmission buffer */
|
||||
while (Endpoint_BytesInEndpoint())
|
||||
{
|
||||
/* Wait until the buffer has space for a new character */
|
||||
while (!((BUFF_STATICSIZE - Rx_Buffer.Elements)));
|
||||
|
||||
/* Store each character from the endpoint */
|
||||
Buffer_StoreElement(&Rx_Buffer, Endpoint_Read_Byte());
|
||||
|
||||
|
||||
|
||||
|
||||
/* Each time there is an element, check which comand should be
|
||||
run and if enough data is available to run that command.
|
||||
There are 1-byte, 2-byte, 3-byte, 4-byte commands, and 5-byte commands
|
||||
Remember that the "which command" byte counts as 1 */
|
||||
if (Rx_Buffer.Elements == 0) {
|
||||
// do nothing, wait for data
|
||||
} else {
|
||||
tempByte = Buffer_PeekElement(&Rx_Buffer); // peek at first element
|
||||
|
||||
/* make sure the issued command and associated data are all ready */
|
||||
if (Rx_Buffer.Elements == 1) { // zero data byte command
|
||||
if ((tempByte == 'P') | (tempByte == 'a') | (tempByte == 'm') |
|
||||
(tempByte == 'R') | (tempByte == 'd') | (tempByte == 'e') |
|
||||
(tempByte == 'L') | (tempByte == 's') | (tempByte == 't') |
|
||||
(tempByte == 'S') | (tempByte == 'V') | (tempByte == 'v') |
|
||||
(tempByte == 'p') | (tempByte == 'F')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 2) { // one data byte command
|
||||
if ((tempByte == 'T') | (tempByte == 'c') | (tempByte == 'C') |
|
||||
(tempByte == 'D') | (tempByte == 'l') | (tempByte == 'f') |
|
||||
(tempByte == 'x') | (tempByte == 'y')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 3) { // two data byte command
|
||||
if ((tempByte == 'A') | (tempByte == 'Z')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 4) { // three data byte command
|
||||
if ((tempByte == ':')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else if (Rx_Buffer.Elements == 5) { // four data byte command
|
||||
if ((tempByte == '.')) {
|
||||
processHostSPIRequest(); // command has enough data, process it
|
||||
}
|
||||
} else {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* Clear the endpoint buffer */
|
||||
Endpoint_ClearCurrentBank();
|
||||
}
|
||||
|
||||
/* Check if Rx buffer contains data */
|
||||
if (Rx_Buffer.Elements)
|
||||
{
|
||||
/* Initiate the transmission of the buffer contents if USART idle */
|
||||
if (!(Transmitting))
|
||||
{
|
||||
Transmitting = true;
|
||||
/* The following flushes the receive buffer to prepare for new data and commands */
|
||||
/* Need to flush the buffer as the command byte which is peeked above needs to be */
|
||||
/* dealt with, otherwise the command bytes will overflow the buffer eventually */
|
||||
//Buffer_GetElement(&Rx_Buffer); // works also
|
||||
Buffer_Initialize(&Rx_Buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* Select the Serial Tx Endpoint */
|
||||
Endpoint_SelectEndpoint(CDC_TX_EPNUM);
|
||||
|
||||
/* Check if the Tx buffer contains anything to be sent to the host */
|
||||
if (Tx_Buffer.Elements)
|
||||
{
|
||||
/* Wait until Serial Tx Endpoint Ready for Read/Write */
|
||||
while (!(Endpoint_ReadWriteAllowed()));
|
||||
|
||||
/* Check before sending the data if the endpoint is completely full */
|
||||
bool IsFull = (Endpoint_BytesInEndpoint() == CDC_TXRX_EPSIZE);
|
||||
|
||||
/* Write the transmission buffer contents to the received data endpoint */
|
||||
while (Tx_Buffer.Elements && (Endpoint_BytesInEndpoint() < CDC_TXRX_EPSIZE))
|
||||
Endpoint_Write_Byte(Buffer_GetElement(&Tx_Buffer));
|
||||
|
||||
/* Send the data */
|
||||
Endpoint_ClearCurrentBank();
|
||||
|
||||
/* If a full endpoint was sent, we need to send an empty packet afterwards to terminate the transfer */
|
||||
if (IsFull)
|
||||
{
|
||||
/* Wait until Serial Tx Endpoint Ready for Read/Write */
|
||||
while (!(Endpoint_ReadWriteAllowed()));
|
||||
|
||||
/* Send an empty packet to terminate the transfer */
|
||||
Endpoint_ClearCurrentBank();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Function to manage status updates to the user. This is done via LEDs on the given board, if available, but may be changed to
|
||||
log to a serial port, or anything else that is suitable for status updates.
|
||||
*
|
||||
\param CurrentStatus Current status of the system, from the USBtoSerial_StatusCodes_t enum
|
||||
*/
|
||||
void UpdateStatus(uint8_t CurrentStatus)
|
||||
{
|
||||
uint8_t LEDMask = LEDS_NO_LEDS;
|
||||
|
||||
/* Set the LED mask to the appropriate LED mask based on the given status code */
|
||||
switch (CurrentStatus)
|
||||
{
|
||||
case Status_USBNotReady:
|
||||
LEDMask = (LEDS_LED1);
|
||||
break;
|
||||
case Status_USBEnumerating:
|
||||
LEDMask = (LEDS_LED1 | LEDS_LED2);
|
||||
break;
|
||||
case Status_USBReady:
|
||||
LEDMask = (LEDS_LED2 | LEDS_LED4);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Set the board LEDs to the new LED mask */
|
||||
LEDs_SetAllLEDs(LEDMask);
|
||||
}
|
||||
|
||||
|
||||
/** Reconfigures SPI to match the current serial port settings issued by the host. */
|
||||
void ReconfigureSPI(void)
|
||||
{
|
||||
uint8_t SPCRmask = (1 << SPE) | (1 << MSTR); // always enable SPI as Master
|
||||
uint8_t SPSRmask = 0;
|
||||
|
||||
/* Determine data width */
|
||||
if (LineCoding.ParityType == Parity_Odd) {
|
||||
dataWidth = 16;
|
||||
} else if (LineCoding.ParityType == Parity_Even) {
|
||||
dataWidth = 32;
|
||||
} else if (LineCoding.ParityType == Parity_None) {
|
||||
dataWidth = 8;
|
||||
}
|
||||
|
||||
/* Determine stop bits - 1.5 stop bits is set as 1 stop bit due to hardware limitations */
|
||||
/* For SPI, determine whether format is LSB or MSB */
|
||||
if (LineCoding.CharFormat == TwoStopBits) {
|
||||
SPCRmask |= (1 << DORD);
|
||||
} else if (LineCoding.CharFormat == OneStopBit) {
|
||||
SPCRmask |= (0 << DORD);
|
||||
}
|
||||
|
||||
/* Determine data size - 5, 6, 7, or 8 bits are supported */
|
||||
/* Changing line coding changes SPI Mode
|
||||
CPOL=0, CPHA=0 Sample (Rising) Setup (Falling) SPI-Mode0 == 8 bits line coding
|
||||
CPOL=0, CPHA=1 Setup (Rising) Sample (Falling) SPI-Mode1 == 7 bits line coding
|
||||
CPOL=1, CPHA=0 Sample (Falling) Setup (Rising) SPI-Mode2 == 6 bits line coding
|
||||
CPOL=1, CPHA=1 Setup (Falling) Sample (Rising) SPI-Mode3 == 5 bits line coding
|
||||
*/
|
||||
if (LineCoding.DataBits == 5) {
|
||||
SPCRmask |= ((1 << CPOL) | (1 << CPHA));
|
||||
} else if (LineCoding.DataBits == 6) {
|
||||
SPCRmask |= ((1 << CPOL) | (0 << CPHA));
|
||||
} else if (LineCoding.DataBits == 7) {
|
||||
SPCRmask |= ((0 << CPOL) | (1 << CPHA));
|
||||
} else if (LineCoding.DataBits == 8) {
|
||||
SPCRmask |= ((0 << CPOL) | (0 << CPHA));
|
||||
}
|
||||
|
||||
|
||||
/* Set the USART baud rate register to the desired baud rate value */
|
||||
/* also alter the SPI speed via value of baud rate */
|
||||
if (LineCoding.BaudRateBPS == 9600) { // 2Mhz SPI (Fosc / 4)
|
||||
SPCRmask |= ((0 << SPR1) | (0 << SPR0));
|
||||
SPSRmask |= (0 << SPI2X);
|
||||
} else if (LineCoding.BaudRateBPS == 14400) { // 1Mhz SPI (Fosc / 8)
|
||||
SPCRmask |= ((0 << SPR1) | (1 << SPR0));
|
||||
SPSRmask |= (1 << SPI2X);
|
||||
} else if (LineCoding.BaudRateBPS == 57600) { // 500kHz SPI (Fosc / 16)
|
||||
SPCRmask |= ((0 << SPR1) | (1 << SPR0));
|
||||
SPSRmask |= (0 << SPI2X);
|
||||
} else if (LineCoding.BaudRateBPS == 38400) { // 250kHz SPI (Fosc / 32)
|
||||
SPCRmask |= ((1 << SPR1) | (0 << SPR0));
|
||||
SPSRmask |= (1 << SPI2X);
|
||||
} else if (LineCoding.BaudRateBPS == 19200) { // 125kHz SPI (Fosc / 64)
|
||||
SPCRmask |= ((1 << SPR1) | (0 << SPR0));
|
||||
SPSRmask |= (0 << SPI2X);
|
||||
} else if (LineCoding.BaudRateBPS == 115200) { // 62.5kHz SPI (Fosc / 128)
|
||||
SPCRmask |= ((1 << SPR1) | (1 << SPR0));
|
||||
SPSRmask |= (0 << SPI2X);
|
||||
}
|
||||
|
||||
SPCR = SPCRmask;
|
||||
SPSR = SPSRmask;
|
||||
|
||||
// only read if first run
|
||||
if (firstRun) {
|
||||
tempIOreg = SPSR; //need to read to initiliaze
|
||||
tempIOreg = SPDR; //need to read to initiliaze
|
||||
firstRun = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* process data according to AVR910 protocol */
|
||||
void processHostSPIRequest(void) {
|
||||
|
||||
uint8_t readByte1 = 0;
|
||||
uint8_t readByte2 = 0;
|
||||
uint8_t readByte3 = 0;
|
||||
uint8_t readByte4 = 0;
|
||||
uint8_t firstByte = 0;
|
||||
|
||||
/* Taken from a90isp_ver23.asm:
|
||||
+-------------+------------+------+
|
||||
;* Commands | Host writes | Host reads | |
|
||||
;* -------- +-----+-------+------+-----+ |
|
||||
;* | ID | data | data | | Note |
|
||||
;* +-----------------------------------+-----+-------+------+-----+------+
|
||||
;* | Enter programming mode | 'P' | | | 13d | 1 |
|
||||
;* | Report autoincrement address | 'a' | | | 'Y' | |
|
||||
;* | Set address | 'A' | ah al | | 13d | 2 |
|
||||
;* | Write program memory, low byte | 'c' | dd | | 13d | 3 |
|
||||
;* | Write program memory, high byte | 'C' | dd | | 13d | 3 |
|
||||
;* | Issue Page Write | 'm' | | | 13d | |
|
||||
;* | Read program memory | 'R' | |dd(dd)| | 4 |
|
||||
;* | Write data memory | 'D' | dd | | 13d | |
|
||||
;* | Read data memory | 'd' | | dd | | |
|
||||
;* | Chip erase | 'e' | | | 13d | |
|
||||
;* | Write lock bits | 'l' | dd | | 13d | |
|
||||
;* | Write fuse bits | 'f' | dd | | 13d | 11 |
|
||||
;* | Read fuse and lock bits | 'F' | | dd | | 11 |
|
||||
;* | Leave programming mode | 'L' | | | 13d | 5 |
|
||||
;* | Select device type | 'T' | dd | | 13d | 6 |
|
||||
;* | Read signature bytes | 's' | | 3*dd | | |
|
||||
;* | Return supported device codes | 't' | | n*dd | 00d | 7 |
|
||||
;* | Return software identifier | 'S' | | s[7] | | 8 |
|
||||
;* | Return sofware version | 'V' | |dd dd | | 9 |
|
||||
;* | Return hardware version | 'v' | |dd dd | | 9 |
|
||||
;* | Return programmer type | 'p' | | dd | | 10 |
|
||||
;* | Set LED | 'x' | dd | | 13d | 12 |
|
||||
;* | Clear LED | 'y' | dd | | 13d | 12 |
|
||||
;* | Universial command | ':' | 3*dd | dd | 13d | |
|
||||
;* | New universal command | '.' | 4*dd | dd | 13d | |
|
||||
;* | Special test command | 'Z' | 2*dd | dd | | |
|
||||
*/
|
||||
|
||||
firstByte = Buffer_GetElement(&Rx_Buffer);
|
||||
Buffer_Initialize(&Tx_Buffer); // make sure the buffer is clear before proceeding
|
||||
|
||||
if (firstByte == 'P') { // enter Programming mode
|
||||
// enable SPI -- already done
|
||||
// enter programming mode on target:
|
||||
//PORTB = 0; // set clock to zero
|
||||
RESETPORT = (1 << RESETPIN); // set RESET pin on target to 1
|
||||
RESETPORT2 = (1 << RESETPIN2);
|
||||
delay_ms(DELAY_SHORT);
|
||||
//RESETPORT = (RESETPORT & ~(1 << RESETPIN)); // set RESET pin on target to 0 - Active
|
||||
RESETPORT = 0x00;
|
||||
RESETPORT2 = 0;
|
||||
delay_ms(DELAY_SHORT);
|
||||
SPI_SendByte(0xAC);
|
||||
SPI_SendByte(0x53);
|
||||
SPI_SendByte(0x00);
|
||||
SPI_SendByte(0x00);
|
||||
delay_ms(DELAY_VERYSHORT);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'T') { // Select device type
|
||||
deviceCode = Buffer_GetElement(&Rx_Buffer); // set device type
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'a') { // Report autoincrement address
|
||||
Buffer_StoreElement(&Tx_Buffer, 'Y'); // return 'Y' - Auto-increment enabled
|
||||
|
||||
} else if (firstByte == 'A') { //Load Address
|
||||
// get two bytes over serial and set currAddress to them
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer); // high byte
|
||||
readByte2 = Buffer_GetElement(&Rx_Buffer); // low byte
|
||||
currAddress = (readByte1 << 8) | (readByte2);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'c') { // Write program memory, low byte
|
||||
// send 4 bytes over SPI; 0x40, then Address High Byte, then Low, then data
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
SPI_SendByte(0x40);
|
||||
SPI_SendByte((currAddress >> 8)); // high byte
|
||||
SPI_SendByte((currAddress)); // low byte
|
||||
SPI_SendByte(readByte1); // data
|
||||
delay_ms(DELAY_MEDIUM); // certain MCUs require a delay of about 24585 cycles
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'C') { // Write program memory, high byte
|
||||
// send 4 bytes over SPI; 0x48, then Address High Byte, then Low, then data
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
SPI_SendByte(0x48);
|
||||
SPI_SendByte((currAddress >> 8)); // high byte
|
||||
SPI_SendByte((currAddress)); // low byte
|
||||
SPI_SendByte(readByte1); // data
|
||||
currAddress++; // increment currAddress
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'm') { // Write Program Memory Page
|
||||
// send 4 bytes over SPI; 0x4c, then Address High Byte, then Low, then 0x00
|
||||
SPI_SendByte(0x4C);
|
||||
SPI_SendByte((currAddress >> 8)); // high byte
|
||||
SPI_SendByte((currAddress)); // low byte
|
||||
SPI_SendByte(0x00);
|
||||
delay_ms(DELAY_LONG);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'R') { // Read Program Memory
|
||||
// send 4 bytes over SPI; 0x28, then Address High Byte, then Low, then send back read data from 4th byte over serial
|
||||
SPI_SendByte(0x28);
|
||||
SPI_SendByte((currAddress >> 8)); // high byte
|
||||
SPI_SendByte((currAddress)); // low byte
|
||||
readByte1 = SPI_TransferByte(0x00); // read in data
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte1);
|
||||
// send 4 bytes over SPI; 0x20, then Address High Byte, then Low, then send back read data from 4th byte over serial
|
||||
SPI_SendByte(0x20);
|
||||
SPI_SendByte((currAddress >> 8)); // high byte
|
||||
SPI_SendByte((currAddress)); // low byte
|
||||
readByte2 = SPI_TransferByte(0x00); // read in data
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte2);
|
||||
currAddress++; // increment currAddress
|
||||
|
||||
} else if (firstByte == 'D') { // Write Data Memory
|
||||
// send 4 bytes over SPI; 0xc0, then Address High Byte, then Low, then data
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
SPI_SendByte(0xC0);
|
||||
SPI_SendByte((currAddress >> 8)); // high byte
|
||||
SPI_SendByte((currAddress)); // low byte
|
||||
SPI_SendByte(readByte1); // data
|
||||
delay_ms(DELAY_MEDIUM);
|
||||
currAddress++; // increment currAddress
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'd') { // Read Data Memory
|
||||
// send 4 bytes over SPI; 0xa0, then Address High Byte, then Low, then send back read data from 4th byte over serial
|
||||
SPI_SendByte(0xA0);
|
||||
SPI_SendByte((currAddress >> 8)); // high byte
|
||||
SPI_SendByte((currAddress)); // low byte
|
||||
readByte1 = SPI_TransferByte(0x00); // read in data
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte1);
|
||||
currAddress++; // increment currAddress
|
||||
|
||||
} else if (firstByte == 'e') { // erase the target device
|
||||
// send 4 bytes over SPI; 0xac, 0x80, 0x04, 0x00
|
||||
SPI_SendByte(0xAC);
|
||||
SPI_SendByte(0x80);
|
||||
SPI_SendByte(0x04);
|
||||
SPI_SendByte(0x00);
|
||||
delay_ms(DELAY_LONG);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'l') { // write lock bits
|
||||
// send 4 bytes over SPI; 0xac, [andi s_data 0x06], 0xe0, 0x00
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer); // read in lock bits data
|
||||
SPI_SendByte(0xAC);
|
||||
SPI_SendByte(((0x06 & readByte1) | 0xE0)); // TODO - is this correct???
|
||||
SPI_SendByte(0x00);
|
||||
SPI_SendByte(0x00);
|
||||
delay_ms(DELAY_MEDIUM);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'f') { // write fuse bits
|
||||
// ignore this command, but need to remove data from the receive buffer
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'L') { // leave programming mode
|
||||
RESETPORT |= (1 << RESETPIN); // set RESET pin on target to 1
|
||||
RESETPORT2 |= (1 << RESETPIN2); // set RESET pin on target to 1
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 's') { // Read signature bytes
|
||||
// send 4 bytes over SPI; 0x30, 0x00, 0x02, read and send last byte over serial
|
||||
SPI_SendByte(0x30);
|
||||
SPI_SendByte(0x00);
|
||||
SPI_SendByte(0x02);
|
||||
readByte1 = SPI_TransferByte(0x00); // read in data
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte1);
|
||||
SPI_SendByte(0x30);
|
||||
SPI_SendByte(0x00);
|
||||
SPI_SendByte(0x01);
|
||||
readByte1 = SPI_TransferByte(0x00); // read in data
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte1);
|
||||
SPI_SendByte(0x30);
|
||||
SPI_SendByte(0x00);
|
||||
SPI_SendByte(0x00);
|
||||
readByte1 = SPI_TransferByte(0x00); // read in data
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte1);
|
||||
|
||||
} else if (firstByte == 't') { // Return supported device codes
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE01);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE02);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE03);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE04);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE05);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE06);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE07);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE08);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE09);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE10);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE11);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE12);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE13);
|
||||
Buffer_StoreElement(&Tx_Buffer, AVRDEVCODE14);
|
||||
Buffer_StoreElement(&Tx_Buffer, 0x00);
|
||||
|
||||
} else if (firstByte == 'S') { // Return software identifier
|
||||
// return string[7] with "AVR ISP"
|
||||
Buffer_StoreElement(&Tx_Buffer, 'A');
|
||||
Buffer_StoreElement(&Tx_Buffer, 'V');
|
||||
Buffer_StoreElement(&Tx_Buffer, 'R');
|
||||
Buffer_StoreElement(&Tx_Buffer, 0x20);
|
||||
Buffer_StoreElement(&Tx_Buffer, 'I');
|
||||
Buffer_StoreElement(&Tx_Buffer, 'S');
|
||||
Buffer_StoreElement(&Tx_Buffer, 'P');
|
||||
|
||||
} else if (firstByte == 'V') { // Return sofware version
|
||||
//return two bytes, software Major then Minor
|
||||
Buffer_StoreElement(&Tx_Buffer, '2');
|
||||
Buffer_StoreElement(&Tx_Buffer, '3');
|
||||
|
||||
} else if (firstByte == 'v') { // Return hardware version
|
||||
//return two bytes, hardware Major then Minor
|
||||
Buffer_StoreElement(&Tx_Buffer, ('1'));
|
||||
Buffer_StoreElement(&Tx_Buffer, ('0'));
|
||||
|
||||
} else if (firstByte == 'p') { // Return programmer type
|
||||
// return 'S' for Serial Programmer
|
||||
Buffer_StoreElement(&Tx_Buffer, 'S');
|
||||
|
||||
} else if (firstByte == 'x') { // set LED
|
||||
// ignore this command, but need to remove data from the receive buffer
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'y') { // clear LED
|
||||
// ignore this command, but need to remove data from the receive buffer
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == ':') { // Universal Command
|
||||
// get 3 bytes over serial
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
readByte2 = Buffer_GetElement(&Rx_Buffer);
|
||||
readByte3 = Buffer_GetElement(&Rx_Buffer);
|
||||
SPI_SendByte(readByte1);
|
||||
SPI_SendByte(readByte2);
|
||||
SPI_SendByte(readByte3);
|
||||
readByte1 = SPI_TransferByte(0x00);
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte1);
|
||||
delay_ms(DELAY_MEDIUM);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == '.') { // New Universal Command
|
||||
// get 4 bytes over serial
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
readByte2 = Buffer_GetElement(&Rx_Buffer);
|
||||
readByte3 = Buffer_GetElement(&Rx_Buffer);
|
||||
readByte4 = Buffer_GetElement(&Rx_Buffer);
|
||||
SPI_SendByte(readByte1);
|
||||
SPI_SendByte(readByte2);
|
||||
SPI_SendByte(readByte3);
|
||||
readByte1 = SPI_TransferByte(readByte4);
|
||||
Buffer_StoreElement(&Tx_Buffer, readByte1);
|
||||
delay_ms(DELAY_MEDIUM);
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
|
||||
} else if (firstByte == 'Z') { // Special test command
|
||||
// do nothing, but need to remove data from the receive buffer
|
||||
readByte1 = Buffer_GetElement(&Rx_Buffer);
|
||||
readByte2 = Buffer_GetElement(&Rx_Buffer);
|
||||
|
||||
} else {
|
||||
// do nothing, but need to return with a carriage return
|
||||
Buffer_StoreElement(&Tx_Buffer, CR_HEX); // return carriage return (CR_HEX) if successful
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void delay_ms(uint8_t dly) {
|
||||
uint16_t endtime = 0;
|
||||
|
||||
endtime = TCNT1;
|
||||
if (endtime > 63486) {
|
||||
endtime = (dly * DELAY_MULTIPLE);
|
||||
} else {
|
||||
endtime += (dly * DELAY_MULTIPLE);
|
||||
}
|
||||
|
||||
timerval = TCNT1;
|
||||
while (timerval < endtime) {
|
||||
timerval = TCNT1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Header file for USBtoSerial.c.
|
||||
*/
|
||||
|
||||
#ifndef _AVRISP_PROGRAMMER_H_
|
||||
#define _AVRISP_PROGRAMMER_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
#include "RingBuff.h"
|
||||
|
||||
#include <LUFA/Version.h> // Library Version Information
|
||||
#include <LUFA/Common/ButtLoadTag.h> // PROGMEM tags readable by the ButtLoad project
|
||||
#include <LUFA/Drivers/USB/USB.h> // USB Functionality
|
||||
#include <LUFA/Drivers/AT90USBXXX/SPI.h> // SPI driver
|
||||
#include <LUFA/Drivers/Board/LEDs.h> // LEDs driver
|
||||
#include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
|
||||
|
||||
/* Macros: */
|
||||
/** CDC Class specific request to get the current virtual serial port configuration settings. */
|
||||
#define REQ_GetLineEncoding 0x21
|
||||
|
||||
/** CDC Class specific request to set the current virtual serial port configuration settings. */
|
||||
#define REQ_SetLineEncoding 0x20
|
||||
|
||||
/** CDC Class specific request to set the current virtual serial port handshake line states. */
|
||||
#define REQ_SetControlLineState 0x22
|
||||
|
||||
/** Notification type constant for a change in the virtual serial port handshake line states, for
|
||||
* use with a USB_Notification_Header_t notification structure when sent to the host via the CDC
|
||||
* notification endpoint.
|
||||
*/
|
||||
#define NOTIF_SerialState 0x20
|
||||
|
||||
/** Mask for the DTR handshake line for use with the REQ_SetControlLineState class specific request
|
||||
* from the host, to indicate that the DTR line state should be high.
|
||||
*/
|
||||
#define CONTROL_LINE_OUT_DTR (1 << 0)
|
||||
|
||||
/** Mask for the RTS handshake line for use with the REQ_SetControlLineState class specific request
|
||||
* from the host, to indicate that theRTS line state should be high.
|
||||
*/
|
||||
#define CONTROL_LINE_OUT_RTS (1 << 1)
|
||||
|
||||
/** Mask for the DCD handshake line for use with the a NOTIF_SerialState class specific notification
|
||||
* from the device to the host, to indicate that the DCD line state is currently high.
|
||||
*/
|
||||
#define CONTROL_LINE_IN_DCD (1 << 0)
|
||||
|
||||
/** Mask for the DSR handshake line for use with the a NOTIF_SerialState class specific notification
|
||||
* from the device to the host, to indicate that the DSR line state is currently high.
|
||||
*/
|
||||
#define CONTROL_LINE_IN_DSR (1 << 1)
|
||||
|
||||
/** Mask for the BREAK handshake line for use with the a NOTIF_SerialState class specific notification
|
||||
* from the device to the host, to indicate that the BREAK line state is currently high.
|
||||
*/
|
||||
#define CONTROL_LINE_IN_BREAK (1 << 2)
|
||||
|
||||
/** Mask for the RING handshake line for use with the a NOTIF_SerialState class specific notification
|
||||
* from the device to the host, to indicate that the RING line state is currently high.
|
||||
*/
|
||||
#define CONTROL_LINE_IN_RING (1 << 3)
|
||||
|
||||
/** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
|
||||
* to indicate that a framing error has ocurred on the virtual serial port.
|
||||
*/
|
||||
#define CONTROL_LINE_IN_FRAMEERROR (1 << 4)
|
||||
|
||||
/** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
|
||||
* to indicate that a parity error has ocurred on the virtual serial port.
|
||||
*/
|
||||
#define CONTROL_LINE_IN_PARITYERROR (1 << 5)
|
||||
|
||||
/** Mask for use with the a NOTIF_SerialState class specific notification from the device to the host,
|
||||
* to indicate that a data overrun error has ocurred on the virtual serial port.
|
||||
*/
|
||||
#define CONTROL_LINE_IN_OVERRUNERROR (1 << 6)
|
||||
|
||||
/* Event Handlers: */
|
||||
/** Indicates that this module will catch the USB_Connect event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_Connect);
|
||||
|
||||
/** Indicates that this module will catch the USB_Disconnect event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_Disconnect);
|
||||
|
||||
/** Indicates that this module will catch the USB_ConfigurationChanged event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_ConfigurationChanged);
|
||||
|
||||
/** Indicates that this module will catch the USB_UnhandledControlPacket event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_UnhandledControlPacket);
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for the virtual serial port line encoding settings, for storing the current USART configuration
|
||||
* as set by the host via a class specific request.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t BaudRateBPS; /**< Baud rate of the virtual serial port, in bits per second */
|
||||
uint8_t CharFormat; /**< Character format of the virtual serial port, a value from the
|
||||
* CDCDevice_CDC_LineCodingFormats_t enum
|
||||
*/
|
||||
uint8_t ParityType; /**< Parity setting of the virtual serial port, a value from the
|
||||
* CDCDevice_LineCodingParity_t enum
|
||||
*/
|
||||
uint8_t DataBits; /**< Bits of data per charater of the virtual serial port */
|
||||
} CDC_Line_Coding_t;
|
||||
|
||||
/** Type define for a CDC notification, sent to the host via the CDC notification endpoint to indicate a
|
||||
* change in the device state asynchronously.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t NotificationType; /**< Notification type, a mask of REQDIR_*, REQTYPE_* and REQREC_* constants
|
||||
* from the library StdRequestType.h header
|
||||
*/
|
||||
uint8_t Notification; /**< Notification value, a NOTIF_* constant */
|
||||
uint16_t wValue; /**< Notification wValue, notification-specific */
|
||||
uint16_t wIndex; /**< Notification wIndex, notification-specific */
|
||||
uint16_t wLength; /**< Notification wLength, notification-specific */
|
||||
} USB_Notification_Header_t;
|
||||
|
||||
/* Enums: */
|
||||
/** Enum for the possible line encoding formats of a virtual serial port. */
|
||||
enum CDCDevice_CDC_LineCodingFormats_t
|
||||
{
|
||||
OneStopBit = 0, /**< Each frame contains one stop bit */
|
||||
OneAndAHalfStopBits = 1, /**< Each frame contains one and a half stop bits */
|
||||
TwoStopBits = 2, /**< Each frame contains two stop bits */
|
||||
};
|
||||
|
||||
/** Enum for the possible line encoding parity settings of a virtual serial port. */
|
||||
enum CDCDevice_LineCodingParity_t
|
||||
{
|
||||
Parity_None = 0, /**< No parity bit mode on each frame */
|
||||
Parity_Odd = 1, /**< Odd parity bit mode on each frame */
|
||||
Parity_Even = 2, /**< Even parity bit mode on each frame */
|
||||
Parity_Mark = 3, /**< Mark parity bit mode on each frame */
|
||||
Parity_Space = 4, /**< Space parity bit mode on each frame */
|
||||
};
|
||||
|
||||
/** Enum for the possible status codes for passing to the UpdateStatus() function. */
|
||||
enum USBtoSerial_StatusCodes_t
|
||||
{
|
||||
Status_USBNotReady = 0, /**< USB is not ready (disconnected from a USB host) */
|
||||
Status_USBEnumerating = 1, /**< USB interface is enumerating */
|
||||
Status_USBReady = 2, /**< USB interface is connected and ready */
|
||||
};
|
||||
|
||||
/* Tasks: */
|
||||
TASK(CDC_Task);
|
||||
|
||||
/* Function Prototypes: */
|
||||
void ReconfigureSPI(void);
|
||||
void UpdateStatus(uint8_t CurrentStatus);
|
||||
void processHostSPIRequest(void);
|
||||
void delay_ms(uint8_t dly);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,89 @@
|
|||
/** \file
|
||||
*
|
||||
* This file contains special DoxyGen information for the generation of the main page and other special
|
||||
* documentation pages. It is not a project source file.
|
||||
*/
|
||||
|
||||
/** \mainpage AVRISP_Programmer
|
||||
*
|
||||
* Communications Device Class demonstration application.
|
||||
* This gives a simple reference application for implementing
|
||||
* a USB to Serial converter using the CDC class. Data communicated
|
||||
* over the USB Virtual Serial Port according to Atmel's AVR910
|
||||
* protocol is used to program AVR MCUs that are
|
||||
* "In-System Programmable via SPI Port".
|
||||
*
|
||||
* After running this firmware for the first time on a new computer,
|
||||
* you will need to supply the .INF file located in this demo
|
||||
* project's directory as the device's driver when running under
|
||||
* Windows. This will enable Windows to use its inbuilt CDC drivers,
|
||||
* negating the need for custom drivers for the device. Other
|
||||
* Operating Systems should automatically use their own inbuilt
|
||||
* CDC-ACM drivers.
|
||||
*
|
||||
* Usage:
|
||||
* avrdude -vv -F -P COM7 -c avr910 -p t261
|
||||
* Note -F flag which overrides signature check and enables programming
|
||||
* of any "In-System Programmable via SPI Port" AVR MCU. Part number,
|
||||
* t261, should be set to your target device.
|
||||
* avrdude -vv -F -P COM7 -c avr910 -p t261 -U flash:w:PROG.hex
|
||||
* PROG.hex is the hex file to program your t261 AVR with
|
||||
* avrdude -vv -F -P COM7 -b 115200 -c avr910 -p t261 -U flash:w:test.hex
|
||||
* The -b 115200 sets the SPI clock to 62.5kHz from the default 125kHz and may
|
||||
* work when the default programming speed fails.
|
||||
* AVROSP.exe -dATtiny261 -cCOM7 -rf
|
||||
* AVRosp is the Open Source AVR ISP Programming Software available from Atmel.com
|
||||
*
|
||||
* Note: on Linux systems, COM7 should be replaced with someting like /dev/ttyACM0
|
||||
* You can determine this value by running dmesg after plugging in the device
|
||||
* Note: you must RESET the programmer after each use (AVRdude session).
|
||||
*
|
||||
* Note: If you experience errors with older devices, try changing DELAY_LONG
|
||||
* to a larger value, such as 0xFF in AVRISP_Programmer.c
|
||||
*
|
||||
* MISO, MOSI, and SCK are connected directly from the AVRopendous board
|
||||
* to the pin of the same functionality on the target. RESET pin on the target
|
||||
* can be connected either to SS (PB0), or PC2. Do not have any other pins
|
||||
* connected - especially HWB pin, to avoid unintentional behaviour.
|
||||
*
|
||||
* AVR910 functionality was overlayed on USBtoSerial functionality.
|
||||
* Keep this in mind when looking over the code.
|
||||
* Default target speed is 125kHz and corresponds to 19200 baud, which
|
||||
* is the default setting for AVRdude.
|
||||
*
|
||||
* Changing "Baud-Rate" will change the SPI speed. Defualt SPI clock speed
|
||||
* is 8Mhz / 4 = 2MHz. 8Mhz is the device clock speed. This is the setting at
|
||||
* 9600 baud. The following is a table of baud-rate vs. SPI Speed that will result
|
||||
* 9600 = 2Mhz
|
||||
* 14400 = 1MHz
|
||||
* 19200 = 125kHz (AVRdude Default)
|
||||
* 38400 = 250kHz
|
||||
* 57600 = 500kHz
|
||||
* 115200 = 62.5kHz
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td><b>USB Mode:</b></td>
|
||||
* <td>Device</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>USB Class:</b></td>
|
||||
* <td>Communications Device Class (CDC)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>USB Subclass:</b></td>
|
||||
* <td>Abstract Control Model (ACM)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Relevant Standards:</b></td>
|
||||
* <td>USBIF CDC Class Standard</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Usable Speeds:</b></td>
|
||||
* <td>Full Speed Mode</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*/
|
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
|
||||
* computer-readable structures which the host requests upon device enumeration, to determine
|
||||
* the device's capabilities and functions.
|
||||
*/
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
|
||||
* device characteristics, including the supported USB version, control endpoint size and the
|
||||
* number of device configurations. The descriptor is read out by the USB host when the enumeration
|
||||
* process begins.
|
||||
*/
|
||||
USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Device_t), Type: DTYPE_Device},
|
||||
|
||||
USBSpecification: VERSION_BCD(01.10),
|
||||
Class: 0x02,
|
||||
SubClass: 0x00,
|
||||
Protocol: 0x00,
|
||||
|
||||
Endpoint0Size: 8,
|
||||
|
||||
VendorID: 0x03EB,
|
||||
ProductID: 0x204F,
|
||||
ReleaseNumber: 0x0000,
|
||||
|
||||
ManufacturerStrIndex: 0x01,
|
||||
ProductStrIndex: 0x02,
|
||||
SerialNumStrIndex: NO_DESCRIPTOR,
|
||||
|
||||
NumberOfConfigurations: 1
|
||||
};
|
||||
|
||||
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
|
||||
* of the device in one of its supported configurations, including information about any device interfaces
|
||||
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
|
||||
* a configuration so that the host may correctly communicate with the USB device.
|
||||
*/
|
||||
USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
{
|
||||
Config:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Configuration_Header_t), Type: DTYPE_Configuration},
|
||||
|
||||
TotalConfigurationSize: sizeof(USB_Descriptor_Configuration_t),
|
||||
TotalInterfaces: 2,
|
||||
|
||||
ConfigurationNumber: 1,
|
||||
ConfigurationStrIndex: NO_DESCRIPTOR,
|
||||
|
||||
ConfigAttributes: (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELFPOWERED),
|
||||
|
||||
MaxPowerConsumption: USB_CONFIG_POWER_MA(100)
|
||||
},
|
||||
|
||||
CCI_Interface:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Interface_t), Type: DTYPE_Interface},
|
||||
|
||||
InterfaceNumber: 0,
|
||||
AlternateSetting: 0,
|
||||
|
||||
TotalEndpoints: 1,
|
||||
|
||||
Class: 0x02,
|
||||
SubClass: 0x02,
|
||||
Protocol: 0x01,
|
||||
|
||||
InterfaceStrIndex: NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
CDC_Functional_IntHeader:
|
||||
{
|
||||
Header: {Size: sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), Type: 0x24},
|
||||
SubType: 0x00,
|
||||
|
||||
Data: {0x01, 0x10}
|
||||
},
|
||||
|
||||
CDC_Functional_CallManagement:
|
||||
{
|
||||
Header: {Size: sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), Type: 0x24},
|
||||
SubType: 0x01,
|
||||
|
||||
Data: {0x03, 0x01}
|
||||
},
|
||||
|
||||
CDC_Functional_AbstractControlManagement:
|
||||
{
|
||||
Header: {Size: sizeof(CDC_FUNCTIONAL_DESCRIPTOR(1)), Type: 0x24},
|
||||
SubType: 0x02,
|
||||
|
||||
Data: {0x06}
|
||||
},
|
||||
|
||||
CDC_Functional_Union:
|
||||
{
|
||||
Header: {Size: sizeof(CDC_FUNCTIONAL_DESCRIPTOR(2)), Type: 0x24},
|
||||
SubType: 0x06,
|
||||
|
||||
Data: {0x00, 0x01}
|
||||
},
|
||||
|
||||
ManagementEndpoint:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Endpoint_t), Type: DTYPE_Endpoint},
|
||||
|
||||
EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_NOTIFICATION_EPNUM),
|
||||
Attributes: EP_TYPE_INTERRUPT,
|
||||
EndpointSize: CDC_NOTIFICATION_EPSIZE,
|
||||
PollingIntervalMS: 0xFF
|
||||
},
|
||||
|
||||
DCI_Interface:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Interface_t), Type: DTYPE_Interface},
|
||||
|
||||
InterfaceNumber: 1,
|
||||
AlternateSetting: 0,
|
||||
|
||||
TotalEndpoints: 2,
|
||||
|
||||
Class: 0x0A,
|
||||
SubClass: 0x00,
|
||||
Protocol: 0x00,
|
||||
|
||||
InterfaceStrIndex: NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
DataOutEndpoint:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Endpoint_t), Type: DTYPE_Endpoint},
|
||||
|
||||
EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_OUT | CDC_RX_EPNUM),
|
||||
Attributes: EP_TYPE_BULK,
|
||||
EndpointSize: CDC_TXRX_EPSIZE,
|
||||
PollingIntervalMS: 0x00
|
||||
},
|
||||
|
||||
DataInEndpoint:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Endpoint_t), Type: DTYPE_Endpoint},
|
||||
|
||||
EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_IN | CDC_TX_EPNUM),
|
||||
Attributes: EP_TYPE_BULK,
|
||||
EndpointSize: CDC_TXRX_EPSIZE,
|
||||
PollingIntervalMS: 0x00
|
||||
}
|
||||
};
|
||||
|
||||
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
|
||||
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
|
||||
* via the language ID table available at USB.org what languages the device supports for its string descriptors.
|
||||
*/
|
||||
USB_Descriptor_String_t PROGMEM LanguageString =
|
||||
{
|
||||
Header: {Size: USB_STRING_LEN(1), Type: DTYPE_String},
|
||||
|
||||
UnicodeString: {LANGUAGE_ID_ENG}
|
||||
};
|
||||
|
||||
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
|
||||
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
|
||||
* Descriptor.
|
||||
*/
|
||||
USB_Descriptor_String_t PROGMEM ManufacturerString =
|
||||
{
|
||||
Header: {Size: USB_STRING_LEN(19), Type: DTYPE_String},
|
||||
|
||||
UnicodeString: L"www.AVRopendous.org"
|
||||
};
|
||||
|
||||
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
|
||||
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
|
||||
* Descriptor.
|
||||
*/
|
||||
USB_Descriptor_String_t PROGMEM ProductString =
|
||||
{
|
||||
Header: {Size: USB_STRING_LEN(29), Type: DTYPE_String},
|
||||
|
||||
UnicodeString: L"LUFA-Based AVR ISP Programmer"
|
||||
};
|
||||
|
||||
/** This function is called by the library when in device mode, and must be overridden (see StdDescriptors.h
|
||||
* documentation) by the application code so that the address and size of a requested descriptor can be given
|
||||
* to the USB library. When the device recieves a Get Descriptor request on the control endpoint, this function
|
||||
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
|
||||
* USB host.
|
||||
*/
|
||||
uint16_t USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
|
||||
{
|
||||
const uint8_t DescriptorType = (wValue >> 8);
|
||||
const uint8_t DescriptorNumber = (wValue & 0xFF);
|
||||
|
||||
void* Address = NULL;
|
||||
uint16_t Size = NO_DESCRIPTOR;
|
||||
|
||||
switch (DescriptorType)
|
||||
{
|
||||
case DTYPE_Device:
|
||||
Address = DESCRIPTOR_ADDRESS(DeviceDescriptor);
|
||||
Size = sizeof(USB_Descriptor_Device_t);
|
||||
break;
|
||||
case DTYPE_Configuration:
|
||||
Address = DESCRIPTOR_ADDRESS(ConfigurationDescriptor);
|
||||
Size = sizeof(USB_Descriptor_Configuration_t);
|
||||
break;
|
||||
case DTYPE_String:
|
||||
switch (DescriptorNumber)
|
||||
{
|
||||
case 0x00:
|
||||
Address = DESCRIPTOR_ADDRESS(LanguageString);
|
||||
Size = pgm_read_byte(&LanguageString.Header.Size);
|
||||
break;
|
||||
case 0x01:
|
||||
Address = DESCRIPTOR_ADDRESS(ManufacturerString);
|
||||
Size = pgm_read_byte(&ManufacturerString.Header.Size);
|
||||
break;
|
||||
case 0x02:
|
||||
Address = DESCRIPTOR_ADDRESS(ProductString);
|
||||
Size = pgm_read_byte(&ProductString.Header.Size);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
*DescriptorAddress = Address;
|
||||
return Size;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Header file for Descriptors.c.
|
||||
*/
|
||||
|
||||
#ifndef _DESCRIPTORS_H_
|
||||
#define _DESCRIPTORS_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
/* Macros: */
|
||||
/** Macro to define a CDC class-specific functional descriptor. CDC functional descriptors have a
|
||||
* uniform structure but variable sized data payloads, thus cannot be represented accurately by
|
||||
* a single typedef struct. A macro is used instead so that functional descriptors can be created
|
||||
* easily by specifying the size of the payload. This allows sizeof() to work correctly.
|
||||
*
|
||||
* \param DataSize Size in bytes of the CDC functional descriptor's data payload
|
||||
*/
|
||||
#define CDC_FUNCTIONAL_DESCRIPTOR(DataSize) \
|
||||
struct \
|
||||
{ \
|
||||
USB_Descriptor_Header_t Header; \
|
||||
uint8_t SubType; \
|
||||
uint8_t Data[DataSize]; \
|
||||
}
|
||||
|
||||
/** Endpoint number of the CDC device-to-host notification IN endpoint. */
|
||||
#define CDC_NOTIFICATION_EPNUM 2
|
||||
|
||||
/** Endpoint number of the CDC device-to-host data IN endpoint. */
|
||||
#define CDC_TX_EPNUM 3
|
||||
|
||||
/** Endpoint number of the CDC host-to-device data OUT endpoint. */
|
||||
#define CDC_RX_EPNUM 4
|
||||
|
||||
/** Size in bytes of the CDC device-to-host notification IN endpoint. */
|
||||
#define CDC_NOTIFICATION_EPSIZE 8
|
||||
|
||||
/** Size in bytes of the CDC data IN and OUT endpoints. */
|
||||
#define CDC_TXRX_EPSIZE 16
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for the device configuration descriptor structure. This must be defined in the
|
||||
* application code, as the configuration descriptor contains several sub-descriptors which
|
||||
* vary between devices, and which describe the device's usage to the host.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
USB_Descriptor_Configuration_Header_t Config;
|
||||
USB_Descriptor_Interface_t CCI_Interface;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_IntHeader;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_CallManagement;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(1) CDC_Functional_AbstractControlManagement;
|
||||
CDC_FUNCTIONAL_DESCRIPTOR(2) CDC_Functional_Union;
|
||||
USB_Descriptor_Endpoint_t ManagementEndpoint;
|
||||
USB_Descriptor_Interface_t DCI_Interface;
|
||||
USB_Descriptor_Endpoint_t DataOutEndpoint;
|
||||
USB_Descriptor_Endpoint_t DataInEndpoint;
|
||||
} USB_Descriptor_Configuration_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
uint16_t USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,55 @@
|
|||
; Windows LUFA USB to Serial Setup File
|
||||
; Copyright (c) 2000 Microsoft Corporation
|
||||
|
||||
[Version]
|
||||
Signature="$Windows NT$"
|
||||
Class=Ports
|
||||
ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
|
||||
Provider=%COMPANY%
|
||||
LayoutFile=layout.inf
|
||||
DriverVer=06/06/2006,1.0.0.0
|
||||
|
||||
[Manufacturer]
|
||||
%MFGNAME% = ManufName
|
||||
|
||||
[DestinationDirs]
|
||||
DefaultDestDir=12
|
||||
|
||||
[ManufName]
|
||||
%Modem3% = Modem3, USB\VID_03EB&PID_204B
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; Windows 2000/XP Sections
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
[Modem3.nt]
|
||||
CopyFiles=USBModemCopyFileSection
|
||||
AddReg=Modem3.nt.AddReg
|
||||
|
||||
[USBModemCopyFileSection]
|
||||
usbser.sys,,,0x20
|
||||
|
||||
[Modem3.nt.AddReg]
|
||||
HKR,,DevLoader,,*ntkern
|
||||
HKR,,NTMPDriver,,usbser.sys
|
||||
HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
|
||||
|
||||
[Modem3.nt.Services]
|
||||
AddService=usbser, 0x00000002, DriverService
|
||||
|
||||
[DriverService]
|
||||
DisplayName=%SERVICE%
|
||||
ServiceType=1
|
||||
StartType=3
|
||||
ErrorControl=1
|
||||
ServiceBinary=%12%\usbser.sys
|
||||
|
||||
;------------------------------------------------------------------------------
|
||||
; String Definitions
|
||||
;------------------------------------------------------------------------------
|
||||
|
||||
[Strings]
|
||||
COMPANY="LUFA Library"
|
||||
MFGNAME="Dean Camera"
|
||||
Modem3="USB Virtual Serial Port"
|
||||
SERVICE="USB Virtual Serial Port CDC Driver"
|
|
@ -0,0 +1,120 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
#include "RingBuff.h"
|
||||
|
||||
void Buffer_Initialize(RingBuff_t* Buffer)
|
||||
{
|
||||
BUFF_ATOMIC_BLOCK
|
||||
{
|
||||
Buffer->InPtr = (RingBuff_Data_t*)&Buffer->Buffer;
|
||||
Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;
|
||||
Buffer->Elements = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Buffer_StoreElement(RingBuff_t* Buffer, RingBuff_Data_t Data)
|
||||
{
|
||||
BUFF_ATOMIC_BLOCK
|
||||
{
|
||||
#if defined(BUFF_DROPOLD)
|
||||
if (Buffer->Elements == BUFF_LENGTH)
|
||||
{
|
||||
Buffer->OutPtr++;
|
||||
|
||||
if (Buffer->OutPtr == &Buffer->Buffer[BUFF_LENGTH])
|
||||
Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
Buffer->Elements++;
|
||||
}
|
||||
#elif defined(BUFF_DROPNEW)
|
||||
if (Buffer->Elements == BUFF_LENGTH)
|
||||
return;
|
||||
|
||||
Buffer->Elements++;
|
||||
#elif defined(BUFF_NODROPCHECK)
|
||||
Buffer->Elements++;
|
||||
#endif
|
||||
|
||||
*(Buffer->InPtr) = Data;
|
||||
Buffer->InPtr++;
|
||||
|
||||
if (Buffer->InPtr == &Buffer->Buffer[BUFF_LENGTH])
|
||||
Buffer->InPtr = (RingBuff_Data_t*)&Buffer->Buffer;
|
||||
}
|
||||
}
|
||||
|
||||
RingBuff_Data_t Buffer_GetElement(RingBuff_t* Buffer)
|
||||
{
|
||||
RingBuff_Data_t BuffData;
|
||||
|
||||
BUFF_ATOMIC_BLOCK
|
||||
{
|
||||
#if defined(BUFF_EMPTYRETURNSZERO)
|
||||
if (!(Buffer->Elements))
|
||||
return 0;
|
||||
#elif !defined(BUFF_NOEMPTYCHECK)
|
||||
#error No empty buffer check behaviour specified.
|
||||
#endif
|
||||
|
||||
BuffData = *(Buffer->OutPtr);
|
||||
|
||||
Buffer->OutPtr++;
|
||||
Buffer->Elements--;
|
||||
|
||||
if (Buffer->OutPtr == &Buffer->Buffer[BUFF_LENGTH])
|
||||
Buffer->OutPtr = (RingBuff_Data_t*)&Buffer->Buffer;
|
||||
}
|
||||
|
||||
return BuffData;
|
||||
}
|
||||
|
||||
#if defined(BUFF_USEPEEK)
|
||||
RingBuff_Data_t Buffer_PeekElement(const RingBuff_t* Buffer)
|
||||
{
|
||||
RingBuff_Data_t BuffData;
|
||||
|
||||
BUFF_ATOMIC_BLOCK
|
||||
{
|
||||
#if defined(BUFF_EMPTYRETURNSZERO)
|
||||
if (!(Buffer->Elements))
|
||||
return 0;
|
||||
#elif !defined(BUFF_NOEMPTYCHECK)
|
||||
#error No empty buffer check behaviour specified.
|
||||
#endif
|
||||
|
||||
BuffData = *(Buffer->OutPtr);
|
||||
}
|
||||
|
||||
return BuffData;
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/* Buffer Configuration: */
|
||||
/* Buffer length - select static size of created ringbuffers: */
|
||||
#define BUFF_STATICSIZE 128 // Set to the static ringbuffer size for all ringbuffers (place size after define)
|
||||
|
||||
/* Volatile mode - uncomment to make buffers volatile, for use in ISRs, etc: */
|
||||
#define BUFF_VOLATILE // Uncomment to cause all ring buffers to become volatile (and atomic if multi-byte) in access
|
||||
|
||||
/* Drop mode - select behaviour when Buffer_StoreElement called on a full buffer: */
|
||||
#define BUFF_DROPOLD // Uncomment to cause full ring buffers to drop the oldest character to make space when full
|
||||
// #define BUFF_DROPNEW // Uncomment to cause full ring buffers to drop the new character when full
|
||||
// #define BUFF_NODROPCHECK // Uncomment to ignore full ring buffer checks - checking left to user!
|
||||
|
||||
/* Underflow behaviour - select behaviour when Buffer_GetElement is called with an empty ringbuffer: */
|
||||
//#define BUFF_EMPTYRETURNSZERO // Uncomment to return 0 when an empty ringbuffer is read
|
||||
#define BUFF_NOEMPTYCHECK // Uncomment to disable checking of empty ringbuffers - checking left to user!
|
||||
|
||||
/* Buffer storage type - set the datatype for the stored data */
|
||||
#define BUFF_DATATYPE uint8_t // Change to the data type that is going to be stored into the buffer
|
||||
|
||||
/* Peek routine - uncomment to include the peek routine (fetches next byte without removing it from the buffer */
|
||||
#define BUFF_USEPEEK
|
||||
|
||||
#ifndef _RINGBUFF_H_
|
||||
#define _RINGBUFF_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <util/atomic.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <LUFA/Common/Common.h>
|
||||
|
||||
/* Defines and checks: */
|
||||
#if defined(BUFF_STATICSIZE)
|
||||
#define BUFF_LENGTH BUFF_STATICSIZE
|
||||
#else
|
||||
#error No buffer length specified!
|
||||
#endif
|
||||
|
||||
#if !(defined(BUFF_DROPOLD) || defined(BUFF_DROPNEW) || defined(BUFF_NODROPCHECK))
|
||||
#error No buffer drop mode specified.
|
||||
#endif
|
||||
|
||||
#if !defined(BUFF_DATATYPE)
|
||||
#error Ringbuffer storage data type not specified.
|
||||
#endif
|
||||
|
||||
#if defined(BUFF_VOLATILE)
|
||||
#define BUFF_MODE volatile
|
||||
#define BUFF_ATOMIC_BLOCK ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
|
||||
#else
|
||||
#define BUFF_MODE
|
||||
#define BUFF_ATOMIC_BLOCK
|
||||
#endif
|
||||
|
||||
#if (BUFF_STATICSIZE > LONG_MAX)
|
||||
#define RingBuff_Elements_t uint64_t
|
||||
#elif (BUFF_STATICSIZE > INT_MAX)
|
||||
#define RingBuff_Elements_t uint32_t
|
||||
#elif (BUFF_STATICSIZE > CHAR_MAX)
|
||||
#define RingBuff_Elements_t uint16_t
|
||||
#else
|
||||
#define RingBuff_Elements_t uint8_t
|
||||
#endif
|
||||
|
||||
/* Type Defines: */
|
||||
typedef BUFF_DATATYPE RingBuff_Data_t;
|
||||
|
||||
typedef BUFF_MODE struct
|
||||
{
|
||||
RingBuff_Data_t Buffer[BUFF_LENGTH];
|
||||
RingBuff_Data_t* InPtr;
|
||||
RingBuff_Data_t* OutPtr;
|
||||
RingBuff_Elements_t Elements;
|
||||
} RingBuff_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
void Buffer_Initialize(RingBuff_t* Buff);
|
||||
void Buffer_StoreElement(RingBuff_t* Buffer, RingBuff_Data_t Data);
|
||||
RingBuff_Data_t Buffer_GetElement(RingBuff_t* Buffer);
|
||||
#if defined(BUFF_USEPEEK)
|
||||
RingBuff_Data_t Buffer_PeekElement(const RingBuff_t* Buffer);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,104 @@
|
|||
ubuntu@ubuntu:~/LUFA/Bootloaders/LUFA_DFU_Bootloader_AT90USB162$ sudo avrdude -vv -F -P /dev/ttyACM0 -c avr910 -p usb162 -U flash:w:BootloaderDFU.hex
|
||||
|
||||
avrdude: Version 5.5, compiled on May 9 2008 at 13:04:46
|
||||
Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
|
||||
|
||||
System wide configuration file is "/etc/avrdude.conf"
|
||||
User configuration file is "/home/ubuntu/.avrduderc"
|
||||
User configuration file does not exist or is not a regular file, skipping
|
||||
|
||||
Using Port : /dev/ttyACM0
|
||||
Using Programmer : avr910
|
||||
AVR Part : AT90USB162
|
||||
Chip Erase delay : 9000 us
|
||||
PAGEL : PD7
|
||||
BS2 : PA0
|
||||
RESET disposition : dedicated
|
||||
RETRY pulse : SCK
|
||||
serial program mode : yes
|
||||
parallel program mode : yes
|
||||
Timeout : 200
|
||||
StabDelay : 100
|
||||
CmdexeDelay : 25
|
||||
SyncLoops : 32
|
||||
ByteDelay : 0
|
||||
PollIndex : 3
|
||||
PollValue : 0x53
|
||||
Memory Detail :
|
||||
|
||||
Block Poll Page Polled
|
||||
Memory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack
|
||||
----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------
|
||||
eeprom 65 10 8 0 no 512 4 0 9000 9000 0x00 0x00
|
||||
flash 65 6 128 0 yes 16384 128 128 4500 4500 0x00 0x00
|
||||
lfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
|
||||
hfuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
|
||||
efuse 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
|
||||
lock 0 0 0 0 no 1 0 0 9000 9000 0x00 0x00
|
||||
calibration 0 0 0 0 no 1 0 0 0 0 0x00 0x00
|
||||
signature 0 0 0 0 no 3 0 0 0 0 0x00 0x00
|
||||
|
||||
Programmer Type : avr910
|
||||
Description : Atmel Low Cost Serial Programmer
|
||||
|
||||
Found programmer: Id = "AVR ISP"; type = S
|
||||
Software Version = 2.3; Hardware Version = 1.0
|
||||
Programmer supports auto addr increment.
|
||||
|
||||
Programmer supports the following devices:
|
||||
Device code: 0x55 = ATtiny12
|
||||
Device code: 0x56 = ATtiny15
|
||||
Device code: 0x5e = ATtiny2313
|
||||
Device code: 0x76 = ATMEGA8
|
||||
Device code: 0x74 = ATMEGA6450
|
||||
Device code: 0x72 = ATMEGA32
|
||||
Device code: 0x45 = ATMEGA64
|
||||
Device code: 0x74 = ATMEGA6450
|
||||
Device code: 0x43 = ATMEGA128
|
||||
Device code: 0x63 = ATMEGA162
|
||||
Device code: 0x78 = ATMEGA169
|
||||
Device code: 0x6c = AT90S4434
|
||||
Device code: 0x38 = AT90S8515
|
||||
Device code: 0x65 = (unknown)
|
||||
|
||||
avrdude: warning: selected device is not supported by programmer: usb162
|
||||
avrdude: AVR device initialized and ready to accept instructions
|
||||
|
||||
Reading | ################################################## | 100% 0.00s
|
||||
|
||||
avrdude: Device signature = 0x1e9482
|
||||
avrdude: safemode: lfuse reads as 5E
|
||||
avrdude: safemode: hfuse reads as D9
|
||||
avrdude: safemode: efuse reads as F4
|
||||
avrdude: NOTE: FLASH memory has been specified, an erase cycle will be performed
|
||||
To disable this feature, specify the -D option.
|
||||
avrdude: erasing chip
|
||||
avrdude: reading input file "BootloaderDFU.hex"
|
||||
avrdude: input file BootloaderDFU.hex auto detected as Intel Hex
|
||||
avrdude: writing flash (16066 bytes):
|
||||
|
||||
Writing | ################################################## | 100% 33.39s
|
||||
|
||||
|
||||
|
||||
avrdude: 16066 bytes of flash written
|
||||
avrdude: verifying flash memory against BootloaderDFU.hex:
|
||||
avrdude: load data flash data from input file BootloaderDFU.hex:
|
||||
avrdude: input file BootloaderDFU.hex auto detected as Intel Hex
|
||||
avrdude: input file BootloaderDFU.hex contains 16066 bytes
|
||||
avrdude: reading on-chip flash data:
|
||||
|
||||
Reading | ################################################## | 100% 16.07s
|
||||
|
||||
|
||||
|
||||
avrdude: verifying ...
|
||||
avrdude: 16066 bytes of flash verified
|
||||
|
||||
avrdude: safemode: lfuse reads as 5E
|
||||
avrdude: safemode: hfuse reads as D9
|
||||
avrdude: safemode: efuse reads as F4
|
||||
avrdude: safemode: Fuses OK
|
||||
|
||||
avrdude done. Thank you.
|
||||
|
|
@ -0,0 +1,704 @@
|
|||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#----------------------------------------------------------------------------
|
||||
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
|
||||
# >> Modified for use with the LUFA project. <<
|
||||
#
|
||||
# Released to the Public Domain
|
||||
#
|
||||
# Additional material for this makefile was written by:
|
||||
# Peter Fleury
|
||||
# Tim Henigan
|
||||
# Colin O'Flynn
|
||||
# Reiner Patommel
|
||||
# Markus Pfaff
|
||||
# Sander Pool
|
||||
# Frederik Rouleau
|
||||
# Carlos Lamas
|
||||
# Dean Camera
|
||||
# Opendous Inc.
|
||||
# Denver Gingerich
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF.
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF.
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude.
|
||||
# Please customize the avrdude settings below first!
|
||||
#
|
||||
# make dfu = Download the hex file to the device, using dfu-programmer (must
|
||||
# have dfu-programmer installed).
|
||||
#
|
||||
# make flip = Download the hex file to the device, using Atmel FLIP (must
|
||||
# have Atmel FLIP installed).
|
||||
#
|
||||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
|
||||
# (must have dfu-programmer installed).
|
||||
#
|
||||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
|
||||
# (must have Atmel FLIP installed).
|
||||
#
|
||||
# make doxygen = Generate DoxyGen documentation for the project (must have
|
||||
# DoxyGen installed)
|
||||
#
|
||||
# make debug = Start either simulavr or avarice as specified for debugging,
|
||||
# with avr-gdb or avr-insight as the front end for debugging.
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only.
|
||||
#
|
||||
# make filename.i = Create a preprocessed source file for use in submitting
|
||||
# bug reports to the GCC project.
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = at90usb1287
|
||||
|
||||
|
||||
# Target board (USBKEY, STK525, STK526, RZUSBSTICK, USER or blank for projects not requiring
|
||||
# LUFA board drivers). If USER is selected, put custom board drivers in a directory called
|
||||
# "Board" inside the application directory.
|
||||
BOARD = USBKEY
|
||||
|
||||
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency. You can then use this symbol in your source code to
|
||||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
|
||||
# automatically to create a 32-bit value in your source code.
|
||||
# Typical values are:
|
||||
# F_CPU = 1000000
|
||||
# F_CPU = 1843200
|
||||
# F_CPU = 2000000
|
||||
# F_CPU = 3686400
|
||||
# F_CPU = 4000000
|
||||
# F_CPU = 7372800
|
||||
# F_CPU = 8000000
|
||||
# F_CPU = 11059200
|
||||
# F_CPU = 14745600
|
||||
# F_CPU = 16000000
|
||||
# F_CPU = 18432000
|
||||
# F_CPU = 20000000
|
||||
F_CPU = 8000000
|
||||
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = AVRISP_Programmer
|
||||
|
||||
|
||||
# Object files directory
|
||||
# To put object files in current directory, use a dot (.), do NOT make
|
||||
# this an empty or blank macro!
|
||||
OBJDIR = .
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c \
|
||||
Descriptors.c \
|
||||
RingBuff.c \
|
||||
../../LUFA/Scheduler/Scheduler.c \
|
||||
../../LUFA/Drivers/AT90USBXXX/Serial.c \
|
||||
../../LUFA/Drivers/USB/LowLevel/LowLevel.c \
|
||||
../../LUFA/Drivers/USB/LowLevel/Endpoint.c \
|
||||
../../LUFA/Drivers/USB/LowLevel/DevChapter9.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/USBTask.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/USBInterrupt.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/Events.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/StdDescriptors.c \
|
||||
|
||||
# List C++ source files here. (C dependencies are automatically generated.)
|
||||
CPPSRC =
|
||||
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC =
|
||||
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
# 0 = turn off optimization. s = optimize for size.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = s
|
||||
|
||||
|
||||
# Debugging format.
|
||||
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
||||
# AVR Studio 4.10 requires dwarf-2.
|
||||
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
|
||||
DEBUG = dwarf-2
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRAINCDIRS = ../../
|
||||
|
||||
|
||||
# Compiler flag to set the C Standard level.
|
||||
# c89 = "ANSI" C
|
||||
# gnu89 = c89 plus GCC extensions
|
||||
# c99 = ISO C99 standard (not yet fully implemented)
|
||||
# gnu99 = c99 plus GCC extensions
|
||||
CSTANDARD = -std=gnu99
|
||||
|
||||
|
||||
# Place -D or -U options here for C sources
|
||||
CDEFS = -DF_CPU=$(F_CPU)UL -DBOARD=BOARD_$(BOARD) -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS
|
||||
CDEFS += -DUSB_DEVICE_ONLY -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
|
||||
|
||||
|
||||
# Place -D or -U options here for ASM sources
|
||||
ADEFS = -DF_CPU=$(F_CPU)
|
||||
|
||||
|
||||
# Place -D or -U options here for C++ sources
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL
|
||||
#CPPDEFS += -D__STDC_LIMIT_MACROS
|
||||
#CPPDEFS += -D__STDC_CONSTANT_MACROS
|
||||
|
||||
|
||||
|
||||
#---------------- Compiler Options C ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CFLAGS = -g$(DEBUG)
|
||||
CFLAGS += $(CDEFS)
|
||||
CFLAGS += -O$(OPT)
|
||||
CFLAGS += -funsigned-char
|
||||
CFLAGS += -funsigned-bitfields
|
||||
CFLAGS += -ffunction-sections
|
||||
CFLAGS += -fpack-struct
|
||||
CFLAGS += -fshort-enums
|
||||
CFLAGS += -finline-limit=20
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
CFLAGS += -Wundef
|
||||
#CFLAGS += -fno-unit-at-a-time
|
||||
#CFLAGS += -Wunreachable-code
|
||||
#CFLAGS += -Wsign-compare
|
||||
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
|
||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
CFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Compiler Options C++ ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CPPFLAGS = -g$(DEBUG)
|
||||
CPPFLAGS += $(CPPDEFS)
|
||||
CPPFLAGS += -O$(OPT)
|
||||
CPPFLAGS += -funsigned-char
|
||||
CPPFLAGS += -funsigned-bitfields
|
||||
CPPFLAGS += -fpack-struct
|
||||
CPPFLAGS += -fshort-enums
|
||||
CPPFLAGS += -fno-exceptions
|
||||
CPPFLAGS += -Wall
|
||||
CFLAGS += -Wundef
|
||||
#CPPFLAGS += -mshort-calls
|
||||
#CPPFLAGS += -fno-unit-at-a-time
|
||||
#CPPFLAGS += -Wstrict-prototypes
|
||||
#CPPFLAGS += -Wunreachable-code
|
||||
#CPPFLAGS += -Wsign-compare
|
||||
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
|
||||
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
#CPPFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Assembler Options ----------------
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
|
||||
# dump that will be displayed for a given single line of source input.
|
||||
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
|
||||
|
||||
|
||||
#---------------- Library Options ----------------
|
||||
# Minimalistic printf version
|
||||
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires MATH_LIB = -lm below)
|
||||
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard printf version.
|
||||
PRINTF_LIB =
|
||||
#PRINTF_LIB = $(PRINTF_LIB_MIN)
|
||||
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
|
||||
|
||||
|
||||
# Minimalistic scanf version
|
||||
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
|
||||
|
||||
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
|
||||
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard scanf version.
|
||||
SCANF_LIB =
|
||||
#SCANF_LIB = $(SCANF_LIB_MIN)
|
||||
#SCANF_LIB = $(SCANF_LIB_FLOAT)
|
||||
|
||||
|
||||
MATH_LIB = -lm
|
||||
|
||||
|
||||
# List any extra directories to look for libraries here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRALIBDIRS =
|
||||
|
||||
|
||||
|
||||
#---------------- External Memory Options ----------------
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# used for variables (.data/.bss) and heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# only used for heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
EXTMEMOPTS =
|
||||
|
||||
|
||||
|
||||
#---------------- Linker Options ----------------
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||
LDFLAGS += -Wl,--relax
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
LDFLAGS += $(EXTMEMOPTS)
|
||||
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
|
||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
|
||||
#LDFLAGS += -T linker_script.x
|
||||
|
||||
|
||||
|
||||
#---------------- Programming Options (avrdude) ----------------
|
||||
|
||||
# Programming hardware: alf avr910 avrisp bascom bsd
|
||||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
|
||||
#
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = jtagmkII
|
||||
|
||||
# com1 = serial port. Use lpt1 to connect to parallel port.
|
||||
AVRDUDE_PORT = usb
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE_COUNTER = -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_NO_VERIFY = -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_VERBOSE = -v -v
|
||||
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
|
||||
|
||||
|
||||
|
||||
#---------------- Debugging Options ----------------
|
||||
|
||||
# For simulavr only - target MCU frequency.
|
||||
DEBUG_MFREQ = $(F_CPU)
|
||||
|
||||
# Set the DEBUG_UI to either gdb or insight.
|
||||
# DEBUG_UI = gdb
|
||||
DEBUG_UI = insight
|
||||
|
||||
# Set the debugging back-end to either avarice, simulavr.
|
||||
DEBUG_BACKEND = avarice
|
||||
#DEBUG_BACKEND = simulavr
|
||||
|
||||
# GDB Init Filename.
|
||||
GDBINIT_FILE = __avr_gdbinit
|
||||
|
||||
# When using avarice settings for the JTAG
|
||||
JTAG_DEV = /dev/com1
|
||||
|
||||
# Debugging port used to communicate between GDB / avarice / simulavr.
|
||||
DEBUG_PORT = 4242
|
||||
|
||||
# Debugging host used to communicate between GDB / avarice / simulavr, normally
|
||||
# just set to localhost unless doing some sort of crazy debugging when
|
||||
# avarice is running on a different computer.
|
||||
DEBUG_HOST = localhost
|
||||
|
||||
|
||||
|
||||
#============================================================================
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
CC = avr-gcc
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
SIZE = avr-size
|
||||
AR = avr-ar rcs
|
||||
NM = avr-nm
|
||||
AVRDUDE = avrdude
|
||||
REMOVE = rm -f
|
||||
REMOVEDIR = rm -rf
|
||||
COPY = cp
|
||||
WINSHELL = cmd
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling C:
|
||||
MSG_COMPILING_CPP = Compiling C++:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
MSG_CREATING_LIBRARY = Creating library:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
|
||||
|
||||
|
||||
# Compiler flags to generate dependency files.
|
||||
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
|
||||
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
|
||||
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore build checkhooks checklibmode sizeafter end
|
||||
|
||||
# Change the build target to build a HEX file or a library.
|
||||
build: elf hex eep lss sym
|
||||
#build: lib
|
||||
|
||||
|
||||
elf: $(TARGET).elf
|
||||
hex: $(TARGET).hex
|
||||
eep: $(TARGET).eep
|
||||
lss: $(TARGET).lss
|
||||
sym: $(TARGET).sym
|
||||
LIBNAME=lib$(TARGET).a
|
||||
lib: $(LIBNAME)
|
||||
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) $(MCU_FLAG) $(FORMAT_FLAG) $(TARGET).elf
|
||||
MCU_FLAG = $(shell $(SIZE) --help | grep -- --mcu > /dev/null && echo --mcu=$(MCU) )
|
||||
FORMAT_FLAG = $(shell $(SIZE) --help | grep -- --format=.*avr > /dev/null && echo --format=avr )
|
||||
|
||||
sizebefore:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
|
||||
2>/dev/null; echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
|
||||
2>/dev/null; echo; fi
|
||||
|
||||
checkhooks: build
|
||||
@echo
|
||||
@echo ------- Unhooked LUFA Events -------
|
||||
@$(shell) (grep -s '^Event.*LUFA/.*\\.o' $(TARGET).map | \
|
||||
cut -d' ' -f1 | cut -d'_' -f2- | grep ".*") || \
|
||||
echo "(None)"
|
||||
@echo ----- End Unhooked LUFA Events -----
|
||||
|
||||
checklibmode:
|
||||
@echo
|
||||
@echo ----------- Library Mode -----------
|
||||
@$(shell) ($(CC) $(ALL_CFLAGS) -E -dM - < /dev/null \
|
||||
| grep 'USB_\(DEVICE\|HOST\)_ONLY' | cut -d' ' -f2 | grep ".*") \
|
||||
|| echo "No specific mode (both device and host mode allowable)."
|
||||
@echo ------------------------------------
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
flip: $(TARGET).hex
|
||||
batchisp -hardware usb -device $(MCU) -operation erase f
|
||||
batchisp -hardware usb -device $(MCU) -operation loadbuffer $(TARGET).hex program
|
||||
batchisp -hardware usb -device $(MCU) -operation start reset 0
|
||||
|
||||
dfu: $(TARGET).hex
|
||||
dfu-programmer $(MCU) erase
|
||||
dfu-programmer $(MCU) flash --debug 1 $(TARGET).hex
|
||||
dfu-programmer $(MCU) reset
|
||||
|
||||
flip-ee: $(TARGET).hex $(TARGET).eep
|
||||
copy $(TARGET).eep $(TARGET)eep.hex
|
||||
batchisp -hardware usb -device $(MCU) -operation memory EEPROM erase
|
||||
batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $(TARGET)eep.hex program
|
||||
batchisp -hardware usb -device $(MCU) -operation start reset 0
|
||||
|
||||
dfu-ee: $(TARGET).hex $(TARGET).eep
|
||||
dfu-programmer $(MCU) erase
|
||||
dfu-programmer $(MCU) eeprom --debug 1 $(TARGET).eep
|
||||
dfu-programmer $(MCU) reset
|
||||
|
||||
# Generate avr-gdb config/init file which does the following:
|
||||
# define the reset signal, load the target file, connect to target, and set
|
||||
# a breakpoint at main().
|
||||
gdb-config:
|
||||
@$(REMOVE) $(GDBINIT_FILE)
|
||||
@echo define reset >> $(GDBINIT_FILE)
|
||||
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
|
||||
@echo end >> $(GDBINIT_FILE)
|
||||
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
|
||||
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
|
||||
ifeq ($(DEBUG_BACKEND),simulavr)
|
||||
@echo load >> $(GDBINIT_FILE)
|
||||
endif
|
||||
@echo break main >> $(GDBINIT_FILE)
|
||||
|
||||
debug: gdb-config $(TARGET).elf
|
||||
ifeq ($(DEBUG_BACKEND), avarice)
|
||||
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
|
||||
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
|
||||
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
|
||||
@$(WINSHELL) /c pause
|
||||
|
||||
else
|
||||
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
|
||||
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
|
||||
endif
|
||||
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
|
||||
COFFCONVERT = $(OBJCOPY) --debugging
|
||||
COFFCONVERT += --change-section-address .data-0x800000
|
||||
COFFCONVERT += --change-section-address .bss-0x800000
|
||||
COFFCONVERT += --change-section-address .noinit-0x800000
|
||||
COFFCONVERT += --change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -z -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
$(NM) -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Create library from object files.
|
||||
.SECONDARY : $(TARGET).a
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.a: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_CREATING_LIBRARY) $@
|
||||
$(AR) $@ $(OBJ)
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
$(OBJDIR)/%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create object files from C++ source files.
|
||||
$(OBJDIR)/%.o : %.cpp
|
||||
@echo
|
||||
@echo $(MSG_COMPILING_CPP) $<
|
||||
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C++ source files.
|
||||
%.s : %.cpp
|
||||
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
$(OBJDIR)/%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Create preprocessed source for use in sending a bug report.
|
||||
%.i : %.c
|
||||
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list clean_binary end
|
||||
|
||||
clean_binary:
|
||||
$(REMOVE) $(TARGET).hex
|
||||
|
||||
clean_list:
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
$(REMOVE) $(SRC:.c=.i)
|
||||
$(REMOVEDIR) .dep
|
||||
|
||||
|
||||
doxygen:
|
||||
@echo Generating Project Documentation...
|
||||
@doxygen Doxygen.conf
|
||||
@echo Documentation Generation Complete.
|
||||
|
||||
clean_doxygen:
|
||||
rm -rf Documentation
|
||||
|
||||
# Create object files directory
|
||||
$(shell mkdir $(OBJDIR) 2>/dev/null)
|
||||
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all checkhooks checklibmode begin \
|
||||
finish end sizebefore sizeafter gccversion \
|
||||
build elf hex eep lss sym coff extcoff \
|
||||
clean clean_list clean_binary program debug \
|
||||
gdb-config doxygen dfu flip
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** Circular bit buffer library. This will allow for individual bits
|
||||
* to be stored in packed form inside circular buffers, to reduce
|
||||
* overall RAM usage.
|
||||
*/
|
||||
|
||||
#include "CircularBitBuffer.h"
|
||||
|
||||
/** Function to initialize or reset a bit buffer, ready for data to be stored into it. */
|
||||
void BitBuffer_Init(BitBuffer_t* Buffer)
|
||||
{
|
||||
/* Reset the number of stored bits in the buffer */
|
||||
Buffer->Elements = 0;
|
||||
|
||||
/* Reset the data in and out pointer structures in the buffer to the first buffer bit */
|
||||
Buffer->In.CurrentByte = Buffer->Data;
|
||||
Buffer->In.ByteMask = (1 << 0);
|
||||
Buffer->Out.CurrentByte = Buffer->Data;
|
||||
Buffer->Out.ByteMask = (1 << 0);
|
||||
}
|
||||
|
||||
/** Function to store the given bit into the given bit buffer. */
|
||||
void BitBuffer_StoreNextBit(BitBuffer_t* Buffer, bool Bit)
|
||||
{
|
||||
/* If the bit to store is true, set the next bit in the buffer */
|
||||
if (Bit)
|
||||
*Buffer->In.CurrentByte |= Buffer->In.ByteMask;
|
||||
|
||||
/* Increment the number of stored bits in the buffer counter */
|
||||
Buffer->Elements++;
|
||||
|
||||
/* Check if the current buffer byte is full of stored bits */
|
||||
if (Buffer->In.ByteMask == (1 << 7))
|
||||
{
|
||||
/* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */
|
||||
if (Buffer->In.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])
|
||||
Buffer->In.CurrentByte++;
|
||||
else
|
||||
Buffer->In.CurrentByte = Buffer->Data;
|
||||
|
||||
/* Reset the storage bit mask in the current buffer byte to the first bit */
|
||||
Buffer->In.ByteMask = (1 << 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Shift the current storage bit mask to the next bit in the current byte */
|
||||
Buffer->In.ByteMask <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Function to retrieve the next bit stored in the given bit buffer. */
|
||||
bool BitBuffer_GetNextBit(BitBuffer_t* Buffer)
|
||||
{
|
||||
/* Retrieve the value of the next bit stored in the buffer */
|
||||
bool Bit = ((*Buffer->Out.CurrentByte & Buffer->Out.ByteMask) != 0);
|
||||
|
||||
/* Clear the buffer bit */
|
||||
*Buffer->Out.CurrentByte &= ~Buffer->Out.ByteMask;
|
||||
|
||||
/* Decrement the number of stored bits in the buffer counter */
|
||||
Buffer->Elements--;
|
||||
|
||||
/* Check if the current buffer byte is empty of stored bits */
|
||||
if (Buffer->Out.ByteMask == (1 << 7))
|
||||
{
|
||||
/* Check if the end of the buffer has been reached, if so reset to start of buffer, otherwise advance to next bit */
|
||||
if (Buffer->Out.CurrentByte != &Buffer->Data[sizeof(Buffer->Data) - 1])
|
||||
Buffer->Out.CurrentByte++;
|
||||
else
|
||||
Buffer->Out.CurrentByte = Buffer->Data;
|
||||
|
||||
/* Reset the retrieval bit mask in the current buffer byte to the first bit */
|
||||
Buffer->Out.ByteMask = (1 << 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Shift the current retrieval bit mask to the next bit in the current byte */
|
||||
Buffer->Out.ByteMask <<= 1;
|
||||
}
|
||||
|
||||
/* Return the retrieved bit from the buffer */
|
||||
return Bit;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Header file for CircularBitBuffer.c.
|
||||
*/
|
||||
|
||||
#ifndef _CIRCULARBITBUFFER_H_
|
||||
#define _CIRCULARBITBUFFER_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <LUFA/Common/Common.h>
|
||||
|
||||
/* Macros: */
|
||||
#if (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB647__) || \
|
||||
defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__)) || defined(__DOXYGEN__)
|
||||
/** Maximum number of bits which can be stored into a bit buffer. The memory usage is one eigth of this value per buffer. */
|
||||
#define MAX_BITS 20480
|
||||
#else
|
||||
#define MAX_BITS 1024
|
||||
#endif
|
||||
|
||||
/* Type Defines: */
|
||||
/* Type define for a pointer to a bit in a bit buffer. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t* CurrentByte; /**< Pointer to the current byte in the buffer */
|
||||
uint8_t ByteMask; /**< Mask of the current bit in the buffer */
|
||||
} BitBufferPointer_t;
|
||||
|
||||
/** Type define for a circular packet bit buffer. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Data[MAX_BITS / 8]; /**< Buffer to hold the stored bits in packed form */
|
||||
uint16_t Elements; /**< Number of stored bits in the bit buffer */
|
||||
|
||||
BitBufferPointer_t In; /**< Bit pointer to the next storage location in the buffer */
|
||||
BitBufferPointer_t Out; /**< Bit pointer to the next retrieval location in the buffer */
|
||||
} BitBuffer_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
/** Initializes or resets a given bit buffer, ready to store new bits.
|
||||
*
|
||||
* \param Buffer Bit buffer to initialize
|
||||
*/
|
||||
void BitBuffer_Init(BitBuffer_t* Buffer) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Stores a bit into the next location inside a given bit buffer.
|
||||
*
|
||||
* \param Buffer Bit buffer to store a bit into
|
||||
* \param Bit Bit to store into the buffer
|
||||
*/
|
||||
void BitBuffer_StoreNextBit(BitBuffer_t* Buffer, bool Bit) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
/** Retrieves a bit from the next location inside a given bit buffer.
|
||||
*
|
||||
* \param Buffer Bit buffer to store a bit into
|
||||
*
|
||||
* \return Next bit from the buffer
|
||||
*/
|
||||
bool BitBuffer_GetNextBit(BitBuffer_t* Buffer) ATTR_NON_NULL_PTR_ARG(1);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,247 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* USB Device Descriptors, for library use when in USB device mode. Descriptors are special
|
||||
* computer-readable structures which the host requests upon device enumeration, to determine
|
||||
* the device's capabilities and functions.
|
||||
*/
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
/** HID report descriptor. This is a HID class specific descriptor, which defines the structure of the
|
||||
* reports sent and received by the HID device to and from the USB host. It indicates what data is sent,
|
||||
* where in the report each element is located and exactly how the data should be interpreted and used.
|
||||
*
|
||||
* See the HID class specification for more information on HID report descriptors.
|
||||
*/
|
||||
USB_Descriptor_HIDReport_Datatype_t PROGMEM KeyboardReport[] =
|
||||
{
|
||||
0x05, 0x01, /* Usage Page (Generic Desktop) */
|
||||
0x09, 0x06, /* Usage (Keyboard) */
|
||||
0xa1, 0x01, /* Collection (Application) */
|
||||
0x05, 0x07, /* Usage Page (Key Codes) */
|
||||
0x19, 0xe0, /* Usage Minimum (Keyboard LeftControl) */
|
||||
0x29, 0xe7, /* Usage Maximum (Keyboard Right GUI) */
|
||||
0x15, 0x00, /* Logical Minimum (0) */
|
||||
0x25, 0x01, /* Logical Maximum (1) */
|
||||
0x75, 0x01, /* Report Size (1) */
|
||||
0x95, 0x08, /* Report Count (8) */
|
||||
0x81, 0x02, /* Input (Data, Variable, Absolute) */
|
||||
0x95, 0x01, /* Report Count (1) */
|
||||
0x75, 0x08, /* Report Size (8) */
|
||||
0x81, 0x03, /* Input (Const, Variable, Absolute) */
|
||||
0x95, 0x01, /* Report Count (1) */
|
||||
0x75, 0x08, /* Report Size (8) */
|
||||
0x15, 0x00, /* Logical Minimum (0) */
|
||||
0x25, 0x65, /* Logical Maximum (101) */
|
||||
0x05, 0x07, /* Usage Page (Keyboard) */
|
||||
0x19, 0x00, /* Usage Minimum (Reserved (no event indicated)) */
|
||||
0x29, 0x65, /* Usage Maximum (Keyboard Application) */
|
||||
0x81, 0x00, /* Input (Data, Array, Absolute) */
|
||||
0xc0 /* End Collection */
|
||||
};
|
||||
|
||||
/** Device descriptor structure. This descriptor, located in FLASH memory, describes the overall
|
||||
* device characteristics, including the supported USB version, control endpoint size and the
|
||||
* number of device configurations. The descriptor is read out by the USB host when the enumeration
|
||||
* process begins.
|
||||
*/
|
||||
USB_Descriptor_Device_t PROGMEM DeviceDescriptor =
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Device_t), Type: DTYPE_Device},
|
||||
|
||||
USBSpecification: VERSION_BCD(01.10),
|
||||
Class: 0x00,
|
||||
SubClass: 0x00,
|
||||
Protocol: 0x00,
|
||||
|
||||
Endpoint0Size: 8,
|
||||
|
||||
VendorID: 0x03EB,
|
||||
ProductID: 0x2042,
|
||||
ReleaseNumber: 0x0000,
|
||||
|
||||
ManufacturerStrIndex: 0x01,
|
||||
ProductStrIndex: 0x02,
|
||||
SerialNumStrIndex: NO_DESCRIPTOR,
|
||||
|
||||
NumberOfConfigurations: 1
|
||||
};
|
||||
|
||||
/** Configuration descriptor structure. This descriptor, located in FLASH memory, describes the usage
|
||||
* of the device in one of its supported configurations, including information about any device interfaces
|
||||
* and endpoints. The descriptor is read out by the USB host during the enumeration process when selecting
|
||||
* a configuration so that the host may correctly communicate with the USB device.
|
||||
*/
|
||||
USB_Descriptor_Configuration_t PROGMEM ConfigurationDescriptor =
|
||||
{
|
||||
Config:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Configuration_Header_t), Type: DTYPE_Configuration},
|
||||
|
||||
TotalConfigurationSize: sizeof(USB_Descriptor_Configuration_t),
|
||||
TotalInterfaces: 1,
|
||||
|
||||
ConfigurationNumber: 1,
|
||||
ConfigurationStrIndex: NO_DESCRIPTOR,
|
||||
|
||||
ConfigAttributes: (USB_CONFIG_ATTR_BUSPOWERED | USB_CONFIG_ATTR_SELFPOWERED),
|
||||
|
||||
MaxPowerConsumption: USB_CONFIG_POWER_MA(100)
|
||||
},
|
||||
|
||||
Interface:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Interface_t), Type: DTYPE_Interface},
|
||||
|
||||
InterfaceNumber: 0x00,
|
||||
AlternateSetting: 0x00,
|
||||
|
||||
TotalEndpoints: 1,
|
||||
|
||||
Class: 0x03,
|
||||
SubClass: 0x01,
|
||||
Protocol: 0x01,
|
||||
|
||||
InterfaceStrIndex: NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
KeyboardHID:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_HID_t), Type: DTYPE_HID},
|
||||
|
||||
HIDSpec: VERSION_BCD(01.11),
|
||||
CountryCode: 0x00,
|
||||
TotalHIDReports: 0x01,
|
||||
HIDReportType: DTYPE_Report,
|
||||
HIDReportLength: sizeof(KeyboardReport)
|
||||
},
|
||||
|
||||
KeyboardEndpoint:
|
||||
{
|
||||
Header: {Size: sizeof(USB_Descriptor_Endpoint_t), Type: DTYPE_Endpoint},
|
||||
|
||||
EndpointAddress: (ENDPOINT_DESCRIPTOR_DIR_IN | KEYBOARD_EPNUM),
|
||||
Attributes: EP_TYPE_INTERRUPT,
|
||||
EndpointSize: KEYBOARD_EPSIZE,
|
||||
PollingIntervalMS: 0x02
|
||||
},
|
||||
};
|
||||
|
||||
/** Language descriptor structure. This descriptor, located in FLASH memory, is returned when the host requests
|
||||
* the string descriptor with index 0 (the first index). It is actually an array of 16-bit integers, which indicate
|
||||
* via the language ID table available at USB.org what languages the device supports for its string descriptors. */
|
||||
USB_Descriptor_String_t PROGMEM LanguageString =
|
||||
{
|
||||
Header: {Size: USB_STRING_LEN(1), Type: DTYPE_String},
|
||||
|
||||
UnicodeString: {LANGUAGE_ID_ENG}
|
||||
};
|
||||
|
||||
/** Manufacturer descriptor string. This is a Unicode string containing the manufacturer's details in human readable
|
||||
* form, and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
|
||||
* Descriptor.
|
||||
*/
|
||||
USB_Descriptor_String_t PROGMEM ManufacturerString =
|
||||
{
|
||||
Header: {Size: USB_STRING_LEN(32), Type: DTYPE_String},
|
||||
|
||||
UnicodeString: L"Dean Camera and Denver Gingerich"
|
||||
};
|
||||
|
||||
/** Product descriptor string. This is a Unicode string containing the product's details in human readable form,
|
||||
* and is read out upon request by the host when the appropriate string ID is requested, listed in the Device
|
||||
* Descriptor.
|
||||
*/
|
||||
USB_Descriptor_String_t PROGMEM ProductString =
|
||||
{
|
||||
Header: {Size: USB_STRING_LEN(20), Type: DTYPE_String},
|
||||
|
||||
UnicodeString: L"Magnetic Card Reader"
|
||||
};
|
||||
|
||||
/** This function is called by the library when in device mode, and must be overridden (see StdDescriptors.h
|
||||
* documentation) by the application code so that the address and size of a requested descriptor can be given
|
||||
* to the USB library. When the device recieves a Get Descriptor request on the control endpoint, this function
|
||||
* is called so that the descriptor details can be passed back and the appropriate descriptor sent back to the
|
||||
* USB host.
|
||||
*/
|
||||
uint16_t USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
|
||||
{
|
||||
const uint8_t DescriptorType = (wValue >> 8);
|
||||
const uint8_t DescriptorNumber = (wValue & 0xFF);
|
||||
|
||||
void* Address = NULL;
|
||||
uint16_t Size = NO_DESCRIPTOR;
|
||||
|
||||
switch (DescriptorType)
|
||||
{
|
||||
case DTYPE_Device:
|
||||
Address = DESCRIPTOR_ADDRESS(DeviceDescriptor);
|
||||
Size = sizeof(USB_Descriptor_Device_t);
|
||||
break;
|
||||
case DTYPE_Configuration:
|
||||
Address = DESCRIPTOR_ADDRESS(ConfigurationDescriptor);
|
||||
Size = sizeof(USB_Descriptor_Configuration_t);
|
||||
break;
|
||||
case DTYPE_String:
|
||||
switch (DescriptorNumber)
|
||||
{
|
||||
case 0x00:
|
||||
Address = DESCRIPTOR_ADDRESS(LanguageString);
|
||||
Size = pgm_read_byte(&LanguageString.Header.Size);
|
||||
break;
|
||||
case 0x01:
|
||||
Address = DESCRIPTOR_ADDRESS(ManufacturerString);
|
||||
Size = pgm_read_byte(&ManufacturerString.Header.Size);
|
||||
break;
|
||||
case 0x02:
|
||||
Address = DESCRIPTOR_ADDRESS(ProductString);
|
||||
Size = pgm_read_byte(&ProductString.Header.Size);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
case DTYPE_HID:
|
||||
Address = DESCRIPTOR_ADDRESS(ConfigurationDescriptor.KeyboardHID);
|
||||
Size = sizeof(USB_Descriptor_HID_t);
|
||||
break;
|
||||
case DTYPE_Report:
|
||||
Address = DESCRIPTOR_ADDRESS(KeyboardReport);
|
||||
Size = sizeof(KeyboardReport);
|
||||
break;
|
||||
}
|
||||
|
||||
*DescriptorAddress = Address;
|
||||
return Size;
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Header file for Descriptors.c.
|
||||
*/
|
||||
|
||||
#ifndef _DESCRIPTORS_H_
|
||||
#define _DESCRIPTORS_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for the HID class specific HID descriptor. A HID descriptor is used in HID class devices
|
||||
* to give information about the HID device, including the HID specification used, and the report descriptors
|
||||
* the device contains to describe how the HID device should be controlled.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
USB_Descriptor_Header_t Header; /**< Standard USB descriptor header */
|
||||
|
||||
uint16_t HIDSpec; /**< HID specification implemented by the device, in BCD form */
|
||||
uint8_t CountryCode; /**< Country code for the country the HID device is localised for */
|
||||
|
||||
uint8_t TotalHIDReports; /**< Total number of HID reports linked to this HID interface */
|
||||
|
||||
uint8_t HIDReportType; /**< Type of the first HID report descriptor */
|
||||
uint16_t HIDReportLength; /**< Length of the first HID report descriptor */
|
||||
} USB_Descriptor_HID_t;
|
||||
|
||||
/** Type define for the data type used for the HID Report descriptor data elements. A HID report
|
||||
* descriptor contains an array of this data type, indicating how the reports from and to the
|
||||
* device are formatted and how the report data is to be used by the host.
|
||||
*/
|
||||
typedef uint8_t USB_Descriptor_HIDReport_Datatype_t;
|
||||
|
||||
/** Type define for the device configuration descriptor structure. This must be defined in the
|
||||
* application code, as the configuration descriptor contains several sub-descriptors which
|
||||
* vary between devices, and which describe the device's usage to the host.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
USB_Descriptor_Configuration_Header_t Config; /**< Configuration descriptor header structure */
|
||||
USB_Descriptor_Interface_t Interface; /**< Keyboard interface descriptor */
|
||||
USB_Descriptor_HID_t KeyboardHID; /**< Keyboard HID descriptor */
|
||||
USB_Descriptor_Endpoint_t KeyboardEndpoint; /**< Keyboard key report endpoint descriptor */
|
||||
} USB_Descriptor_Configuration_t;
|
||||
|
||||
/* Macros: */
|
||||
/** Endpoint number of the keyboard key press reporting endpoint. */
|
||||
#define KEYBOARD_EPNUM 1
|
||||
|
||||
/** Size of the keyboard report endpoints, in bytes. */
|
||||
#define KEYBOARD_EPSIZE 8
|
||||
|
||||
/** Descriptor type value for a HID descriptor. */
|
||||
#define DTYPE_HID 0x21
|
||||
|
||||
/** Descriptor type value for a HID report. */
|
||||
#define DTYPE_Report 0x22
|
||||
|
||||
/* Function Prototypes: */
|
||||
uint16_t USB_GetDescriptor(const uint16_t wValue, const uint8_t wIndex, void** const DescriptorAddress)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
<AVRStudio><MANAGEMENT><ProjectName>Magstripe</ProjectName><Created>30-Sep-2008 14:19:14</Created><LastEdit>30-Sep-2008 14:19:28</LastEdit><ICON>241</ICON><ProjectType>0</ProjectType><Created>30-Sep-2008 14:19:14</Created><Version>4</Version><Build>4, 14, 0, 589</Build><ProjectTypeName>AVR GCC</ProjectTypeName></MANAGEMENT><CODE_CREATION><ObjectFile></ObjectFile><EntryFile></EntryFile><SaveFolder>C:\Users\Dean\Documents\Electronics\Projects\WORK\MyUSBWORK\Projects\Magstripe\</SaveFolder></CODE_CREATION><DEBUG_TARGET><CURRENT_TARGET></CURRENT_TARGET><CURRENT_PART></CURRENT_PART><BREAKPOINTS></BREAKPOINTS><IO_EXPAND><HIDE>false</HIDE></IO_EXPAND><REGISTERNAMES><Register>R00</Register><Register>R01</Register><Register>R02</Register><Register>R03</Register><Register>R04</Register><Register>R05</Register><Register>R06</Register><Register>R07</Register><Register>R08</Register><Register>R09</Register><Register>R10</Register><Register>R11</Register><Register>R12</Register><Register>R13</Register><Register>R14</Register><Register>R15</Register><Register>R16</Register><Register>R17</Register><Register>R18</Register><Register>R19</Register><Register>R20</Register><Register>R21</Register><Register>R22</Register><Register>R23</Register><Register>R24</Register><Register>R25</Register><Register>R26</Register><Register>R27</Register><Register>R28</Register><Register>R29</Register><Register>R30</Register><Register>R31</Register></REGISTERNAMES><COM>Auto</COM><COMType>0</COMType><WATCHNUM>0</WATCHNUM><WATCHNAMES><Pane0></Pane0><Pane1></Pane1><Pane2></Pane2><Pane3></Pane3></WATCHNAMES><BreakOnTrcaeFull>0</BreakOnTrcaeFull></DEBUG_TARGET><Debugger><Triggers></Triggers></Debugger><AVRGCCPLUGIN><FILES><SOURCEFILE>Descriptors.c</SOURCEFILE><SOURCEFILE>Magstripe.c</SOURCEFILE><HEADERFILE>Descriptors.h</HEADERFILE><HEADERFILE>Magstripe.h</HEADERFILE><HEADERFILE>MagstripeHW.h</HEADERFILE><OTHERFILE>makefile</OTHERFILE></FILES><CONFIGS><CONFIG><NAME>default</NAME><USESEXTERNALMAKEFILE>YES</USESEXTERNALMAKEFILE><EXTERNALMAKEFILE>makefile</EXTERNALMAKEFILE><PART>atmega128</PART><HEX>1</HEX><LIST>1</LIST><MAP>1</MAP><OUTPUTFILENAME>Magstripe.elf</OUTPUTFILENAME><OUTPUTDIR>default\</OUTPUTDIR><ISDIRTY>1</ISDIRTY><OPTIONS/><INCDIRS/><LIBDIRS/><LIBS/><LINKOBJECTS/><OPTIONSFORALL>-Wall -gdwarf-2 -std=gnu99 -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums</OPTIONSFORALL><LINKEROPTIONS></LINKEROPTIONS><SEGMENTS/></CONFIG></CONFIGS><LASTCONFIG>default</LASTCONFIG><USES_WINAVR>1</USES_WINAVR><GCC_LOC>C:\WinAVR-20080512\bin\avr-gcc.exe</GCC_LOC><MAKE_LOC>C:\WinAVR-20080512\utils\bin\make.exe</MAKE_LOC></AVRGCCPLUGIN><IOView><usergroups/><sort sorted="0" column="0" ordername="0" orderaddress="0" ordergroup="0"/></IOView><Files></Files><Events><Bookmarks></Bookmarks></Events><Trace><Filters></Filters></Trace></AVRStudio>
|
|
@ -0,0 +1,436 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Main source file for the MagStripe application. This file contains the code which drives
|
||||
* the USB keyboard interface from the magnetic card stripe reader device.
|
||||
*/
|
||||
|
||||
#include "Magstripe.h"
|
||||
|
||||
/* Project Tags, for reading out using the ButtLoad project */
|
||||
BUTTLOADTAG(ProjName, "Magstripe Reader");
|
||||
BUTTLOADTAG(BuildTime, __TIME__);
|
||||
BUTTLOADTAG(BuildDate, __DATE__);
|
||||
BUTTLOADTAG(LUFAVersion, "LUFA V" LUFA_VERSION_STRING);
|
||||
|
||||
/* Scheduler Task List */
|
||||
TASK_LIST
|
||||
{
|
||||
{ Task: USB_USBTask , TaskStatus: TASK_STOP },
|
||||
{ Task: USB_Keyboard_Report , TaskStatus: TASK_STOP },
|
||||
{ Task: Magstripe_Read , TaskStatus: TASK_STOP },
|
||||
};
|
||||
|
||||
/* Global Variables */
|
||||
/** Indicates if the device is using Report Protocol mode, instead of Boot Protocol mode. Boot Protocol mode
|
||||
* is a special reporting mode used by compatible PC BIOS to support USB keyboards before a full OS and USB
|
||||
* driver has been loaded, by using predefined report structures indicated in the USB HID standard.
|
||||
*/
|
||||
bool UsingReportProtocol = true;
|
||||
|
||||
/** Total idle period in milliseconds set by the host via a SetIdle request, used to silence the report endpoint
|
||||
* until the report data changes or the idle period elapsed. Generally used to implement hardware key repeats, or
|
||||
* by some BIOS to reduce the number of reports when in Boot Protocol mode.
|
||||
*/
|
||||
uint8_t IdleCount = 0;
|
||||
|
||||
/** Milliseconds remaining counter for the HID class SetIdle and GetIdle requests, used to silence the report
|
||||
* endpoint for an amount of time indicated by the host or until the report changes.
|
||||
*/
|
||||
uint16_t IdleMSRemaining = 0;
|
||||
|
||||
/** Circular buffer to hold the read bits from track 1 of the inserted magnetic card. */
|
||||
BitBuffer_t Track1Data;
|
||||
|
||||
/** Circular buffer to hold the read bits from track 2 of the inserted magnetic card. */
|
||||
BitBuffer_t Track2Data;
|
||||
|
||||
/** Circular buffer to hold the read bits from track 3 of the inserted magnetic card. */
|
||||
BitBuffer_t Track3Data;
|
||||
|
||||
/** Delay counter between sucessive key strokes. This is to prevent the OS from ignoring multiple keys in a short
|
||||
* period of time due to key repeats. Two milliseconds works for most OSes.
|
||||
*/
|
||||
uint8_t KeyDelayRemaining;
|
||||
|
||||
|
||||
/** Main program entry point. This routine configures the hardware required by the application, then
|
||||
* starts the scheduler to run the application tasks.
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
/* Disable watchdog if enabled by bootloader/fuses */
|
||||
MCUSR &= ~(1 << WDRF);
|
||||
wdt_disable();
|
||||
|
||||
/* Disable Clock Division */
|
||||
SetSystemClockPrescaler(0);
|
||||
|
||||
/* Hardware Initialization */
|
||||
Magstripe_Init();
|
||||
|
||||
/* Buffer Initialization */
|
||||
BitBuffer_Init(&Track1Data);
|
||||
BitBuffer_Init(&Track2Data);
|
||||
BitBuffer_Init(&Track3Data);
|
||||
|
||||
/* Millisecond timer initialization, with output compare interrupt enabled for the idle timing */
|
||||
OCR0A = 0xFA;
|
||||
TCCR0A = (1 << WGM01);
|
||||
TCCR0B = ((1 << CS01) | (1 << CS00));
|
||||
TIMSK0 = (1 << OCIE0A);
|
||||
|
||||
/* Initialize Scheduler so that it can be used */
|
||||
Scheduler_Init();
|
||||
|
||||
/* Initialize USB Subsystem */
|
||||
USB_Init();
|
||||
|
||||
/* Scheduling - routine never returns, so put this last in the main function */
|
||||
Scheduler_Start();
|
||||
}
|
||||
|
||||
/** Event handler for the USB_Connect event. This starts the USB task. */
|
||||
EVENT_HANDLER(USB_Connect)
|
||||
{
|
||||
/* Start USB management task */
|
||||
Scheduler_SetTaskMode(USB_USBTask, TASK_RUN);
|
||||
}
|
||||
|
||||
/** Event handler for the USB_Disconnect event. This stops the USB and keyboard report tasks. */
|
||||
EVENT_HANDLER(USB_Disconnect)
|
||||
{
|
||||
/* Stop running keyboard reporting, card reading and USB management tasks */
|
||||
Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_STOP);
|
||||
Scheduler_SetTaskMode(USB_USBTask, TASK_STOP);
|
||||
Scheduler_SetTaskMode(Magstripe_Read, TASK_STOP);
|
||||
}
|
||||
|
||||
/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
|
||||
* to relay reports to the host, and starts the keyboard report task.
|
||||
*/
|
||||
EVENT_HANDLER(USB_ConfigurationChanged)
|
||||
{
|
||||
/* Setup Keyboard Keycode Report Endpoint */
|
||||
Endpoint_ConfigureEndpoint(KEYBOARD_EPNUM, EP_TYPE_INTERRUPT,
|
||||
ENDPOINT_DIR_IN, KEYBOARD_EPSIZE,
|
||||
ENDPOINT_BANK_SINGLE);
|
||||
|
||||
/* Default to report protocol on connect */
|
||||
UsingReportProtocol = true;
|
||||
|
||||
/* Start Keyboard reporting and card reading tasks */
|
||||
Scheduler_SetTaskMode(USB_Keyboard_Report, TASK_RUN);
|
||||
Scheduler_SetTaskMode(Magstripe_Read, TASK_RUN);
|
||||
}
|
||||
|
||||
/** Event handler for the USB_UnhandledControlPacket event. This is used to catch standard and class specific
|
||||
* control requests that are not handled internally by the USB library, so that they can be handled appropriately
|
||||
* for the application.
|
||||
*/
|
||||
EVENT_HANDLER(USB_UnhandledControlPacket)
|
||||
{
|
||||
/* Handle HID Class specific requests */
|
||||
switch (bRequest)
|
||||
{
|
||||
case REQ_GetReport:
|
||||
if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
USB_KeyboardReport_Data_t KeyboardReportData;
|
||||
|
||||
/* Create the next keyboard report for transmission to the host */
|
||||
GetNextReport(&KeyboardReportData);
|
||||
|
||||
/* Ignore report type and ID number value */
|
||||
Endpoint_Discard_Word();
|
||||
|
||||
/* Ignore unused Interface number value */
|
||||
Endpoint_Discard_Word();
|
||||
|
||||
/* Read in the number of bytes in the report to send to the host */
|
||||
uint16_t wLength = Endpoint_Read_Word_LE();
|
||||
|
||||
/* If trying to send more bytes than exist to the host, clamp the value at the report size */
|
||||
if (wLength > sizeof(KeyboardReportData))
|
||||
wLength = sizeof(KeyboardReportData);
|
||||
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Write the report data to the control endpoint */
|
||||
Endpoint_Write_Control_Stream_LE(&KeyboardReportData, wLength);
|
||||
|
||||
/* Finalize the stream transfer to send the last packet or clear the host abort */
|
||||
Endpoint_ClearSetupOUT();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetProtocol:
|
||||
if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Write the current protocol flag to the host */
|
||||
Endpoint_Write_Byte(UsingReportProtocol);
|
||||
|
||||
/* Send the flag to the host */
|
||||
Endpoint_ClearSetupIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetProtocol:
|
||||
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
/* Read in the wValue parameter containing the new protocol mode */
|
||||
uint16_t wValue = Endpoint_Read_Word_LE();
|
||||
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Set or clear the flag depending on what the host indicates that the current Protocol should be */
|
||||
UsingReportProtocol = (wValue != 0x0000);
|
||||
|
||||
/* Send an empty packet to acknowedge the command */
|
||||
Endpoint_ClearSetupIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_SetIdle:
|
||||
if (bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
/* Read in the wValue parameter containing the idle period */
|
||||
uint16_t wValue = Endpoint_Read_Word_LE();
|
||||
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Get idle period in MSB */
|
||||
IdleCount = (wValue >> 8);
|
||||
|
||||
/* Send an empty packet to acknowedge the command */
|
||||
Endpoint_ClearSetupIN();
|
||||
}
|
||||
|
||||
break;
|
||||
case REQ_GetIdle:
|
||||
if (bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSetupReceived();
|
||||
|
||||
/* Write the current idle duration to the host */
|
||||
Endpoint_Write_Byte(IdleCount);
|
||||
|
||||
/* Send the flag to the host */
|
||||
Endpoint_ClearSetupIN();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** ISR for the timer 0 compare vector. This ISR fires once each millisecond, and decrements the counter indicating
|
||||
* the number of milliseconds left to idle (not send the host reports) if the device has been instructed to idle
|
||||
* by the host via a SetIdle class specific request.
|
||||
*/
|
||||
ISR(TIMER0_COMPA_vect, ISR_BLOCK)
|
||||
{
|
||||
/* One millisecond has elapsed, decrement the idle time remaining counter if it has not already elapsed */
|
||||
if (IdleMSRemaining)
|
||||
IdleMSRemaining--;
|
||||
|
||||
if (KeyDelayRemaining)
|
||||
KeyDelayRemaining--;
|
||||
}
|
||||
|
||||
/** Constructs a keyboard report indicating the currently pressed keyboard keys to the host.
|
||||
*
|
||||
* \param ReportData Pointer to a USB_KeyboardReport_Data_t report structure where the resulting report should
|
||||
* be stored
|
||||
*
|
||||
* \return Boolean true if the current report is different to the previous report, false otherwise
|
||||
*/
|
||||
bool GetNextReport(USB_KeyboardReport_Data_t* ReportData)
|
||||
{
|
||||
static bool OddReport = false;
|
||||
static bool MustRelease = false;
|
||||
|
||||
BitBuffer_t* Buffer = NULL;
|
||||
|
||||
/* Clear the report contents */
|
||||
memset(ReportData, 0, sizeof(USB_KeyboardReport_Data_t));
|
||||
|
||||
/* Get the next non-empty track data buffer */
|
||||
if (Track1Data.Elements)
|
||||
Buffer = &Track1Data;
|
||||
else if (Track2Data.Elements)
|
||||
Buffer = &Track2Data;
|
||||
else if (Track3Data.Elements)
|
||||
Buffer = &Track3Data;
|
||||
|
||||
if (Buffer != NULL)
|
||||
{
|
||||
/* Toggle the odd report number indicator */
|
||||
OddReport = !OddReport;
|
||||
|
||||
/* Set the flag indicating that a null report must eventually be sent to release all pressed keys */
|
||||
MustRelease = true;
|
||||
|
||||
/* Only send the next key on odd reports, so that they are interpersed with null reports to release keys */
|
||||
if (OddReport)
|
||||
{
|
||||
/* Set the report key code to the key code for the next data bit */
|
||||
ReportData->KeyCode[0] = BitBuffer_GetNextBit(Buffer) ? KEY_1 : KEY_0;
|
||||
|
||||
/* If buffer is now empty, a new line must be sent instead of the terminating bit */
|
||||
if (!(Buffer->Elements))
|
||||
{
|
||||
/* Set the keycode to the code for an enter key press */
|
||||
ReportData->KeyCode[0] = KEY_ENTER;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (MustRelease)
|
||||
{
|
||||
/* Leave key code to null (0), to release all pressed keys */
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Task to read out data from inserted magnetic cards and place the seperate track data into their respective
|
||||
* data buffers for later sending to the host as keyboard key presses.
|
||||
*/
|
||||
TASK(Magstripe_Read)
|
||||
{
|
||||
/* Arrays to hold the buffer pointers, clock and data bit masks for the seperate card tracks */
|
||||
const struct
|
||||
{
|
||||
BitBuffer_t* Buffer;
|
||||
uint8_t ClockMask;
|
||||
uint8_t DataMask;
|
||||
} TrackInfo[] = {{&Track1Data, MAG_T1_CLOCK, MAG_T1_DATA},
|
||||
{&Track2Data, MAG_T2_CLOCK, MAG_T2_DATA},
|
||||
{&Track3Data, MAG_T3_CLOCK, MAG_T3_DATA}};
|
||||
|
||||
/* Previous magnetic card control line' status, for later comparison */
|
||||
uint8_t Magstripe_Prev = 0;
|
||||
|
||||
/* Buffered current card reader control line' status */
|
||||
uint8_t Magstripe_LCL = Magstripe_GetStatus();
|
||||
|
||||
/* Exit the task early if no card is present in the reader */
|
||||
if (!(Magstripe_LCL & MAG_CARDPRESENT))
|
||||
return;
|
||||
|
||||
/* Read out card data while a card is present */
|
||||
while (Magstripe_LCL & MAG_CARDPRESENT)
|
||||
{
|
||||
/* Read out the next bit for each track of the card */
|
||||
for (uint8_t Track = 0; Track < 3; Track++)
|
||||
{
|
||||
/* Current data line status for the current card track */
|
||||
bool DataLevel = ((Magstripe_LCL & TrackInfo[Track].DataMask) != 0);
|
||||
|
||||
/* Current clock line status for the current card track */
|
||||
bool ClockLevel = ((Magstripe_LCL & TrackInfo[Track].ClockMask) != 0);
|
||||
|
||||
/* Current track clock transition check */
|
||||
bool ClockChanged = (((Magstripe_LCL ^ Magstripe_Prev) & TrackInfo[Track].ClockMask) != 0);
|
||||
|
||||
/* Sample the next bit on the falling edge of the track's clock line, store key code into the track's buffer */
|
||||
if (ClockLevel && ClockChanged)
|
||||
BitBuffer_StoreNextBit(TrackInfo[Track].Buffer, DataLevel);
|
||||
}
|
||||
|
||||
/* Retain the current card reader control line states for later edge detection */
|
||||
Magstripe_Prev = Magstripe_LCL;
|
||||
|
||||
/* Retrieve the new card reader control line states */
|
||||
Magstripe_LCL = Magstripe_GetStatus();
|
||||
}
|
||||
|
||||
/* Add terminators to the end of each track buffer */
|
||||
BitBuffer_StoreNextBit(&Track1Data, 0);
|
||||
BitBuffer_StoreNextBit(&Track2Data, 0);
|
||||
BitBuffer_StoreNextBit(&Track3Data, 0);
|
||||
}
|
||||
|
||||
/** Task for the magnetic card reading and keyboard report generation. This task waits until a card is inserted,
|
||||
* then reads off the card data and sends it to the host as a series of keyboard keypresses via keyboard reports.
|
||||
*/
|
||||
TASK(USB_Keyboard_Report)
|
||||
{
|
||||
USB_KeyboardReport_Data_t KeyboardReportData;
|
||||
bool SendReport = false;
|
||||
|
||||
/* Check if the USB system is connected to a host */
|
||||
if (USB_IsConnected)
|
||||
{
|
||||
/* Select the Keyboard Report Endpoint */
|
||||
Endpoint_SelectEndpoint(KEYBOARD_EPNUM);
|
||||
|
||||
/* Check if Keyboard Endpoint Ready for Read/Write */
|
||||
if (Endpoint_ReadWriteAllowed())
|
||||
{
|
||||
/* Only fetch the next key to send once the period between key presses has elapsed */
|
||||
if (!(KeyDelayRemaining))
|
||||
{
|
||||
/* Create the next keyboard report for transmission to the host */
|
||||
SendReport = GetNextReport(&KeyboardReportData);
|
||||
}
|
||||
|
||||
/* Check if the idle period is set and has elapsed */
|
||||
if (IdleCount && !(IdleMSRemaining))
|
||||
{
|
||||
/* Idle period elapsed, indicate that a report must be sent */
|
||||
SendReport = true;
|
||||
|
||||
/* Reset the idle time remaining counter, must multiply by 4 to get the duration in milliseconds */
|
||||
IdleMSRemaining = (IdleCount << 2);
|
||||
}
|
||||
|
||||
/* Write the keyboard report if a report is to be sent to the host */
|
||||
if (SendReport)
|
||||
{
|
||||
/* Write Keyboard Report Data */
|
||||
Endpoint_Write_Stream_LE(&KeyboardReportData, sizeof(USB_KeyboardReport_Data_t));
|
||||
|
||||
/* Finalize the stream transfer to send the last packet */
|
||||
Endpoint_ClearCurrentBank();
|
||||
|
||||
/* Reset the key delay period counter */
|
||||
KeyDelayRemaining = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2009.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.fourwalledcubicle.com
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Header file for Magstripe.c.
|
||||
*/
|
||||
|
||||
#ifndef _MAGSTRIPE_H_
|
||||
#define _MAGSTRIPE_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
#include "MagstripeHW.h"
|
||||
#include "CircularBitBuffer.h"
|
||||
|
||||
#include <LUFA/Version.h> // Library Version Information
|
||||
#include <LUFA/Common/ButtLoadTag.h> // PROGMEM tags readable by the ButtLoad project
|
||||
#include <LUFA/Drivers/USB/USB.h> // USB Functionality
|
||||
#include <LUFA/Scheduler/Scheduler.h> // Simple scheduler for task management
|
||||
|
||||
|
||||
/* Task Definitions: */
|
||||
/** Task definition for the keyboard and magnetic card reading task. */
|
||||
TASK(USB_Keyboard_Report);
|
||||
|
||||
TASK(Magstripe_Read);
|
||||
|
||||
/* Macros: */
|
||||
/** HID Class Specific Request to get the current HID report from the device. */
|
||||
#define REQ_GetReport 0x01
|
||||
|
||||
/** HID Class Specific Request to get the current device idle count. */
|
||||
#define REQ_GetIdle 0x02
|
||||
|
||||
/** HID Class Specific Request to set the current HID report to the device. */
|
||||
#define REQ_SetReport 0x09
|
||||
|
||||
/** HID Class Specific Request to set the device's idle count. */
|
||||
#define REQ_SetIdle 0x0A
|
||||
|
||||
/** HID Class Specific Request to get the current HID report protocol mode. */
|
||||
#define REQ_GetProtocol 0x03
|
||||
|
||||
/** HID Class Specific Request to set the current HID report protocol mode. */
|
||||
#define REQ_SetProtocol 0x0B
|
||||
|
||||
/** HID keyboard keycode to indicate that the "1" key is currently pressed. */
|
||||
#define KEY_1 30
|
||||
|
||||
/** HID keyboard keycode to indicate that the "0" key is currently pressed. */
|
||||
#define KEY_0 39
|
||||
|
||||
/** HID keyboard keycode to indicate that the enter key is currently pressed. */
|
||||
#define KEY_ENTER 40
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for the keyboard report structure. This structure matches the report layout
|
||||
* given to the host in the HID Report descriptor, as well as matches the boot protocol report
|
||||
* structure. This means that this one report structure can be used in both Report and Boot Protocol
|
||||
* modes. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t Modifier; /**< Modifier byte, indicating pressed modifier keys such as CTRL or ALT */
|
||||
uint8_t Reserved; /**< Reserved for OEM use, always set to 0 */
|
||||
uint8_t KeyCode[6]; /**< Key code array for pressed keys - up to six can be given simultaneously */
|
||||
} USB_KeyboardReport_Data_t;
|
||||
|
||||
/* Event Handlers: */
|
||||
/** Indicates that this module will catch the USB_Connect event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_Connect);
|
||||
|
||||
/** Indicates that this module will catch the USB_Disconnect event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_Disconnect);
|
||||
|
||||
/** Indicates that this module will catch the USB_ConfigurationChanged event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_ConfigurationChanged);
|
||||
|
||||
/** Indicates that this module will catch the USB_UnhandledControlPacket event when thrown by the library. */
|
||||
HANDLES_EVENT(USB_UnhandledControlPacket);
|
||||
|
||||
/* Function Prototypes: */
|
||||
bool GetNextReport(USB_KeyboardReport_Data_t* ReportData);
|
||||
void SendKey(USB_KeyboardReport_Data_t* KeyboardReportData, uint8_t Key);
|
||||
void Send(USB_KeyboardReport_Data_t* KeyboardReportData, bool SendReport);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,85 @@
|
|||
/** \file
|
||||
*
|
||||
* This file contains special DoxyGen information for the generation of the main page and other special
|
||||
* documentation pages. It is not a project source file.
|
||||
*/
|
||||
|
||||
/** \mainpage Denver Gingerich's USBSnoop Magnetic Card Reader Project
|
||||
*
|
||||
* Firmware for a USB AVR powered USB TTL magnetic stripe reader (using a card
|
||||
* reader such as the Omron V3B-4K) by Denver Gingerich. This project is designed
|
||||
* to be used with the open source Stripe Snoop project at http://stripesnoop.sourceforge.net/.
|
||||
*
|
||||
* See http://ossguy.com/ss_usb/ for the USB reader hardware project website,
|
||||
* including construction and support details.
|
||||
*
|
||||
* To use, connect your magentic card reader device to the USB AVR as follows (pin and port mapping may be adjusted
|
||||
* from the project makefile):
|
||||
*
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td><b>Signal:</b></td>
|
||||
* <td><b>AVR Port:</b></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Track 1 Data</td>
|
||||
* <td>PORTC, Pin 1</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Track 1 Clock</td>
|
||||
* <td>PORTC, Pin 2</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Track 2 Data</td>
|
||||
* <td>PORTC, Pin 3</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Track 2 Clock</td>
|
||||
* <td>PORTC, Pin 0</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Track 3 Data</td>
|
||||
* <td>PORTC, Pin 5</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Track 3 Clock</td>
|
||||
* <td>PORTC, Pin 6</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>Card Detect</td>
|
||||
* <td>PORTC, Pin 4</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
*
|
||||
* This project is based on the LUFA Keyboard demonstration application,
|
||||
* written by Denver Gingerich.
|
||||
*
|
||||
* This application uses a keyboard HID driver to communicate the data collected
|
||||
* a TTL magnetic stripe reader to the connected computer. The raw bitstream
|
||||
* obtained from the magnetic stripe reader is "typed" through the keyboard
|
||||
* driver as 0's and 1's. After every card swipe, the demo will send a return key.
|
||||
*
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td><b>USB Mode:</b></td>
|
||||
* <td>Device</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>USB Class:</b></td>
|
||||
* <td>Human Interface Device (HID)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>USB Subclass:</b></td>
|
||||
* <td>Keyboard</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Relevant Standards:</b></td>
|
||||
* <td>USBIF HID Standard, USBIF HID Usage Tables</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td><b>Usable Speeds:</b></td>
|
||||
* <td>Low Speed Mode, Full Speed Mode</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*/
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
Copyright 2009 Denver Gingerich (denver [at] ossguy [dot] com)
|
||||
Copyright 2009 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
*/
|
||||
|
||||
/*
|
||||
NOTE: The user of this include file MUST define the following macros
|
||||
prior to including the file:
|
||||
|
||||
MAG_T1_CLOCK_PIN Pin connected to Track 1 clock wire (ie. PORTC1)
|
||||
MAG_T1_DATA_PIN Pin connected to Track 1 data wire (ie. PORTC2)
|
||||
MAG_T2_CLOCK_PIN Pin connected to Track 2 clock wire (ie. PORTC3)
|
||||
MAG_T2_DATA_PIN Pin connected to Track 2 data wire (ie. PORTC0)
|
||||
MAG_T3_CLOCK_PIN Pin connected to Track 3 clock wire (ie. PORTC5)
|
||||
MAG_T3_DATA_PIN Pin connected to Track 3 data wire (ie. PORTC6)
|
||||
MAG_CLS_PIN Pin connected to card loaded wire (ie. PORTC4)
|
||||
MAG_PIN PIN macro for the reader's port (ie. PINC)
|
||||
MAG_DDR DDR macro for the reader's port (ie. DDRC)
|
||||
MAG_PORT PORT macro for the reader's port (ie. PORTC)
|
||||
|
||||
The example macros listed above assume that the Track 2 data wire is
|
||||
connected to pin 0 on port C, the Track 2 clock wire is connected to
|
||||
pin 3 on port C (similarly for Tracks 1 and 3), and the card loaded
|
||||
wire is connected to pin 4 on port C.
|
||||
|
||||
If the magstripe reader you are using only reads one or two tracks,
|
||||
then set the clock and data pins for the tracks it doesn't read to a
|
||||
pin that is unused. For example, on the AT90USBKey, any of the pins on
|
||||
port C that do not have wires attached will be unused since they are
|
||||
not connected to any onboard devices (such as the joystick or
|
||||
temperature sensor).
|
||||
|
||||
Connecting wires to pins on different ports (ie. a data wire to pin 0
|
||||
on port C and a clock wire to pin 0 on port D) is currently
|
||||
unsupported. All pins specified above must be on the same port.
|
||||
*/
|
||||
|
||||
/** \file
|
||||
*
|
||||
* Driver header for a TTL Magnetic Card reader device (such as the Omron V3B-4K).
|
||||
*/
|
||||
|
||||
#ifndef _MAGSTRIPEHW_H_
|
||||
#define _MAGSTRIPEHW_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
|
||||
#include <LUFA/Common/Common.h>
|
||||
|
||||
/* Private Interface - For use in library only: */
|
||||
/* Macros: */
|
||||
/** Mask of the track data, clock and card detection pins. */
|
||||
#define MAG_MASK (MAG_T1_DATA | MAG_T1_CLOCK | \
|
||||
MAG_T2_DATA | MAG_T2_CLOCK | \
|
||||
MAG_T3_DATA | MAG_T3_CLOCK | \
|
||||
MAG_CARDPRESENT)
|
||||
|
||||
/* Public Interface - May be used in end-application: */
|
||||
/* Inline Functions: */
|
||||
/** Initializes the magnetic stripe card reader ports and pins so that the card reader
|
||||
* device can be controlled and read by the card reader driver. This must be called before
|
||||
* trying to read any of the card reader's status lines.
|
||||
*/
|
||||
static inline void Magstripe_Init(void)
|
||||
{
|
||||
MAG_DDR &= ~MAG_MASK;
|
||||
MAG_PORT |= MAG_MASK;
|
||||
};
|
||||
|
||||
/** Returns the status of all the magnetic card reader's outputs.
|
||||
*
|
||||
* \return A mask indicating which card lines are high or low
|
||||
*/
|
||||
static inline uint8_t Magstripe_GetStatus(void) ATTR_WARN_UNUSED_RESULT;
|
||||
static inline uint8_t Magstripe_GetStatus(void)
|
||||
{
|
||||
/* Magstripe IOs are active low and must be inverted when read */
|
||||
return ((uint8_t)~MAG_PIN & MAG_MASK);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,712 @@
|
|||
# Hey Emacs, this is a -*- makefile -*-
|
||||
#----------------------------------------------------------------------------
|
||||
# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
|
||||
# >> Modified for use with the LUFA project. <<
|
||||
#
|
||||
# Released to the Public Domain
|
||||
#
|
||||
# Additional material for this makefile was written by:
|
||||
# Peter Fleury
|
||||
# Tim Henigan
|
||||
# Colin O'Flynn
|
||||
# Reiner Patommel
|
||||
# Markus Pfaff
|
||||
# Sander Pool
|
||||
# Frederik Rouleau
|
||||
# Carlos Lamas
|
||||
# Dean Camera
|
||||
# Opendous Inc.
|
||||
# Denver Gingerich
|
||||
#
|
||||
#----------------------------------------------------------------------------
|
||||
# On command line:
|
||||
#
|
||||
# make all = Make software.
|
||||
#
|
||||
# make clean = Clean out built project files.
|
||||
#
|
||||
# make coff = Convert ELF to AVR COFF.
|
||||
#
|
||||
# make extcoff = Convert ELF to AVR Extended COFF.
|
||||
#
|
||||
# make program = Download the hex file to the device, using avrdude.
|
||||
# Please customize the avrdude settings below first!
|
||||
#
|
||||
# make dfu = Download the hex file to the device, using dfu-programmer (must
|
||||
# have dfu-programmer installed).
|
||||
#
|
||||
# make flip = Download the hex file to the device, using Atmel FLIP (must
|
||||
# have Atmel FLIP installed).
|
||||
#
|
||||
# make dfu-ee = Download the eeprom file to the device, using dfu-programmer
|
||||
# (must have dfu-programmer installed).
|
||||
#
|
||||
# make flip-ee = Download the eeprom file to the device, using Atmel FLIP
|
||||
# (must have Atmel FLIP installed).
|
||||
#
|
||||
# make doxygen = Generate DoxyGen documentation for the project (must have
|
||||
# DoxyGen installed)
|
||||
#
|
||||
# make debug = Start either simulavr or avarice as specified for debugging,
|
||||
# with avr-gdb or avr-insight as the front end for debugging.
|
||||
#
|
||||
# make filename.s = Just compile filename.c into the assembler code only.
|
||||
#
|
||||
# make filename.i = Create a preprocessed source file for use in submitting
|
||||
# bug reports to the GCC project.
|
||||
#
|
||||
# To rebuild project do "make clean" then "make all".
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = at90usb1287
|
||||
|
||||
|
||||
# Target board (see library BoardTypes.h documentation, USER or blank for projects not requiring
|
||||
# LUFA board drivers). If USER is selected, put custom board drivers in a directory called
|
||||
# "Board" inside the application directory.
|
||||
BOARD = USBKEY
|
||||
|
||||
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency. You can then use this symbol in your source code to
|
||||
# calculate timings. Do NOT tack on a 'UL' at the end, this will be done
|
||||
# automatically to create a 32-bit value in your source code.
|
||||
# Typical values are:
|
||||
# F_CPU = 1000000
|
||||
# F_CPU = 1843200
|
||||
# F_CPU = 2000000
|
||||
# F_CPU = 3686400
|
||||
# F_CPU = 4000000
|
||||
# F_CPU = 7372800
|
||||
# F_CPU = 8000000
|
||||
# F_CPU = 11059200
|
||||
# F_CPU = 14745600
|
||||
# F_CPU = 16000000
|
||||
# F_CPU = 18432000
|
||||
# F_CPU = 20000000
|
||||
F_CPU = 16000000
|
||||
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = Magstripe
|
||||
|
||||
|
||||
# Object files directory
|
||||
# To put object files in current directory, use a dot (.), do NOT make
|
||||
# this an empty or blank macro!
|
||||
OBJDIR = .
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c \
|
||||
Descriptors.c \
|
||||
CircularBitBuffer.c \
|
||||
../../LUFA/Scheduler/Scheduler.c \
|
||||
../../LUFA/Drivers/USB/LowLevel/LowLevel.c \
|
||||
../../LUFA/Drivers/USB/LowLevel/Endpoint.c \
|
||||
../../LUFA/Drivers/USB/LowLevel/DevChapter9.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/USBTask.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/USBInterrupt.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/Events.c \
|
||||
../../LUFA/Drivers/USB/HighLevel/StdDescriptors.c \
|
||||
|
||||
# List C++ source files here. (C dependencies are automatically generated.)
|
||||
CPPSRC =
|
||||
|
||||
|
||||
# List Assembler source files here.
|
||||
# Make them always end in a capital .S. Files ending in a lowercase .s
|
||||
# will not be considered source files but generated files (assembler
|
||||
# output from the compiler), and will be deleted upon "make clean"!
|
||||
# Even though the DOS/Win* filesystem matches both .s and .S the same,
|
||||
# it will preserve the spelling of the filenames, and gcc itself does
|
||||
# care about how the name is spelled on its command-line.
|
||||
ASRC =
|
||||
|
||||
|
||||
# Optimization level, can be [0, 1, 2, 3, s].
|
||||
# 0 = turn off optimization. s = optimize for size.
|
||||
# (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
|
||||
OPT = s
|
||||
|
||||
|
||||
# Debugging format.
|
||||
# Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
|
||||
# AVR Studio 4.10 requires dwarf-2.
|
||||
# AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
|
||||
DEBUG = dwarf-2
|
||||
|
||||
|
||||
# List any extra directories to look for include files here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRAINCDIRS = ../../
|
||||
|
||||
|
||||
# Compiler flag to set the C Standard level.
|
||||
# c89 = "ANSI" C
|
||||
# gnu89 = c89 plus GCC extensions
|
||||
# c99 = ISO C99 standard (not yet fully implemented)
|
||||
# gnu99 = c99 plus GCC extensions
|
||||
CSTANDARD = -std=gnu99
|
||||
|
||||
|
||||
# Place -D or -U options here for C sources
|
||||
CDEFS = -DF_CPU=$(F_CPU)UL -DBOARD=BOARD_$(BOARD) -DUSE_NONSTANDARD_DESCRIPTOR_NAMES -DNO_STREAM_CALLBACKS
|
||||
CDEFS += -DUSB_DEVICE_ONLY -DUSE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
|
||||
|
||||
CDEFS += -DMAG_T1_CLOCK="(1 << 0)"
|
||||
CDEFS += -DMAG_T1_DATA="(1 << 1)"
|
||||
CDEFS += -DMAG_T2_CLOCK="(1 << 2)"
|
||||
CDEFS += -DMAG_T2_DATA="(1 << 3)"
|
||||
CDEFS += -DMAG_T3_CLOCK="(1 << 4)"
|
||||
CDEFS += -DMAG_T3_DATA="(1 << 5)"
|
||||
CDEFS += -DMAG_CARDPRESENT="(1 << 6)"
|
||||
CDEFS += -DMAG_PIN=PINB
|
||||
CDEFS += -DMAG_DDR=DDRB
|
||||
CDEFS += -DMAG_PORT=PORTB
|
||||
|
||||
# Place -D or -U options here for ASM sources
|
||||
ADEFS = -DF_CPU=$(F_CPU)
|
||||
|
||||
|
||||
# Place -D or -U options here for C++ sources
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL
|
||||
#CPPDEFS += -D__STDC_LIMIT_MACROS
|
||||
#CPPDEFS += -D__STDC_CONSTANT_MACROS
|
||||
|
||||
|
||||
|
||||
#---------------- Compiler Options C ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CFLAGS = -g$(DEBUG)
|
||||
CFLAGS += $(CDEFS)
|
||||
CFLAGS += -O$(OPT)
|
||||
CFLAGS += -funsigned-char
|
||||
CFLAGS += -funsigned-bitfields
|
||||
CFLAGS += -fpack-struct
|
||||
CFLAGS += -fshort-enums
|
||||
CFLAGS += -ffunction-sections
|
||||
CFLAGS += -finline-limit=20
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
CFLAGS += -Wundef
|
||||
#CFLAGS += -fno-unit-at-a-time
|
||||
#CFLAGS += -Wunreachable-code
|
||||
#CFLAGS += -Wsign-compare
|
||||
CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
|
||||
CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
CFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Compiler Options C++ ----------------
|
||||
# -g*: generate debugging information
|
||||
# -O*: optimization level
|
||||
# -f...: tuning, see GCC manual and avr-libc documentation
|
||||
# -Wall...: warning level
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns...: create assembler listing
|
||||
CPPFLAGS = -g$(DEBUG)
|
||||
CPPFLAGS += $(CPPDEFS)
|
||||
CPPFLAGS += -O$(OPT)
|
||||
CPPFLAGS += -funsigned-char
|
||||
CPPFLAGS += -funsigned-bitfields
|
||||
CPPFLAGS += -fpack-struct
|
||||
CPPFLAGS += -fshort-enums
|
||||
CPPFLAGS += -fno-exceptions
|
||||
CPPFLAGS += -Wall
|
||||
CFLAGS += -Wundef
|
||||
#CPPFLAGS += -fno-unit-at-a-time
|
||||
#CPPFLAGS += -Wstrict-prototypes
|
||||
#CPPFLAGS += -Wunreachable-code
|
||||
#CPPFLAGS += -Wsign-compare
|
||||
CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
|
||||
CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
|
||||
#CPPFLAGS += $(CSTANDARD)
|
||||
|
||||
|
||||
#---------------- Assembler Options ----------------
|
||||
# -Wa,...: tell GCC to pass this to the assembler.
|
||||
# -adhlns: create listing
|
||||
# -gstabs: have the assembler create line number information; note that
|
||||
# for use in COFF files, additional information about filenames
|
||||
# and function names needs to be present in the assembler source
|
||||
# files -- see avr-libc docs [FIXME: not yet described there]
|
||||
# -listing-cont-lines: Sets the maximum number of continuation lines of hex
|
||||
# dump that will be displayed for a given single line of source input.
|
||||
ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
|
||||
|
||||
|
||||
#---------------- Library Options ----------------
|
||||
# Minimalistic printf version
|
||||
PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
|
||||
|
||||
# Floating point printf version (requires MATH_LIB = -lm below)
|
||||
PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard printf version.
|
||||
PRINTF_LIB =
|
||||
#PRINTF_LIB = $(PRINTF_LIB_MIN)
|
||||
#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
|
||||
|
||||
|
||||
# Minimalistic scanf version
|
||||
SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
|
||||
|
||||
# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
|
||||
SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
|
||||
|
||||
# If this is left blank, then it will use the Standard scanf version.
|
||||
SCANF_LIB =
|
||||
#SCANF_LIB = $(SCANF_LIB_MIN)
|
||||
#SCANF_LIB = $(SCANF_LIB_FLOAT)
|
||||
|
||||
|
||||
MATH_LIB = -lm
|
||||
|
||||
|
||||
# List any extra directories to look for libraries here.
|
||||
# Each directory must be seperated by a space.
|
||||
# Use forward slashes for directory separators.
|
||||
# For a directory that has spaces, enclose it in quotes.
|
||||
EXTRALIBDIRS =
|
||||
|
||||
|
||||
|
||||
#---------------- External Memory Options ----------------
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# used for variables (.data/.bss) and heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
# 64 KB of external RAM, starting after internal RAM (ATmega128!),
|
||||
# only used for heap (malloc()).
|
||||
#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
|
||||
|
||||
EXTMEMOPTS =
|
||||
|
||||
|
||||
|
||||
#---------------- Linker Options ----------------
|
||||
# -Wl,...: tell GCC to pass this to linker.
|
||||
# -Map: create map file
|
||||
# --cref: add cross reference to map file
|
||||
LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
|
||||
LDFLAGS += -Wl,--relax
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
LDFLAGS += $(EXTMEMOPTS)
|
||||
LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
|
||||
LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
|
||||
#LDFLAGS += -T linker_script.x
|
||||
|
||||
|
||||
|
||||
#---------------- Programming Options (avrdude) ----------------
|
||||
|
||||
# Programming hardware: alf avr910 avrisp bascom bsd
|
||||
# dt006 pavr picoweb pony-stk200 sp12 stk200 stk500
|
||||
#
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = jtagmkII
|
||||
|
||||
# com1 = serial port. Use lpt1 to connect to parallel port.
|
||||
AVRDUDE_PORT = usb
|
||||
|
||||
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
|
||||
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
|
||||
|
||||
|
||||
# Uncomment the following if you want avrdude's erase cycle counter.
|
||||
# Note that this counter needs to be initialized first using -Yn,
|
||||
# see avrdude manual.
|
||||
#AVRDUDE_ERASE_COUNTER = -y
|
||||
|
||||
# Uncomment the following if you do /not/ wish a verification to be
|
||||
# performed after programming the device.
|
||||
#AVRDUDE_NO_VERIFY = -V
|
||||
|
||||
# Increase verbosity level. Please use this when submitting bug
|
||||
# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude>
|
||||
# to submit bug reports.
|
||||
#AVRDUDE_VERBOSE = -v -v
|
||||
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
|
||||
AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
|
||||
|
||||
|
||||
|
||||
#---------------- Debugging Options ----------------
|
||||
|
||||
# For simulavr only - target MCU frequency.
|
||||
DEBUG_MFREQ = $(F_CPU)
|
||||
|
||||
# Set the DEBUG_UI to either gdb or insight.
|
||||
# DEBUG_UI = gdb
|
||||
DEBUG_UI = insight
|
||||
|
||||
# Set the debugging back-end to either avarice, simulavr.
|
||||
DEBUG_BACKEND = avarice
|
||||
#DEBUG_BACKEND = simulavr
|
||||
|
||||
# GDB Init Filename.
|
||||
GDBINIT_FILE = __avr_gdbinit
|
||||
|
||||
# When using avarice settings for the JTAG
|
||||
JTAG_DEV = /dev/com1
|
||||
|
||||
# Debugging port used to communicate between GDB / avarice / simulavr.
|
||||
DEBUG_PORT = 4242
|
||||
|
||||
# Debugging host used to communicate between GDB / avarice / simulavr, normally
|
||||
# just set to localhost unless doing some sort of crazy debugging when
|
||||
# avarice is running on a different computer.
|
||||
DEBUG_HOST = localhost
|
||||
|
||||
|
||||
|
||||
#============================================================================
|
||||
|
||||
|
||||
# Define programs and commands.
|
||||
SHELL = sh
|
||||
CC = avr-gcc
|
||||
OBJCOPY = avr-objcopy
|
||||
OBJDUMP = avr-objdump
|
||||
SIZE = avr-size
|
||||
AR = avr-ar rcs
|
||||
NM = avr-nm
|
||||
AVRDUDE = avrdude
|
||||
REMOVE = rm -f
|
||||
REMOVEDIR = rm -rf
|
||||
COPY = cp
|
||||
WINSHELL = cmd
|
||||
|
||||
# Define Messages
|
||||
# English
|
||||
MSG_ERRORS_NONE = Errors: none
|
||||
MSG_BEGIN = -------- begin --------
|
||||
MSG_END = -------- end --------
|
||||
MSG_SIZE_BEFORE = Size before:
|
||||
MSG_SIZE_AFTER = Size after:
|
||||
MSG_COFF = Converting to AVR COFF:
|
||||
MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
|
||||
MSG_FLASH = Creating load file for Flash:
|
||||
MSG_EEPROM = Creating load file for EEPROM:
|
||||
MSG_EXTENDED_LISTING = Creating Extended Listing:
|
||||
MSG_SYMBOL_TABLE = Creating Symbol Table:
|
||||
MSG_LINKING = Linking:
|
||||
MSG_COMPILING = Compiling C:
|
||||
MSG_COMPILING_CPP = Compiling C++:
|
||||
MSG_ASSEMBLING = Assembling:
|
||||
MSG_CLEANING = Cleaning project:
|
||||
MSG_CREATING_LIBRARY = Creating library:
|
||||
|
||||
|
||||
|
||||
|
||||
# Define all object files.
|
||||
OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
|
||||
|
||||
# Define all listing files.
|
||||
LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
|
||||
|
||||
|
||||
# Compiler flags to generate dependency files.
|
||||
GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
|
||||
|
||||
|
||||
# Combine all necessary flags and optional flags.
|
||||
# Add target processor to flags.
|
||||
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
|
||||
ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
|
||||
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# Default target.
|
||||
all: begin gccversion sizebefore build checkhooks checklibmode sizeafter end
|
||||
|
||||
# Change the build target to build a HEX file or a library.
|
||||
build: elf hex eep lss sym
|
||||
#build: lib
|
||||
|
||||
|
||||
elf: $(TARGET).elf
|
||||
hex: $(TARGET).hex
|
||||
eep: $(TARGET).eep
|
||||
lss: $(TARGET).lss
|
||||
sym: $(TARGET).sym
|
||||
LIBNAME=lib$(TARGET).a
|
||||
lib: $(LIBNAME)
|
||||
|
||||
|
||||
|
||||
# Eye candy.
|
||||
# AVR Studio 3.x does not check make's exit code but relies on
|
||||
# the following magic strings to be generated by the compile job.
|
||||
begin:
|
||||
@echo
|
||||
@echo $(MSG_BEGIN)
|
||||
|
||||
end:
|
||||
@echo $(MSG_END)
|
||||
@echo
|
||||
|
||||
|
||||
# Display size of file.
|
||||
HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
|
||||
ELFSIZE = $(SIZE) $(MCU_FLAG) $(FORMAT_FLAG) $(TARGET).elf
|
||||
MCU_FLAG = $(shell $(SIZE) --help | grep -- --mcu > /dev/null && echo --mcu=$(MCU) )
|
||||
FORMAT_FLAG = $(shell $(SIZE) --help | grep -- --format=.*avr > /dev/null && echo --format=avr )
|
||||
|
||||
sizebefore:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
|
||||
2>/dev/null; echo; fi
|
||||
|
||||
sizeafter:
|
||||
@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
|
||||
2>/dev/null; echo; fi
|
||||
|
||||
checkhooks: build
|
||||
@echo
|
||||
@echo ------- Unhooked LUFA Events -------
|
||||
@$(shell) (grep -s '^Event.*LUFA/.*\\.o' $(TARGET).map | \
|
||||
cut -d' ' -f1 | cut -d'_' -f2- | grep ".*") || \
|
||||
echo "(None)"
|
||||
@echo ----- End Unhooked LUFA Events -----
|
||||
|
||||
checklibmode:
|
||||
@echo
|
||||
@echo ----------- Library Mode -----------
|
||||
@$(shell) ($(CC) $(ALL_CFLAGS) -E -dM - < /dev/null \
|
||||
| grep 'USB_\(DEVICE\|HOST\)_ONLY' | cut -d' ' -f2 | grep ".*") \
|
||||
|| echo "No specific mode (both device and host mode allowable)."
|
||||
@echo ------------------------------------
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
flip: $(TARGET).hex
|
||||
batchisp -hardware usb -device $(MCU) -operation erase f
|
||||
batchisp -hardware usb -device $(MCU) -operation loadbuffer $(TARGET).hex program
|
||||
batchisp -hardware usb -device $(MCU) -operation start reset 0
|
||||
|
||||
dfu: $(TARGET).hex
|
||||
dfu-programmer $(MCU) erase
|
||||
dfu-programmer $(MCU) flash --debug 1 $(TARGET).hex
|
||||
dfu-programmer $(MCU) reset
|
||||
|
||||
flip-ee: $(TARGET).hex $(TARGET).eep
|
||||
copy $(TARGET).eep $(TARGET)eep.hex
|
||||
batchisp -hardware usb -device $(MCU) -operation memory EEPROM erase
|
||||
batchisp -hardware usb -device $(MCU) -operation memory EEPROM loadbuffer $(TARGET)eep.hex program
|
||||
batchisp -hardware usb -device $(MCU) -operation start reset 0
|
||||
|
||||
dfu-ee: $(TARGET).hex $(TARGET).eep
|
||||
dfu-programmer $(MCU) erase
|
||||
dfu-programmer $(MCU) eeprom --debug 1 $(TARGET).eep
|
||||
dfu-programmer $(MCU) reset
|
||||
|
||||
# Generate avr-gdb config/init file which does the following:
|
||||
# define the reset signal, load the target file, connect to target, and set
|
||||
# a breakpoint at main().
|
||||
gdb-config:
|
||||
@$(REMOVE) $(GDBINIT_FILE)
|
||||
@echo define reset >> $(GDBINIT_FILE)
|
||||
@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
|
||||
@echo end >> $(GDBINIT_FILE)
|
||||
@echo file $(TARGET).elf >> $(GDBINIT_FILE)
|
||||
@echo target remote $(DEBUG_HOST):$(DEBUG_PORT) >> $(GDBINIT_FILE)
|
||||
ifeq ($(DEBUG_BACKEND),simulavr)
|
||||
@echo load >> $(GDBINIT_FILE)
|
||||
endif
|
||||
@echo break main >> $(GDBINIT_FILE)
|
||||
|
||||
debug: gdb-config $(TARGET).elf
|
||||
ifeq ($(DEBUG_BACKEND), avarice)
|
||||
@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
|
||||
@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
|
||||
$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
|
||||
@$(WINSHELL) /c pause
|
||||
|
||||
else
|
||||
@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
|
||||
$(DEBUG_MFREQ) --port $(DEBUG_PORT)
|
||||
endif
|
||||
@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
|
||||
|
||||
|
||||
|
||||
|
||||
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
|
||||
COFFCONVERT = $(OBJCOPY) --debugging
|
||||
COFFCONVERT += --change-section-address .data-0x800000
|
||||
COFFCONVERT += --change-section-address .bss-0x800000
|
||||
COFFCONVERT += --change-section-address .noinit-0x800000
|
||||
COFFCONVERT += --change-section-address .eeprom-0x810000
|
||||
|
||||
|
||||
|
||||
coff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
extcoff: $(TARGET).elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
|
||||
$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
|
||||
|
||||
|
||||
|
||||
# Create final output files (.hex, .eep) from ELF output file.
|
||||
%.hex: %.elf
|
||||
@echo
|
||||
@echo $(MSG_FLASH) $@
|
||||
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
|
||||
|
||||
%.eep: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EEPROM) $@
|
||||
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
|
||||
--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
|
||||
|
||||
# Create extended listing file from ELF output file.
|
||||
%.lss: %.elf
|
||||
@echo
|
||||
@echo $(MSG_EXTENDED_LISTING) $@
|
||||
$(OBJDUMP) -h -z -S $< > $@
|
||||
|
||||
# Create a symbol table from ELF output file.
|
||||
%.sym: %.elf
|
||||
@echo
|
||||
@echo $(MSG_SYMBOL_TABLE) $@
|
||||
$(NM) -n $< > $@
|
||||
|
||||
|
||||
|
||||
# Create library from object files.
|
||||
.SECONDARY : $(TARGET).a
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.a: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_CREATING_LIBRARY) $@
|
||||
$(AR) $@ $(OBJ)
|
||||
|
||||
|
||||
# Link: create ELF output file from object files.
|
||||
.SECONDARY : $(TARGET).elf
|
||||
.PRECIOUS : $(OBJ)
|
||||
%.elf: $(OBJ)
|
||||
@echo
|
||||
@echo $(MSG_LINKING) $@
|
||||
$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
|
||||
|
||||
|
||||
# Compile: create object files from C source files.
|
||||
$(OBJDIR)/%.o : %.c
|
||||
@echo
|
||||
@echo $(MSG_COMPILING) $<
|
||||
$(CC) -c $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create object files from C++ source files.
|
||||
$(OBJDIR)/%.o : %.cpp
|
||||
@echo
|
||||
@echo $(MSG_COMPILING_CPP) $<
|
||||
$(CC) -c $(ALL_CPPFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C source files.
|
||||
%.s : %.c
|
||||
$(CC) -S $(ALL_CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Compile: create assembler files from C++ source files.
|
||||
%.s : %.cpp
|
||||
$(CC) -S $(ALL_CPPFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Assemble: create object files from assembler source files.
|
||||
$(OBJDIR)/%.o : %.S
|
||||
@echo
|
||||
@echo $(MSG_ASSEMBLING) $<
|
||||
$(CC) -c $(ALL_ASFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Create preprocessed source for use in sending a bug report.
|
||||
%.i : %.c
|
||||
$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@
|
||||
|
||||
|
||||
# Target: clean project.
|
||||
clean: begin clean_list clean_binary end
|
||||
|
||||
clean_binary:
|
||||
$(REMOVE) $(TARGET).hex
|
||||
|
||||
clean_list:
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
$(REMOVE) $(SRC:.c=.i)
|
||||
$(REMOVEDIR) .dep
|
||||
|
||||
|
||||
doxygen:
|
||||
@echo Generating Project Documentation...
|
||||
@doxygen Doxygen.conf
|
||||
@echo Documentation Generation Complete.
|
||||
|
||||
clean_doxygen:
|
||||
rm -rf Documentation
|
||||
|
||||
# Create object files directory
|
||||
$(shell mkdir $(OBJDIR) 2>/dev/null)
|
||||
|
||||
|
||||
# Include the dependency files.
|
||||
-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
|
||||
|
||||
|
||||
# Listing of phony targets.
|
||||
.PHONY : all checkhooks checklibmode begin \
|
||||
finish end sizebefore sizeafter gccversion \
|
||||
build elf hex eep lss sym coff extcoff \
|
||||
clean clean_list clean_binary program debug \
|
||||
gdb-config doxygen dfu flip
|
|
@ -0,0 +1,25 @@
|
|||
#
|
||||
# LUFA Library
|
||||
# Copyright (C) Dean Camera, 2009.
|
||||
#
|
||||
# dean [at] fourwalledcubicle [dot] com
|
||||
# www.fourwalledcubicle.com
|
||||
#
|
||||
|
||||
# Makefile to build all the LUFA Projects. Call with "make all" to
|
||||
# rebuild all projects.
|
||||
|
||||
# Projects are pre-cleaned before each one is built, to ensure any
|
||||
# custom LUFA library build options are reflected in the compiled
|
||||
# code.
|
||||
|
||||
all:
|
||||
make -C Magstripe clean
|
||||
make -C Magstripe all
|
||||
|
||||
make -C AVRISP_Programmer clean
|
||||
make -C AVRISP_Programmer all
|
||||
|
||||
%:
|
||||
make -C Magstripe $@
|
||||
make -C AVRISP_Programmer $@
|
Loading…
Reference in New Issue