mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-16 21:01:31 +00:00
Moved all source to the trunk directory.
This commit is contained in:
parent
6a10d6b465
commit
032a83e9e1
176
Projects/AVRISP_Programmer/AVRISP_Firmware_Design.txt
Normal file
176
Projects/AVRISP_Programmer/AVRISP_Firmware_Design.txt
Normal file
@ -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;
|
||||||
|
|
1
Projects/AVRISP_Programmer/AVRISP_Programmer.aps
Normal file
1
Projects/AVRISP_Programmer/AVRISP_Programmer.aps
Normal file
@ -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>
|
886
Projects/AVRISP_Programmer/AVRISP_Programmer.c
Normal file
886
Projects/AVRISP_Programmer/AVRISP_Programmer.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
194
Projects/AVRISP_Programmer/AVRISP_Programmer.h
Normal file
194
Projects/AVRISP_Programmer/AVRISP_Programmer.h
Normal file
@ -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
|
89
Projects/AVRISP_Programmer/AVRISP_Programmer.txt
Normal file
89
Projects/AVRISP_Programmer/AVRISP_Programmer.txt
Normal file
@ -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>
|
||||||
|
*/
|
BIN
Projects/AVRISP_Programmer/AVRISP_Programmer_Picture.jpg
Normal file
BIN
Projects/AVRISP_Programmer/AVRISP_Programmer_Picture.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 73 KiB |
263
Projects/AVRISP_Programmer/Descriptors.c
Normal file
263
Projects/AVRISP_Programmer/Descriptors.c
Normal file
@ -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;
|
||||||
|
}
|
98
Projects/AVRISP_Programmer/Descriptors.h
Normal file
98
Projects/AVRISP_Programmer/Descriptors.h
Normal file
@ -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
|
1485
Projects/AVRISP_Programmer/Doxygen.conf
Normal file
1485
Projects/AVRISP_Programmer/Doxygen.conf
Normal file
File diff suppressed because it is too large
Load Diff
55
Projects/AVRISP_Programmer/LUFA AVRISP_Programmer.inf
Normal file
55
Projects/AVRISP_Programmer/LUFA AVRISP_Programmer.inf
Normal file
@ -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"
|
120
Projects/AVRISP_Programmer/RingBuff.c
Normal file
120
Projects/AVRISP_Programmer/RingBuff.c
Normal file
@ -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
|
116
Projects/AVRISP_Programmer/RingBuff.h
Normal file
116
Projects/AVRISP_Programmer/RingBuff.h
Normal file
@ -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
|
104
Projects/AVRISP_Programmer/Sample_Programming_Session.txt
Normal file
104
Projects/AVRISP_Programmer/Sample_Programming_Session.txt
Normal file
@ -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.
|
||||||
|
|
704
Projects/AVRISP_Programmer/makefile
Normal file
704
Projects/AVRISP_Programmer/makefile
Normal file
@ -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
|
113
Projects/Magstripe/CircularBitBuffer.c
Normal file
113
Projects/Magstripe/CircularBitBuffer.c
Normal file
@ -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;
|
||||||
|
}
|
95
Projects/Magstripe/CircularBitBuffer.h
Normal file
95
Projects/Magstripe/CircularBitBuffer.h
Normal file
@ -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
|
247
Projects/Magstripe/Descriptors.c
Normal file
247
Projects/Magstripe/Descriptors.c
Normal file
@ -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;
|
||||||
|
}
|
98
Projects/Magstripe/Descriptors.h
Normal file
98
Projects/Magstripe/Descriptors.h
Normal file
@ -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
|
1485
Projects/Magstripe/Doxygen.conf
Normal file
1485
Projects/Magstripe/Doxygen.conf
Normal file
File diff suppressed because it is too large
Load Diff
1
Projects/Magstripe/Magstripe.aps
Normal file
1
Projects/Magstripe/Magstripe.aps
Normal file
@ -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>
|
436
Projects/Magstripe/Magstripe.c
Normal file
436
Projects/Magstripe/Magstripe.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
121
Projects/Magstripe/Magstripe.h
Normal file
121
Projects/Magstripe/Magstripe.h
Normal file
@ -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
|
85
Projects/Magstripe/Magstripe.txt
Normal file
85
Projects/Magstripe/Magstripe.txt
Normal file
@ -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>
|
||||||
|
*/
|
100
Projects/Magstripe/MagstripeHW.h
Normal file
100
Projects/Magstripe/MagstripeHW.h
Normal file
@ -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
|
712
Projects/Magstripe/makefile
Normal file
712
Projects/Magstripe/makefile
Normal file
@ -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
|
25
Projects/makefile
Normal file
25
Projects/makefile
Normal file
@ -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
Block a user