Merge of arduino-1.0.1. Work in progress...
This commit is contained in:
commit
a3dbb49c07
13
boards.txt
13
boards.txt
|
@ -7,14 +7,22 @@ uno.upload.tool=avrdude
|
|||
uno.upload.protocol=arduino
|
||||
uno.upload.maximum_size=32256
|
||||
uno.upload.speed=115200
|
||||
|
||||
uno.bootloader.tool=avrdude
|
||||
uno.bootloader.erase.params=-e -Ulock:w:0x3F:m -Uefuse:w:0x05:m -Uhfuse:w:0xde:m -Ulfuse:w:0xff:m
|
||||
uno.bootloader.write.params=-Uflash:w:{bootloader.file}:i -Ulock:w:0x0F:m
|
||||
uno.bootloader.low_fuses=0xFF
|
||||
uno.bootloader.high_fuses=0xDE
|
||||
uno.bootloader.extended_fuses=0x05
|
||||
uno.bootloader.unlock_bits=0x3F
|
||||
uno.bootloader.lock_bits=0x0F
|
||||
uno.bootloader.erase.params=-e -Ulock:w:{bootloader.unlock_bits}:m -Uefuse:w:{bootloader.extended_fuses}:m -Uhfuse:w:{bootloader.high_fuses}:m -Ulfuse:w:{bootloader.low_fuses}:m
|
||||
uno.bootloader.write.params=-Uflash:w:{bootloader.file}:i -Ulock:w:{bootloader.lock_bits}:m
|
||||
uno.bootloader.file={runtime.ide.path}/hardware/arduino/avr/optiboot/optiboot_atmega328.hex
|
||||
|
||||
uno.build.mcu=atmega328p
|
||||
uno.build.f_cpu=16000000L
|
||||
uno.build.core=arduino
|
||||
uno.build.variant=standard
|
||||
uno.build.extra_flags=
|
||||
|
||||
##############################################################
|
||||
|
||||
|
@ -162,6 +170,7 @@ leonardo.build.vid=0x2341
|
|||
leonardo.build.pid=0x8036
|
||||
leonardo.build.core=arduino
|
||||
leonardo.build.variant=leonardo
|
||||
leonardo.build.extra_flags=-DUSB_VID={build.vid} -DDUSB_PID={build.pid}
|
||||
|
||||
##############################################################
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,714 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2011.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, 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 CDC class bootloader. This file contains the complete bootloader logic.
|
||||
*/
|
||||
|
||||
#define INCLUDE_FROM_CATERINA_C
|
||||
#include "Caterina.h"
|
||||
|
||||
/** Contains the current baud rate and other settings of the first virtual serial port. This must be retained as some
|
||||
* operating systems will not open the port unless the settings can be set successfully.
|
||||
*/
|
||||
static CDC_LineEncoding_t LineEncoding = { .BaudRateBPS = 0,
|
||||
.CharFormat = CDC_LINEENCODING_OneStopBit,
|
||||
.ParityType = CDC_PARITY_None,
|
||||
.DataBits = 8 };
|
||||
|
||||
/** Current address counter. This stores the current address of the FLASH or EEPROM as set by the host,
|
||||
* and is used when reading or writing to the AVRs memory (either FLASH or EEPROM depending on the issued
|
||||
* command.)
|
||||
*/
|
||||
static uint32_t CurrAddress;
|
||||
|
||||
/** Flag to indicate if the bootloader should be running, or should exit and allow the application code to run
|
||||
* via a watchdog reset. When cleared the bootloader will exit, starting the watchdog and entering an infinite
|
||||
* loop until the AVR restarts and the application runs.
|
||||
*/
|
||||
static bool RunBootloader = true;
|
||||
|
||||
/* Pulse generation counters to keep track of the time remaining for each pulse type */
|
||||
#define TX_RX_LED_PULSE_PERIOD 100
|
||||
uint16_t TxLEDPulse = 0; // time remaining for Tx LED pulse
|
||||
uint16_t RxLEDPulse = 0; // time remaining for Rx LED pulse
|
||||
|
||||
/* Bootloader timeout timer */
|
||||
#define TIMEOUT_PERIOD 8000
|
||||
uint16_t Timeout = 0;
|
||||
|
||||
uint16_t bootKey = 0x7777;
|
||||
volatile uint16_t *const bootKeyPtr = (volatile uint16_t *)0x0800;
|
||||
|
||||
void StartSketch(void)
|
||||
{
|
||||
cli();
|
||||
|
||||
/* Undo TIMER1 setup and clear the count before running the sketch */
|
||||
TIMSK1 = 0;
|
||||
TCCR1B = 0;
|
||||
TCNT1H = 0; // 16-bit write to TCNT1 requires high byte be written first
|
||||
TCNT1L = 0;
|
||||
|
||||
/* Relocate the interrupt vector table to the application section */
|
||||
MCUCR = (1 << IVCE);
|
||||
MCUCR = 0;
|
||||
|
||||
L_LED_OFF();
|
||||
TX_LED_OFF();
|
||||
RX_LED_OFF();
|
||||
|
||||
/* jump to beginning of application space */
|
||||
__asm__ volatile("jmp 0x0000");
|
||||
}
|
||||
|
||||
/* Breathing animation on L LED indicates bootloader is running */
|
||||
uint16_t LLEDPulse;
|
||||
void LEDPulse(void)
|
||||
{
|
||||
LLEDPulse++;
|
||||
uint8_t p = LLEDPulse >> 8;
|
||||
if (p > 127)
|
||||
p = 254-p;
|
||||
p += p;
|
||||
if (((uint8_t)LLEDPulse) > p)
|
||||
L_LED_OFF();
|
||||
else
|
||||
L_LED_ON();
|
||||
}
|
||||
|
||||
/** Main program entry point. This routine configures the hardware required by the bootloader, then continuously
|
||||
* runs the bootloader processing routine until it times out or is instructed to exit.
|
||||
*/
|
||||
int main(void)
|
||||
{
|
||||
/* Save the value of the boot key memory before it is overwritten */
|
||||
uint16_t bootKeyPtrVal = *bootKeyPtr;
|
||||
*bootKeyPtr = 0;
|
||||
|
||||
/* Check the reason for the reset so we can act accordingly */
|
||||
uint8_t mcusr_state = MCUSR; // store the initial state of the Status register
|
||||
MCUSR = 0; // clear all reset flags
|
||||
|
||||
/* Watchdog may be configured with a 15 ms period so must disable it before going any further */
|
||||
wdt_disable();
|
||||
|
||||
if (mcusr_state & (1<<EXTRF)) {
|
||||
// External reset - we should continue to self-programming mode.
|
||||
} else if (mcusr_state == (1<<PORF) && pgm_read_word(0) != 0xFFFF) {
|
||||
// After a power-on reset skip the bootloader and jump straight to sketch
|
||||
// if one exists.
|
||||
StartSketch();
|
||||
} else if ((mcusr_state == (1<<WDRF)) && (bootKeyPtrVal != bootKey) && (pgm_read_word(0) != 0xFFFF)) {
|
||||
// If it looks like an "accidental" watchdog reset then start the sketch.
|
||||
StartSketch();
|
||||
}
|
||||
|
||||
/* Setup hardware required for the bootloader */
|
||||
SetupHardware();
|
||||
|
||||
/* Enable global interrupts so that the USB stack can function */
|
||||
sei();
|
||||
|
||||
Timeout = 0;
|
||||
|
||||
while (RunBootloader)
|
||||
{
|
||||
CDC_Task();
|
||||
USB_USBTask();
|
||||
/* Time out and start the sketch if one is present */
|
||||
if (Timeout > TIMEOUT_PERIOD)
|
||||
RunBootloader = false;
|
||||
|
||||
LEDPulse();
|
||||
}
|
||||
|
||||
/* Disconnect from the host - USB interface will be reset later along with the AVR */
|
||||
USB_Detach();
|
||||
|
||||
/* Jump to beginning of application space to run the sketch - do not reset */
|
||||
StartSketch();
|
||||
}
|
||||
|
||||
/** Configures all hardware required for the bootloader. */
|
||||
void SetupHardware(void)
|
||||
{
|
||||
/* Disable watchdog if enabled by bootloader/fuses */
|
||||
MCUSR &= ~(1 << WDRF);
|
||||
wdt_disable();
|
||||
|
||||
/* Disable clock division */
|
||||
clock_prescale_set(clock_div_1);
|
||||
|
||||
/* Relocate the interrupt vector table to the bootloader section */
|
||||
MCUCR = (1 << IVCE);
|
||||
MCUCR = (1 << IVSEL);
|
||||
|
||||
LED_SETUP();
|
||||
CPU_PRESCALE(0);
|
||||
L_LED_OFF();
|
||||
TX_LED_OFF();
|
||||
RX_LED_OFF();
|
||||
|
||||
/* Initialize TIMER1 to handle bootloader timeout and LED tasks.
|
||||
* With 16 MHz clock and 1/64 prescaler, timer 1 is clocked at 250 kHz
|
||||
* Our chosen compare match generates an interrupt every 1 ms.
|
||||
* This interrupt is disabled selectively when doing memory reading, erasing,
|
||||
* or writing since SPM has tight timing requirements.
|
||||
*/
|
||||
OCR1AH = 0;
|
||||
OCR1AL = 250;
|
||||
TIMSK1 = (1 << OCIE1A); // enable timer 1 output compare A match interrupt
|
||||
TCCR1B = ((1 << CS11) | (1 << CS10)); // 1/64 prescaler on timer 1 input
|
||||
|
||||
/* Initialize USB Subsystem */
|
||||
USB_Init();
|
||||
}
|
||||
|
||||
//uint16_t ctr = 0;
|
||||
ISR(TIMER1_COMPA_vect, ISR_BLOCK)
|
||||
{
|
||||
/* Reset counter */
|
||||
TCNT1H = 0;
|
||||
TCNT1L = 0;
|
||||
|
||||
/* Check whether the TX or RX LED one-shot period has elapsed. if so, turn off the LED */
|
||||
if (TxLEDPulse && !(--TxLEDPulse))
|
||||
TX_LED_OFF();
|
||||
if (RxLEDPulse && !(--RxLEDPulse))
|
||||
RX_LED_OFF();
|
||||
|
||||
if (pgm_read_word(0) != 0xFFFF)
|
||||
Timeout++;
|
||||
}
|
||||
|
||||
/** Event handler for the USB_ConfigurationChanged event. This configures the device's endpoints ready
|
||||
* to relay data to and from the attached USB host.
|
||||
*/
|
||||
void EVENT_USB_Device_ConfigurationChanged(void)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/** Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
|
||||
* the device from the USB host before passing along unhandled control requests to the library for processing
|
||||
* internally.
|
||||
*/
|
||||
void EVENT_USB_Device_ControlRequest(void)
|
||||
{
|
||||
/* Ignore any requests that aren't directed to the CDC interface */
|
||||
if ((USB_ControlRequest.bmRequestType & (CONTROL_REQTYPE_TYPE | CONTROL_REQTYPE_RECIPIENT)) !=
|
||||
(REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* Process CDC specific control requests */
|
||||
switch (USB_ControlRequest.bRequest)
|
||||
{
|
||||
case CDC_REQ_GetLineEncoding:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
/* Write the line coding data to the control endpoint */
|
||||
Endpoint_Write_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
|
||||
Endpoint_ClearOUT();
|
||||
}
|
||||
|
||||
break;
|
||||
case CDC_REQ_SetLineEncoding:
|
||||
if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
|
||||
{
|
||||
Endpoint_ClearSETUP();
|
||||
|
||||
/* Read the line coding data in from the host into the global struct */
|
||||
Endpoint_Read_Control_Stream_LE(&LineEncoding, sizeof(CDC_LineEncoding_t));
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(NO_BLOCK_SUPPORT)
|
||||
/** Reads or writes a block of EEPROM or FLASH memory to or from the appropriate CDC data endpoint, depending
|
||||
* on the AVR910 protocol command issued.
|
||||
*
|
||||
* \param[in] Command Single character AVR910 protocol command indicating what memory operation to perform
|
||||
*/
|
||||
static void ReadWriteMemoryBlock(const uint8_t Command)
|
||||
{
|
||||
uint16_t BlockSize;
|
||||
char MemoryType;
|
||||
|
||||
bool HighByte = false;
|
||||
uint8_t LowByte = 0;
|
||||
|
||||
BlockSize = (FetchNextCommandByte() << 8);
|
||||
BlockSize |= FetchNextCommandByte();
|
||||
|
||||
MemoryType = FetchNextCommandByte();
|
||||
|
||||
if ((MemoryType != 'E') && (MemoryType != 'F'))
|
||||
{
|
||||
/* Send error byte back to the host */
|
||||
WriteNextResponseByte('?');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Disable timer 1 interrupt - can't afford to process nonessential interrupts
|
||||
* while doing SPM tasks */
|
||||
TIMSK1 = 0;
|
||||
|
||||
/* Check if command is to read memory */
|
||||
if (Command == 'g')
|
||||
{
|
||||
/* Re-enable RWW section */
|
||||
boot_rww_enable();
|
||||
|
||||
while (BlockSize--)
|
||||
{
|
||||
if (MemoryType == 'F')
|
||||
{
|
||||
/* Read the next FLASH byte from the current FLASH page */
|
||||
#if (FLASHEND > 0xFFFF)
|
||||
WriteNextResponseByte(pgm_read_byte_far(CurrAddress | HighByte));
|
||||
#else
|
||||
WriteNextResponseByte(pgm_read_byte(CurrAddress | HighByte));
|
||||
#endif
|
||||
|
||||
/* If both bytes in current word have been read, increment the address counter */
|
||||
if (HighByte)
|
||||
CurrAddress += 2;
|
||||
|
||||
HighByte = !HighByte;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read the next EEPROM byte into the endpoint */
|
||||
WriteNextResponseByte(eeprom_read_byte((uint8_t*)(intptr_t)(CurrAddress >> 1)));
|
||||
|
||||
/* Increment the address counter after use */
|
||||
CurrAddress += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t PageStartAddress = CurrAddress;
|
||||
|
||||
if (MemoryType == 'F')
|
||||
{
|
||||
boot_page_erase(PageStartAddress);
|
||||
boot_spm_busy_wait();
|
||||
}
|
||||
|
||||
while (BlockSize--)
|
||||
{
|
||||
if (MemoryType == 'F')
|
||||
{
|
||||
/* If both bytes in current word have been written, increment the address counter */
|
||||
if (HighByte)
|
||||
{
|
||||
/* Write the next FLASH word to the current FLASH page */
|
||||
boot_page_fill(CurrAddress, ((FetchNextCommandByte() << 8) | LowByte));
|
||||
|
||||
/* Increment the address counter after use */
|
||||
CurrAddress += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
LowByte = FetchNextCommandByte();
|
||||
}
|
||||
|
||||
HighByte = !HighByte;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write the next EEPROM byte from the endpoint */
|
||||
eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
|
||||
|
||||
/* Increment the address counter after use */
|
||||
CurrAddress += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* If in FLASH programming mode, commit the page after writing */
|
||||
if (MemoryType == 'F')
|
||||
{
|
||||
/* Commit the flash page to memory */
|
||||
boot_page_write(PageStartAddress);
|
||||
|
||||
/* Wait until write operation has completed */
|
||||
boot_spm_busy_wait();
|
||||
}
|
||||
|
||||
/* Send response byte back to the host */
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
|
||||
/* Re-enable timer 1 interrupt disabled earlier in this routine */
|
||||
TIMSK1 = (1 << OCIE1A);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Retrieves the next byte from the host in the CDC data OUT endpoint, and clears the endpoint bank if needed
|
||||
* to allow reception of the next data packet from the host.
|
||||
*
|
||||
* \return Next received byte from the host in the CDC data OUT endpoint
|
||||
*/
|
||||
static uint8_t FetchNextCommandByte(void)
|
||||
{
|
||||
/* Select the OUT endpoint so that the next data byte can be read */
|
||||
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
|
||||
|
||||
/* If OUT endpoint empty, clear it and wait for the next packet from the host */
|
||||
while (!(Endpoint_IsReadWriteAllowed()))
|
||||
{
|
||||
Endpoint_ClearOUT();
|
||||
|
||||
while (!(Endpoint_IsOUTReceived()))
|
||||
{
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fetch the next byte from the OUT endpoint */
|
||||
return Endpoint_Read_8();
|
||||
}
|
||||
|
||||
/** Writes the next response byte to the CDC data IN endpoint, and sends the endpoint back if needed to free up the
|
||||
* bank when full ready for the next byte in the packet to the host.
|
||||
*
|
||||
* \param[in] Response Next response byte to send to the host
|
||||
*/
|
||||
static void WriteNextResponseByte(const uint8_t Response)
|
||||
{
|
||||
/* Select the IN endpoint so that the next data byte can be written */
|
||||
Endpoint_SelectEndpoint(CDC_TX_EPNUM);
|
||||
|
||||
/* If IN endpoint full, clear it and wait until ready for the next packet to the host */
|
||||
if (!(Endpoint_IsReadWriteAllowed()))
|
||||
{
|
||||
Endpoint_ClearIN();
|
||||
|
||||
while (!(Endpoint_IsINReady()))
|
||||
{
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the next byte to the IN endpoint */
|
||||
Endpoint_Write_8(Response);
|
||||
|
||||
TX_LED_ON();
|
||||
TxLEDPulse = TX_RX_LED_PULSE_PERIOD;
|
||||
}
|
||||
|
||||
#define STK_OK 0x10
|
||||
#define STK_INSYNC 0x14 // ' '
|
||||
#define CRC_EOP 0x20 // 'SPACE'
|
||||
#define STK_GET_SYNC 0x30 // '0'
|
||||
|
||||
#define STK_GET_PARAMETER 0x41 // 'A'
|
||||
#define STK_SET_DEVICE 0x42 // 'B'
|
||||
#define STK_SET_DEVICE_EXT 0x45 // 'E'
|
||||
#define STK_LOAD_ADDRESS 0x55 // 'U'
|
||||
#define STK_UNIVERSAL 0x56 // 'V'
|
||||
#define STK_PROG_PAGE 0x64 // 'd'
|
||||
#define STK_READ_PAGE 0x74 // 't'
|
||||
#define STK_READ_SIGN 0x75 // 'u'
|
||||
|
||||
/** Task to read in AVR910 commands from the CDC data OUT endpoint, process them, perform the required actions
|
||||
* and send the appropriate response back to the host.
|
||||
*/
|
||||
void CDC_Task(void)
|
||||
{
|
||||
/* Select the OUT endpoint */
|
||||
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
|
||||
|
||||
/* Check if endpoint has a command in it sent from the host */
|
||||
if (!(Endpoint_IsOUTReceived()))
|
||||
return;
|
||||
|
||||
RX_LED_ON();
|
||||
RxLEDPulse = TX_RX_LED_PULSE_PERIOD;
|
||||
|
||||
/* Read in the bootloader command (first byte sent from host) */
|
||||
uint8_t Command = FetchNextCommandByte();
|
||||
|
||||
if (Command == 'E')
|
||||
{
|
||||
/* We nearly run out the bootloader timeout clock,
|
||||
* leaving just a few hundred milliseconds so the
|
||||
* bootloder has time to respond and service any
|
||||
* subsequent requests */
|
||||
Timeout = TIMEOUT_PERIOD - 500;
|
||||
|
||||
/* Re-enable RWW section - must be done here in case
|
||||
* user has disabled verification on upload. */
|
||||
boot_rww_enable_safe();
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if (Command == 'T')
|
||||
{
|
||||
FetchNextCommandByte();
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if ((Command == 'L') || (Command == 'P'))
|
||||
{
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if (Command == 't')
|
||||
{
|
||||
// Return ATMEGA128 part code - this is only to allow AVRProg to use the bootloader
|
||||
WriteNextResponseByte(0x44);
|
||||
WriteNextResponseByte(0x00);
|
||||
}
|
||||
else if (Command == 'a')
|
||||
{
|
||||
// Indicate auto-address increment is supported
|
||||
WriteNextResponseByte('Y');
|
||||
}
|
||||
else if (Command == 'A')
|
||||
{
|
||||
// Set the current address to that given by the host
|
||||
CurrAddress = (FetchNextCommandByte() << 9);
|
||||
CurrAddress |= (FetchNextCommandByte() << 1);
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if (Command == 'p')
|
||||
{
|
||||
// Indicate serial programmer back to the host
|
||||
WriteNextResponseByte('S');
|
||||
}
|
||||
else if (Command == 'S')
|
||||
{
|
||||
// Write the 7-byte software identifier to the endpoint
|
||||
for (uint8_t CurrByte = 0; CurrByte < 7; CurrByte++)
|
||||
WriteNextResponseByte(SOFTWARE_IDENTIFIER[CurrByte]);
|
||||
}
|
||||
else if (Command == 'V')
|
||||
{
|
||||
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MAJOR);
|
||||
WriteNextResponseByte('0' + BOOTLOADER_VERSION_MINOR);
|
||||
}
|
||||
else if (Command == 's')
|
||||
{
|
||||
WriteNextResponseByte(AVR_SIGNATURE_3);
|
||||
WriteNextResponseByte(AVR_SIGNATURE_2);
|
||||
WriteNextResponseByte(AVR_SIGNATURE_1);
|
||||
}
|
||||
else if (Command == 'e')
|
||||
{
|
||||
// Clear the application section of flash
|
||||
for (uint32_t CurrFlashAddress = 0; CurrFlashAddress < BOOT_START_ADDR; CurrFlashAddress += SPM_PAGESIZE)
|
||||
{
|
||||
boot_page_erase(CurrFlashAddress);
|
||||
boot_spm_busy_wait();
|
||||
boot_page_write(CurrFlashAddress);
|
||||
boot_spm_busy_wait();
|
||||
}
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
#if !defined(NO_LOCK_BYTE_WRITE_SUPPORT)
|
||||
else if (Command == 'l')
|
||||
{
|
||||
// Set the lock bits to those given by the host
|
||||
boot_lock_bits_set(FetchNextCommandByte());
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
#endif
|
||||
else if (Command == 'r')
|
||||
{
|
||||
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOCK_BITS));
|
||||
}
|
||||
else if (Command == 'F')
|
||||
{
|
||||
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_LOW_FUSE_BITS));
|
||||
}
|
||||
else if (Command == 'N')
|
||||
{
|
||||
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_HIGH_FUSE_BITS));
|
||||
}
|
||||
else if (Command == 'Q')
|
||||
{
|
||||
WriteNextResponseByte(boot_lock_fuse_bits_get(GET_EXTENDED_FUSE_BITS));
|
||||
}
|
||||
#if !defined(NO_BLOCK_SUPPORT)
|
||||
else if (Command == 'b')
|
||||
{
|
||||
WriteNextResponseByte('Y');
|
||||
|
||||
// Send block size to the host
|
||||
WriteNextResponseByte(SPM_PAGESIZE >> 8);
|
||||
WriteNextResponseByte(SPM_PAGESIZE & 0xFF);
|
||||
}
|
||||
else if ((Command == 'B') || (Command == 'g'))
|
||||
{
|
||||
// Keep resetting the timeout counter if we're receiving self-programming instructions
|
||||
Timeout = 0;
|
||||
// Delegate the block write/read to a separate function for clarity
|
||||
ReadWriteMemoryBlock(Command);
|
||||
}
|
||||
#endif
|
||||
#if !defined(NO_FLASH_BYTE_SUPPORT)
|
||||
else if (Command == 'C')
|
||||
{
|
||||
// Write the high byte to the current flash page
|
||||
boot_page_fill(CurrAddress, FetchNextCommandByte());
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if (Command == 'c')
|
||||
{
|
||||
// Write the low byte to the current flash page
|
||||
boot_page_fill(CurrAddress | 0x01, FetchNextCommandByte());
|
||||
|
||||
// Increment the address
|
||||
CurrAddress += 2;
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if (Command == 'm')
|
||||
{
|
||||
// Commit the flash page to memory
|
||||
boot_page_write(CurrAddress);
|
||||
|
||||
// Wait until write operation has completed
|
||||
boot_spm_busy_wait();
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if (Command == 'R')
|
||||
{
|
||||
#if (FLASHEND > 0xFFFF)
|
||||
uint16_t ProgramWord = pgm_read_word_far(CurrAddress);
|
||||
#else
|
||||
uint16_t ProgramWord = pgm_read_word(CurrAddress);
|
||||
#endif
|
||||
|
||||
WriteNextResponseByte(ProgramWord >> 8);
|
||||
WriteNextResponseByte(ProgramWord & 0xFF);
|
||||
}
|
||||
#endif
|
||||
#if !defined(NO_EEPROM_BYTE_SUPPORT)
|
||||
else if (Command == 'D')
|
||||
{
|
||||
// Read the byte from the endpoint and write it to the EEPROM
|
||||
eeprom_write_byte((uint8_t*)((intptr_t)(CurrAddress >> 1)), FetchNextCommandByte());
|
||||
|
||||
// Increment the address after use
|
||||
CurrAddress += 2;
|
||||
|
||||
// Send confirmation byte back to the host
|
||||
WriteNextResponseByte('\r');
|
||||
}
|
||||
else if (Command == 'd')
|
||||
{
|
||||
// Read the EEPROM byte and write it to the endpoint
|
||||
WriteNextResponseByte(eeprom_read_byte((uint8_t*)((intptr_t)(CurrAddress >> 1))));
|
||||
|
||||
// Increment the address after use
|
||||
CurrAddress += 2;
|
||||
}
|
||||
#endif
|
||||
else if (Command != 27)
|
||||
{
|
||||
// Unknown (non-sync) command, return fail code
|
||||
WriteNextResponseByte('?');
|
||||
}
|
||||
|
||||
|
||||
/* Select the IN endpoint */
|
||||
Endpoint_SelectEndpoint(CDC_TX_EPNUM);
|
||||
|
||||
/* Remember if the endpoint is completely full before clearing it */
|
||||
bool IsEndpointFull = !(Endpoint_IsReadWriteAllowed());
|
||||
|
||||
/* Send the endpoint data to the host */
|
||||
Endpoint_ClearIN();
|
||||
|
||||
/* If a full endpoint's worth of data was sent, we need to send an empty packet afterwards to signal end of transfer */
|
||||
if (IsEndpointFull)
|
||||
{
|
||||
while (!(Endpoint_IsINReady()))
|
||||
{
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return;
|
||||
}
|
||||
|
||||
Endpoint_ClearIN();
|
||||
}
|
||||
|
||||
/* Wait until the data has been sent to the host */
|
||||
while (!(Endpoint_IsINReady()))
|
||||
{
|
||||
if (USB_DeviceState == DEVICE_STATE_Unattached)
|
||||
return;
|
||||
}
|
||||
|
||||
/* Select the OUT endpoint */
|
||||
Endpoint_SelectEndpoint(CDC_RX_EPNUM);
|
||||
|
||||
/* Acknowledge the command from the host */
|
||||
Endpoint_ClearOUT();
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2011.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, 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 BootloaderCDC.c.
|
||||
*/
|
||||
|
||||
#ifndef _CDC_H_
|
||||
#define _CDC_H_
|
||||
|
||||
/* Includes: */
|
||||
#include <avr/io.h>
|
||||
#include <avr/wdt.h>
|
||||
#include <avr/boot.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/power.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "Descriptors.h"
|
||||
|
||||
#include <LUFA/Drivers/USB/USB.h>
|
||||
/* Macros: */
|
||||
/** Version major of the CDC bootloader. */
|
||||
#define BOOTLOADER_VERSION_MAJOR 0x01
|
||||
|
||||
/** Version minor of the CDC bootloader. */
|
||||
#define BOOTLOADER_VERSION_MINOR 0x00
|
||||
|
||||
/** Hardware version major of the CDC bootloader. */
|
||||
#define BOOTLOADER_HWVERSION_MAJOR 0x01
|
||||
|
||||
/** Hardware version minor of the CDC bootloader. */
|
||||
#define BOOTLOADER_HWVERSION_MINOR 0x00
|
||||
|
||||
/** Eight character bootloader firmware identifier reported to the host when requested */
|
||||
#define SOFTWARE_IDENTIFIER "CATERINA"
|
||||
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define LED_SETUP() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5);
|
||||
#define L_LED_OFF() PORTC &= ~(1<<7)
|
||||
#define L_LED_ON() PORTC |= (1<<7)
|
||||
#define L_LED_TOGGLE() PORTC ^= (1<<7)
|
||||
#define TX_LED_OFF() PORTD |= (1<<5)
|
||||
#define TX_LED_ON() PORTD &= ~(1<<5)
|
||||
#define RX_LED_OFF() PORTB |= (1<<0)
|
||||
#define RX_LED_ON() PORTB &= ~(1<<0)
|
||||
|
||||
/* Type Defines: */
|
||||
/** Type define for a non-returning pointer to the start of the loaded application in flash memory. */
|
||||
typedef void (*AppPtr_t)(void) ATTR_NO_RETURN;
|
||||
|
||||
/* Function Prototypes: */
|
||||
void StartSketch(void);
|
||||
void LEDPulse(void);
|
||||
|
||||
void CDC_Task(void);
|
||||
void SetupHardware(void);
|
||||
|
||||
void EVENT_USB_Device_ConfigurationChanged(void);
|
||||
|
||||
#if defined(INCLUDE_FROM_CATERINA_C) || defined(__DOXYGEN__)
|
||||
#if !defined(NO_BLOCK_SUPPORT)
|
||||
static void ReadWriteMemoryBlock(const uint8_t Command);
|
||||
#endif
|
||||
static uint8_t FetchNextCommandByte(void);
|
||||
static void WriteNextResponseByte(const uint8_t Response);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,262 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2011.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, 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 SRAM 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.
|
||||
*/
|
||||
const USB_Descriptor_Device_t DeviceDescriptor =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Device_t), .Type = DTYPE_Device},
|
||||
|
||||
.USBSpecification = VERSION_BCD(01.10),
|
||||
.Class = CDC_CSCP_CDCClass,
|
||||
.SubClass = CDC_CSCP_NoSpecificSubclass,
|
||||
.Protocol = CDC_CSCP_NoSpecificProtocol,
|
||||
|
||||
.Endpoint0Size = FIXED_CONTROL_ENDPOINT_SIZE,
|
||||
|
||||
.VendorID = DEVICE_VID,
|
||||
.ProductID = DEVICE_PID,
|
||||
.ReleaseNumber = VERSION_BCD(00.01),
|
||||
|
||||
.ManufacturerStrIndex = 0x02,
|
||||
.ProductStrIndex = 0x01,
|
||||
.SerialNumStrIndex = NO_DESCRIPTOR,
|
||||
|
||||
.NumberOfConfigurations = FIXED_NUM_CONFIGURATIONS
|
||||
};
|
||||
|
||||
/** Configuration descriptor structure. This descriptor, located in SRAM 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.
|
||||
*/
|
||||
const USB_Descriptor_Configuration_t 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,
|
||||
|
||||
.MaxPowerConsumption = USB_CONFIG_POWER_MA(100)
|
||||
},
|
||||
|
||||
.CDC_CCI_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = 0,
|
||||
.AlternateSetting = 0,
|
||||
|
||||
.TotalEndpoints = 1,
|
||||
|
||||
.Class = CDC_CSCP_CDCClass,
|
||||
.SubClass = CDC_CSCP_ACMSubclass,
|
||||
.Protocol = CDC_CSCP_ATCommandProtocol,
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.CDC_Functional_Header =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalHeader_t), .Type = DTYPE_CSInterface},
|
||||
.Subtype = 0x00,
|
||||
|
||||
.CDCSpecification = VERSION_BCD(01.10),
|
||||
},
|
||||
|
||||
.CDC_Functional_ACM =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalACM_t), .Type = DTYPE_CSInterface},
|
||||
.Subtype = 0x02,
|
||||
|
||||
.Capabilities = 0x04,
|
||||
},
|
||||
|
||||
.CDC_Functional_Union =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_CDC_Descriptor_FunctionalUnion_t), .Type = DTYPE_CSInterface},
|
||||
.Subtype = 0x06,
|
||||
|
||||
.MasterInterfaceNumber = 0,
|
||||
.SlaveInterfaceNumber = 1,
|
||||
},
|
||||
|
||||
.CDC_NotificationEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | CDC_NOTIFICATION_EPNUM),
|
||||
.Attributes = (EP_TYPE_INTERRUPT | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = CDC_NOTIFICATION_EPSIZE,
|
||||
.PollingIntervalMS = 0xFF
|
||||
},
|
||||
|
||||
.CDC_DCI_Interface =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Interface_t), .Type = DTYPE_Interface},
|
||||
|
||||
.InterfaceNumber = 1,
|
||||
.AlternateSetting = 0,
|
||||
|
||||
.TotalEndpoints = 2,
|
||||
|
||||
.Class = CDC_CSCP_CDCDataClass,
|
||||
.SubClass = CDC_CSCP_NoDataSubclass,
|
||||
.Protocol = CDC_CSCP_NoDataProtocol,
|
||||
|
||||
.InterfaceStrIndex = NO_DESCRIPTOR
|
||||
},
|
||||
|
||||
.CDC_DataOutEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_OUT | CDC_RX_EPNUM),
|
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = CDC_TXRX_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
},
|
||||
|
||||
.CDC_DataInEndpoint =
|
||||
{
|
||||
.Header = {.Size = sizeof(USB_Descriptor_Endpoint_t), .Type = DTYPE_Endpoint},
|
||||
|
||||
.EndpointAddress = (ENDPOINT_DIR_IN | CDC_TX_EPNUM),
|
||||
.Attributes = (EP_TYPE_BULK | ENDPOINT_ATTR_NO_SYNC | ENDPOINT_USAGE_DATA),
|
||||
.EndpointSize = CDC_TXRX_EPSIZE,
|
||||
.PollingIntervalMS = 0x01
|
||||
}
|
||||
};
|
||||
|
||||
/** Language descriptor structure. This descriptor, located in SRAM 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.
|
||||
*/
|
||||
const USB_Descriptor_String_t LanguageString =
|
||||
{
|
||||
.Header = {.Size = USB_STRING_LEN(1), .Type = DTYPE_String},
|
||||
|
||||
.UnicodeString = {LANGUAGE_ID_ENG}
|
||||
};
|
||||
|
||||
/** 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.
|
||||
*/
|
||||
const USB_Descriptor_String_t ProductString =
|
||||
{
|
||||
.Header = {.Size = USB_STRING_LEN(16), .Type = DTYPE_String},
|
||||
|
||||
#if DEVICE_PID == 0x0036
|
||||
.UnicodeString = L"Arduino Leonardo"
|
||||
#else
|
||||
.UnicodeString = L"USB IO board "
|
||||
#endif
|
||||
};
|
||||
|
||||
const USB_Descriptor_String_t ManufNameString =
|
||||
{
|
||||
.Header = {.Size = USB_STRING_LEN(11), .Type = DTYPE_String},
|
||||
|
||||
#if DEVICE_VID == 0x2341
|
||||
.UnicodeString = L"Arduino LLC"
|
||||
#else
|
||||
.UnicodeString = L"Unknown "
|
||||
#endif
|
||||
};
|
||||
|
||||
/** This function is called by the library when in device mode, and must be overridden (see LUFA library "USB Descriptors"
|
||||
* 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 receives 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 CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||
const uint8_t wIndex,
|
||||
const void** const DescriptorAddress)
|
||||
{
|
||||
const uint8_t DescriptorType = (wValue >> 8);
|
||||
const uint8_t DescriptorNumber = (wValue & 0xFF);
|
||||
|
||||
const void* Address = NULL;
|
||||
uint16_t Size = NO_DESCRIPTOR;
|
||||
|
||||
switch (DescriptorType)
|
||||
{
|
||||
case DTYPE_Device:
|
||||
Address = &DeviceDescriptor;
|
||||
Size = sizeof(USB_Descriptor_Device_t);
|
||||
break;
|
||||
case DTYPE_Configuration:
|
||||
Address = &ConfigurationDescriptor;
|
||||
Size = sizeof(USB_Descriptor_Configuration_t);
|
||||
break;
|
||||
case DTYPE_String:
|
||||
if (!(DescriptorNumber))
|
||||
{
|
||||
Address = &LanguageString;
|
||||
Size = LanguageString.Header.Size;
|
||||
}
|
||||
else if (DescriptorNumber == DeviceDescriptor.ProductStrIndex)
|
||||
{
|
||||
Address = &ProductString;
|
||||
Size = ProductString.Header.Size;
|
||||
} else if (DescriptorNumber == DeviceDescriptor.ManufacturerStrIndex)
|
||||
{
|
||||
Address = &ManufNameString;
|
||||
Size = ManufNameString.Header.Size;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
*DescriptorAddress = Address;
|
||||
return Size;
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
LUFA Library
|
||||
Copyright (C) Dean Camera, 2011.
|
||||
|
||||
dean [at] fourwalledcubicle [dot] com
|
||||
www.lufa-lib.org
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com)
|
||||
|
||||
Permission to use, copy, modify, distribute, and sell this
|
||||
software and its documentation for any purpose is hereby granted
|
||||
without fee, 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>
|
||||
|
||||
/* Macros: */
|
||||
#if defined(__AVR_AT90USB1287__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x97
|
||||
#define AVR_SIGNATURE_3 0x82
|
||||
#elif defined(__AVR_AT90USB647__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x96
|
||||
#define AVR_SIGNATURE_3 0x82
|
||||
#elif defined(__AVR_AT90USB1286__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x97
|
||||
#define AVR_SIGNATURE_3 0x82
|
||||
#elif defined(__AVR_AT90USB646__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x96
|
||||
#define AVR_SIGNATURE_3 0x82
|
||||
#elif defined(__AVR_ATmega32U6__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x95
|
||||
#define AVR_SIGNATURE_3 0x88
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x95
|
||||
#define AVR_SIGNATURE_3 0x87
|
||||
#elif defined(__AVR_ATmega16U4__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x94
|
||||
#define AVR_SIGNATURE_3 0x88
|
||||
#elif defined(__AVR_ATmega32U2__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x95
|
||||
#define AVR_SIGNATURE_3 0x8A
|
||||
#elif defined(__AVR_ATmega16U2__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x94
|
||||
#define AVR_SIGNATURE_3 0x89
|
||||
#elif defined(__AVR_AT90USB162__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x94
|
||||
#define AVR_SIGNATURE_3 0x82
|
||||
#elif defined(__AVR_ATmega8U2__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x93
|
||||
#define AVR_SIGNATURE_3 0x89
|
||||
#elif defined(__AVR_AT90USB82__)
|
||||
#define AVR_SIGNATURE_1 0x1E
|
||||
#define AVR_SIGNATURE_2 0x94
|
||||
#define AVR_SIGNATURE_3 0x82
|
||||
#else
|
||||
#error The selected AVR part is not currently supported by this bootloader.
|
||||
#endif
|
||||
|
||||
/** Endpoint number for the CDC control interface event notification endpoint. */
|
||||
#define CDC_NOTIFICATION_EPNUM 2
|
||||
|
||||
/** Endpoint number for the CDC data interface TX (data IN) endpoint. */
|
||||
#define CDC_TX_EPNUM 3
|
||||
|
||||
/** Endpoint number for the CDC data interface RX (data OUT) endpoint. */
|
||||
#define CDC_RX_EPNUM 4
|
||||
|
||||
/** Size of the CDC data interface TX and RX data endpoint banks, in bytes. */
|
||||
#define CDC_TXRX_EPSIZE 16
|
||||
|
||||
/** Size of the CDC control interface notification endpoint bank, in bytes. */
|
||||
#define CDC_NOTIFICATION_EPSIZE 8
|
||||
|
||||
/* 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;
|
||||
|
||||
// CDC Control Interface
|
||||
USB_Descriptor_Interface_t CDC_CCI_Interface;
|
||||
USB_CDC_Descriptor_FunctionalHeader_t CDC_Functional_Header;
|
||||
USB_CDC_Descriptor_FunctionalACM_t CDC_Functional_ACM;
|
||||
USB_CDC_Descriptor_FunctionalUnion_t CDC_Functional_Union;
|
||||
USB_Descriptor_Endpoint_t CDC_NotificationEndpoint;
|
||||
|
||||
// CDC Data Interface
|
||||
USB_Descriptor_Interface_t CDC_DCI_Interface;
|
||||
USB_Descriptor_Endpoint_t CDC_DataOutEndpoint;
|
||||
USB_Descriptor_Endpoint_t CDC_DataInEndpoint;
|
||||
} USB_Descriptor_Configuration_t;
|
||||
|
||||
/* Function Prototypes: */
|
||||
uint16_t CALLBACK_USB_GetDescriptor(const uint16_t wValue,
|
||||
const uint8_t wIndex,
|
||||
const void** const DescriptorAddress)
|
||||
ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,728 @@
|
|||
# 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 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".
|
||||
#----------------------------------------------------------------------------
|
||||
|
||||
# USB vendor ID (VID)
|
||||
# official Arduino LLC VID
|
||||
# VID = 0x2341
|
||||
|
||||
|
||||
# USB product ID (PID)
|
||||
# official Leonardo PID
|
||||
# PID = 0x0036
|
||||
|
||||
|
||||
# MCU name
|
||||
MCU = atmega32u4
|
||||
|
||||
|
||||
# Target architecture (see library "Board Types" documentation).
|
||||
ARCH = AVR8
|
||||
|
||||
|
||||
# Target board (see library "Board Types" documentation, NONE 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 = USER
|
||||
|
||||
|
||||
# Processor frequency.
|
||||
# This will define a symbol, F_CPU, in all source code files equal to the
|
||||
# processor frequency in Hz. 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.
|
||||
#
|
||||
# This will be an integer division of F_USB below, as it is sourced by
|
||||
# F_USB after it has run through any CPU prescalers. Note that this value
|
||||
# does not *change* the processor frequency - it should merely be updated to
|
||||
# reflect the processor speed set externally so that the code can use accurate
|
||||
# software delays.
|
||||
F_CPU = 16000000
|
||||
|
||||
|
||||
# Input clock frequency.
|
||||
# This will define a symbol, F_USB, in all source code files equal to the
|
||||
# input clock frequency (before any prescaling is performed) in Hz. This value may
|
||||
# differ from F_CPU if prescaling is used on the latter, and is required as the
|
||||
# raw input clock is fed directly to the PLL sections of the AVR for high speed
|
||||
# clock generation for the USB and other AVR subsections. Do NOT tack on a 'UL'
|
||||
# at the end, this will be done automatically to create a 32-bit value in your
|
||||
# source code.
|
||||
#
|
||||
# If no clock division is performed on the input clock inside the AVR (via the
|
||||
# CPU clock adjust registers or the clock division fuses), this will be equal to F_CPU.
|
||||
F_USB = $(F_CPU)
|
||||
|
||||
|
||||
# Starting byte address of the bootloader, as a byte address - computed via the formula
|
||||
# BOOT_START = ((FLASH_SIZE_KB - BOOT_SECTION_SIZE_KB) * 1024)
|
||||
#
|
||||
# Note that the bootloader size and start address given in AVRStudio is in words and not
|
||||
# bytes, and so will need to be doubled to obtain the byte address needed by AVR-GCC.
|
||||
FLASH_SIZE_KB = 32
|
||||
BOOT_SECTION_SIZE_KB = 4
|
||||
BOOT_START = 0x$(shell echo "obase=16; ($(FLASH_SIZE_KB) - $(BOOT_SECTION_SIZE_KB)) * 1024" | bc)
|
||||
|
||||
|
||||
# Output format. (can be srec, ihex, binary)
|
||||
FORMAT = ihex
|
||||
|
||||
|
||||
# Target file name (without extension).
|
||||
TARGET = Caterina
|
||||
|
||||
|
||||
# Object files directory
|
||||
# To put object files in current directory, use a dot (.), do NOT make
|
||||
# this an empty or blank macro!
|
||||
OBJDIR = .
|
||||
|
||||
|
||||
# Path to the LUFA library
|
||||
LUFA_PATH = ../../../../../LUFA-111009
|
||||
|
||||
|
||||
# LUFA library compile-time options and predefined tokens
|
||||
LUFA_OPTS = -D USB_DEVICE_ONLY
|
||||
LUFA_OPTS += -D DEVICE_STATE_AS_GPIOR=0
|
||||
LUFA_OPTS += -D ORDERED_EP_CONFIG
|
||||
LUFA_OPTS += -D FIXED_CONTROL_ENDPOINT_SIZE=8
|
||||
LUFA_OPTS += -D FIXED_NUM_CONFIGURATIONS=1
|
||||
LUFA_OPTS += -D USE_RAM_DESCRIPTORS
|
||||
LUFA_OPTS += -D USE_STATIC_OPTIONS="(USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)"
|
||||
LUFA_OPTS += -D NO_INTERNAL_SERIAL
|
||||
LUFA_OPTS += -D NO_DEVICE_SELF_POWER
|
||||
LUFA_OPTS += -D NO_DEVICE_REMOTE_WAKEUP
|
||||
LUFA_OPTS += -D NO_SOF_EVENTS
|
||||
|
||||
#LUFA_OPTS += -D NO_BLOCK_SUPPORT
|
||||
#LUFA_OPTS += -D NO_EEPROM_BYTE_SUPPORT
|
||||
#LUFA_OPTS += -D NO_FLASH_BYTE_SUPPORT
|
||||
LUFA_OPTS += -D NO_LOCK_BYTE_WRITE_SUPPORT
|
||||
|
||||
|
||||
# Create the LUFA source path variables by including the LUFA root makefile
|
||||
include $(LUFA_PATH)/LUFA/makefile
|
||||
|
||||
|
||||
# List C source files here. (C dependencies are automatically generated.)
|
||||
SRC = $(TARGET).c \
|
||||
Descriptors.c \
|
||||
$(LUFA_SRC_USB) \
|
||||
|
||||
|
||||
# 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 = $(LUFA_PATH)/
|
||||
|
||||
|
||||
# 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=c99
|
||||
|
||||
|
||||
# Place -D or -U options here for C sources
|
||||
CDEFS = -DF_CPU=$(F_CPU)UL
|
||||
CDEFS += -DF_USB=$(F_USB)UL
|
||||
CDEFS += -DBOARD=BOARD_$(BOARD) -DARCH=ARCH_$(ARCH)
|
||||
CDEFS += -DBOOT_START_ADDR=$(BOOT_START)UL
|
||||
CDEFS += -DDEVICE_VID=$(VID)UL
|
||||
CDEFS += -DDEVICE_PID=$(PID)UL
|
||||
CDEFS += $(LUFA_OPTS)
|
||||
|
||||
|
||||
# Place -D or -U options here for ASM sources
|
||||
ADEFS = -DF_CPU=$(F_CPU)
|
||||
ADEFS += -DF_USB=$(F_USB)UL
|
||||
ADEFS += -DBOARD=BOARD_$(BOARD)
|
||||
ADEFS += -DBOOT_START_ADDR=$(BOOT_START)UL
|
||||
ADEFS += $(LUFA_OPTS)
|
||||
|
||||
|
||||
# Place -D or -U options here for C++ sources
|
||||
CPPDEFS = -DF_CPU=$(F_CPU)UL
|
||||
CPPDEFS += -DF_USB=$(F_USB)UL
|
||||
CPPDEFS += -DBOARD=BOARD_$(BOARD)
|
||||
CPPDEFS += -DBOOT_START_ADDR=$(BOOT_START)UL
|
||||
CPPDEFS += $(LUFA_OPTS)
|
||||
#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 += -fno-inline-small-functions
|
||||
CFLAGS += -fpack-struct
|
||||
CFLAGS += -fshort-enums
|
||||
CFLAGS += -fno-strict-aliasing
|
||||
CFLAGS += -Wall
|
||||
CFLAGS += -Wstrict-prototypes
|
||||
#CFLAGS += -mshort-calls
|
||||
#CFLAGS += -fno-unit-at-a-time
|
||||
#CFLAGS += -Wundef
|
||||
#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
|
||||
CPPFLAGS += -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,--section-start=.text=$(BOOT_START)
|
||||
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
|
||||
# Type: avrdude -c ?
|
||||
# to get a full listing.
|
||||
#
|
||||
AVRDUDE_PROGRAMMER = avrispmkII
|
||||
|
||||
# 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 = /Applications/avrdude -C /Applications/avrdude.conf -B 1
|
||||
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 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
|
||||
|
||||
|
||||
|
||||
# Display compiler version information.
|
||||
gccversion :
|
||||
@$(CC) --version
|
||||
|
||||
|
||||
# Program the device.
|
||||
program: $(TARGET).hex $(TARGET).eep
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
|
||||
|
||||
|
||||
# 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 -R .fuse -R .lock $< $@
|
||||
|
||||
%.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 -S -z $< > $@
|
||||
|
||||
# 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 end
|
||||
|
||||
clean_list :
|
||||
@echo
|
||||
@echo $(MSG_CLEANING)
|
||||
$(REMOVE) $(TARGET).hex
|
||||
$(REMOVE) $(TARGET).eep
|
||||
$(REMOVE) $(TARGET).cof
|
||||
$(REMOVE) $(TARGET).elf
|
||||
$(REMOVE) $(TARGET).map
|
||||
$(REMOVE) $(TARGET).sym
|
||||
$(REMOVE) $(TARGET).lss
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o)
|
||||
$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst)
|
||||
$(REMOVE) $(SRC:.c=.s)
|
||||
$(REMOVE) $(SRC:.c=.d)
|
||||
$(REMOVE) $(SRC:.c=.i)
|
||||
$(REMOVEDIR) .dep
|
||||
|
||||
doxygen:
|
||||
@echo Generating Project Documentation \($(TARGET)\)...
|
||||
@doxygen Doxygen.conf
|
||||
@echo Documentation Generation Complete.
|
||||
|
||||
clean_doxygen:
|
||||
rm -rf Documentation
|
||||
|
||||
checksource:
|
||||
@for f in $(SRC) $(CPPSRC) $(ASRC); do \
|
||||
if [ -f $$f ]; then \
|
||||
echo "Found Source File: $$f" ; \
|
||||
else \
|
||||
echo "Source File Not Found: $$f" ; \
|
||||
fi; done
|
||||
|
||||
|
||||
# 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 begin finish end sizebefore sizeafter gccversion \
|
||||
build elf hex eep lss sym coff extcoff doxygen clean \
|
||||
clean_list clean_doxygen program debug gdb-config checksource
|
||||
|
|
@ -1,115 +0,0 @@
|
|||
:1078000011241FBECFEFDAE0DEBFCDBFFFC04101C4
|
||||
:1078100042144505560455026403740300001E9586
|
||||
:1078200087020110030000C18081C106C0FF0A0069
|
||||
:107830000CA10185037508150026FF00954009017C
|
||||
:107840008102954009029102C0040309041A033021
|
||||
:1078500000300030003000300030003000300031A7
|
||||
:1078600000370030003100380341007200640075B9
|
||||
:107870000069006E006F0020004C0065006F006E14
|
||||
:10788000006100720064006F00200062006F006FF2
|
||||
:107890000074006C006F00610064006500720018E5
|
||||
:1078A00003410072006400750069006E006F0020E3
|
||||
:1078B000004C004C00430012010002020000404155
|
||||
:1078C0002334000001000203011201000200000045
|
||||
:1078D0004041233400000100020301090264000357
|
||||
:1078E00001008032080B00020202010009040000BE
|
||||
:1078F0000102020000052400100105240101010419
|
||||
:107900002402020524060001070581031000400936
|
||||
:10791000040100020A0000000705020240000007FF
|
||||
:107920000583024000000904020001030000000971
|
||||
:107930002101010001221E000705840340004000D0
|
||||
:1079400020918A0130918B012C5F3F4F30938B0146
|
||||
:1079500020938A01C901892F99278695982F803411
|
||||
:1079600018F08FE7891B982F990F921710F44798FA
|
||||
:107970000895479A08955D9A289A81E08093E000DF
|
||||
:107980001092E200EE27FF27099408950F931F93AA
|
||||
:10799000CF93DF93982FEB01042F10E088E760303E
|
||||
:1079A000780730F411E083E0FB0180935700E895FD
|
||||
:1079B000892F68E071E0402FF8D0112311F107B64C
|
||||
:1079C00000FCFDCF402F4695FE01A8E0B1E020E08D
|
||||
:1079D00031E009C08D919D910C0130935700E895DD
|
||||
:1079E000112432962F5F2417A8F385E0FE018093BF
|
||||
:1079F0005700E89507B600FCFDCF81E18093570062
|
||||
:107A0000E895DF91CF911F910F91089588E10FB60E
|
||||
:107A1000F89480936000109260000FBE5D9A289ADF
|
||||
:107A200047983F9A209A559A90E890936100109257
|
||||
:107A3000610081E885BF95BF9FD084E18093880174
|
||||
:107A400080E180938901E0E0F0E0859194918F5F7F
|
||||
:107A50009F4F19F081E080938F01EE24FF24BB2417
|
||||
:107A6000B39454EFC52E51E0D52E13D2082F8EE0DB
|
||||
:107A700098E7FC012491319602964491201711F069
|
||||
:107A80002223B9F7109291011092900182E068E0F0
|
||||
:107A900071E08BD0013479F4609108016058633053
|
||||
:107AA00028F0683111F064E001C063E0C62FD0E037
|
||||
:107AB000CF5DD7480EC0063571F480910801803340
|
||||
:107AC00011F011E022C080910A01C82FD0E0C25EFF
|
||||
:107AD000D74811E022C0053721F413E0CEE1D8E702
|
||||
:107AE0001CC0053539F4E0900801F0900901EE0C56
|
||||
:107AF000FF1C0AC0043631F482E0B701409109014D
|
||||
:107B000045DF02C0043721F010E0C5E2D8E705C028
|
||||
:107B100010910901E701E10EF11CBBD18097B1F48E
|
||||
:107B200083E068E871E041E050E059D0112329F08A
|
||||
:107B3000412F50E083E8BE0152D083E469E871E050
|
||||
:107B400041E050E04CD0013509F08FCFD092910147
|
||||
:107B5000C0929001B0928F01EE24FF2486CFFC01E9
|
||||
:107B6000289884E680938D0104C08091F100819370
|
||||
:107B700061506623D1F708951092910110929001FF
|
||||
:107B800010928E0110928F0181E08093D70080EADD
|
||||
:107B90008093D80082E189BD09B400FEFDCF80E961
|
||||
:107BA0008093D8001092E0000895FB018093E900D3
|
||||
:107BB00024E69BE611C08091E80085FFFCCF289861
|
||||
:107BC00020938D018091F10081938091E80085FDE3
|
||||
:107BD00002C09093E8004150442369F70895982F1C
|
||||
:107BE000FB01282F207287708093E90064E63AE356
|
||||
:107BF00017C08091E80085FFFCCF97FF02C08491F9
|
||||
:107C000001C080813196211180E05D9860938C01E4
|
||||
:107C10008093F1008091E80085FD02C03093E80078
|
||||
:107C2000415050408FEF4F3F580719F796FF03C060
|
||||
:107C30008AE38093E800089580919301813299F45A
|
||||
:107C40005D9884E680938C0120E030E003C0808161
|
||||
:107C50008093F100F901E050FF4F2F5F3F4F283034
|
||||
:107C60003105A9F714C0803261F48091E80082FFE9
|
||||
:107C7000FCCF80E091E067E072DF8BEF8093E8005B
|
||||
:107C800006C0823221F4809194018093070181E043
|
||||
:107C9000089520919501223289F1213081F480915B
|
||||
:107CA000980190919901089711F420939A0180917D
|
||||
:107CB0009A01882309F04FC0E9ECF8E74EC0223062
|
||||
:107CC00021F484E6EBEDF8E71CC0233009F041C055
|
||||
:107CD00080919401882319F4E9E4F8E73EC08230EA
|
||||
:107CE00019F4E7E6F8E739C0833019F4EDE4F8E772
|
||||
:107CF00034C0813071F5EFE9F8E72FC081E0EBE2A5
|
||||
:107D0000F8E790919801382F981708F4392F90913F
|
||||
:107D10008C0120E04EEF8091E8008570E1F38091C6
|
||||
:107D2000E80082FD12C02F5F84915D988093F1007E
|
||||
:107D3000822F8F7311F44093E800319694E6231755
|
||||
:107D400050F390938C0181E0089590938C0180E032
|
||||
:107D5000089580E00895E7EBF8E78491D2CF109280
|
||||
:107D6000E9008091E80083FF61C082E991E068E06A
|
||||
:107D7000F6DE82EF8093E8008091920187FF05C0D4
|
||||
:107D80008091E80080FFFCCF03C08EEF8093E80075
|
||||
:107D900080919301853051F48091E80080FFFCCF01
|
||||
:107DA0008091940180688093E30039C08930E1F4C8
|
||||
:107DB0008091940180938E01E7E2F8E791E031E051
|
||||
:107DC00026E39093E9003093EB0084918093EC00DC
|
||||
:107DD0002093ED009F5F3196953099F78EE7809361
|
||||
:107DE000EA001092EA001BC0883049F490918E019D
|
||||
:107DF0005D9884E680938C019093F10010C08823F5
|
||||
:107E000039F45D9884E680938C011092F10007C0EC
|
||||
:107E1000863011F43EDF01C00FDF882321F08EEFA2
|
||||
:107E20008093E800089581E28093EB0008958091AB
|
||||
:107E3000E1001092E100282F83FF0CC01092E900AE
|
||||
:107E400081E08093EB001092EC0082E38093ED00E0
|
||||
:107E500010928E0122FF1CC080918C01882331F08A
|
||||
:107E6000815080938C01882309F45D9A80918D0163
|
||||
:107E7000882331F0815080938D01882309F4289A5A
|
||||
:107E800080918F01882321F410929101109290012A
|
||||
:107E900008951F93CF93DF9312E0C0E9D1E05FDF35
|
||||
:107EA000C6DF1093E9008091E80085FF13C0289891
|
||||
:107EB00084E680938D019091F1008091E80085FD2A
|
||||
:107EC00003C08BE68093E800892F90E0DF91CF918B
|
||||
:107ED0001F91089580919001909191010197909345
|
||||
:107EE0009101809390018091900190919101892B53
|
||||
:0E7EF00009F441DDCE010197F1F722DDD0CF7C
|
||||
:087EFE0000E10000000000009B
|
||||
:040000030000780081
|
||||
:00000001FF
|
|
@ -1,105 +0,0 @@
|
|||
###############################################################################
|
||||
# Makefile for DiskLoader
|
||||
###############################################################################
|
||||
|
||||
## General Flags
|
||||
PROJECT = DiskLoader
|
||||
TARGET = DiskLoader.elf
|
||||
CC = avr-gcc
|
||||
|
||||
# BOARD2
|
||||
MCU = atmega32u4
|
||||
AVR_FREQ = 16000000L
|
||||
|
||||
# Specify the Arduino model using the assigned PID. This is used by Descriptors.c
|
||||
# to set PID and product descriptor string
|
||||
# Arduino Leonardo PID
|
||||
ARDUINO_MODEL_PID = 0x0034
|
||||
# Arduino Micro PID
|
||||
#ARDUINO_MODEL_PID = 0x0035
|
||||
|
||||
# Change if your programmer is different
|
||||
AVRDUDE_PROGRAMMER = avrispmkII
|
||||
AVRDUDE_PORT = usb
|
||||
|
||||
# program name should not be changed...
|
||||
PROGRAM = DiskLoader
|
||||
|
||||
AVRDUDE = avrdude
|
||||
AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) -p $(MCU)
|
||||
|
||||
## Options common to compile, link and assembly rules
|
||||
COMMON = -mmcu=$(MCU)
|
||||
|
||||
override CFLAGS = -g -Wall -Os -mmcu=$(MCU) -DF_CPU=$(AVR_FREQ) -DARDUINO_MODEL_PID=$(ARDUINO_MODEL_PID) $(DEFS) -ffunction-sections -gdwarf-2 -fdata-sections -fno-split-wide-types
|
||||
|
||||
## Assembly specific flags
|
||||
ASMFLAGS = $(COMMON)
|
||||
ASMFLAGS += $(CFLAGS)
|
||||
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2
|
||||
|
||||
## Linker flags
|
||||
LDFLAGS = $(COMMON)
|
||||
LDFLAGS += -Wl,-gc-sections,-Map=DiskLoader.map,--section-start=.text=0x7800,--relax
|
||||
LDFLAGS += -nodefaultlibs -nostartfiles
|
||||
|
||||
|
||||
## Intel Hex file production flags
|
||||
HEX_EEPROM_FLAGS = -j .eeprom
|
||||
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
|
||||
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings
|
||||
|
||||
## Objects explicitly added by the user
|
||||
LINKONLYOBJECTS =
|
||||
|
||||
MODULES := .
|
||||
SRC_DIR := $(addprefix src/,$(MODULES))
|
||||
BUILD_DIR := $(addprefix build/,$(MODULES))
|
||||
|
||||
SRC := $(foreach sdir,$(SRC_DIR),$(wildcard $(sdir)/*.cpp))
|
||||
OBJ := $(patsubst src/%.cpp,build/%.o,$(SRC))
|
||||
DEP := $(OBJ:%.o=%.d)
|
||||
INCLUDES := $(addprefix -I,$(SRC_DIR))
|
||||
|
||||
vpath %.cpp $(SRC_DIR)
|
||||
|
||||
.PHONY: all checkdirs clean
|
||||
|
||||
all: checkdirs $(TARGET) DiskLoader.hex DiskLoader.lss size
|
||||
|
||||
-include $(DEP)
|
||||
|
||||
checkdirs: $(BUILD_DIR)
|
||||
|
||||
$(BUILD_DIR):
|
||||
@mkdir -p $@
|
||||
|
||||
clean:
|
||||
@rm -rf build/
|
||||
@rm -f *.hex
|
||||
@rm -f *.elf
|
||||
@rm -f *.lss
|
||||
@rm -f *.map
|
||||
|
||||
define make-goal
|
||||
$1/%.o: %.cpp
|
||||
$(CC) $(INCLUDES) $(CFLAGS) -c $$< -MD -o $$@
|
||||
endef
|
||||
|
||||
$(foreach bdir,$(BUILD_DIR),$(eval $(call make-goal,$(bdir))))
|
||||
|
||||
$(TARGET): $(OBJ)
|
||||
$(CC) $(LDFLAGS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) $^ -o $@
|
||||
|
||||
%.hex: $(TARGET)
|
||||
avr-objcopy -O ihex $(HEX_FLASH_FLAGS) $< $@
|
||||
|
||||
%.lss: $(TARGET)
|
||||
avr-objdump -h -S $< > $@
|
||||
|
||||
size: $(TARGET)
|
||||
@echo
|
||||
# @avr-size -C --mcu=${MCU} ${TARGET}.elf
|
||||
|
||||
program: $(TARGET).hex
|
||||
$(AVRDUDE) $(AVRDUDE_FLAGS) -B 5 -u -U flash:w:$(TARGET).hex
|
|
@ -1,239 +0,0 @@
|
|||
|
||||
|
||||
#include "Platform.h"
|
||||
|
||||
// This bootloader creates a composite Serial device
|
||||
//
|
||||
// The serial interface supports a STK500v1 protocol that is very similar to optiboot
|
||||
//
|
||||
// The bootloader will timeout and start the firmware after a few hundred milliseconds
|
||||
// if a usb connection is not detected.
|
||||
//
|
||||
// The tweakier code is to keep the bootloader below 2k (no interrupt table, for example)
|
||||
|
||||
extern "C"
|
||||
void entrypoint(void) __attribute__ ((naked)) __attribute__ ((section (".vectors")));
|
||||
void entrypoint(void)
|
||||
{
|
||||
asm volatile (
|
||||
"eor r1, r1\n" // Zero register
|
||||
"out 0x3F, r1\n" // SREG
|
||||
"ldi r28, 0xFF\n"
|
||||
"ldi r29, 0x0A\n"
|
||||
"out 0x3E, r29\n" // SPH
|
||||
"out 0x3D, r28\n" // SPL
|
||||
"rjmp main" // Stack is all set up, start the main code
|
||||
::);
|
||||
}
|
||||
|
||||
u8 _flashbuf[128];
|
||||
u8 _inSync;
|
||||
u8 _ok;
|
||||
extern volatile u8 _ejected;
|
||||
extern volatile u16 _timeout;
|
||||
|
||||
void Program(u8 ep, u16 page, u8 count)
|
||||
{
|
||||
u8 write = page < 30*1024; // Don't write over firmware please
|
||||
if (write)
|
||||
boot_page_erase(page);
|
||||
|
||||
Recv(ep,_flashbuf,count); // Read while page is erasing
|
||||
|
||||
if (!write)
|
||||
return;
|
||||
|
||||
boot_spm_busy_wait(); // Wait until the memory is erased.
|
||||
|
||||
count >>= 1;
|
||||
u16* p = (u16*)page;
|
||||
u16* b = (u16*)_flashbuf;
|
||||
for (u8 i = 0; i < count; i++)
|
||||
boot_page_fill(p++, b[i]);
|
||||
|
||||
boot_page_write(page);
|
||||
boot_spm_busy_wait();
|
||||
boot_rww_enable ();
|
||||
}
|
||||
|
||||
|
||||
int USBGetChar();
|
||||
#define getch USBGetChar
|
||||
|
||||
#define HW_VER 0x02
|
||||
#define SW_MAJOR 0x01
|
||||
#define SW_MINOR 0x10
|
||||
|
||||
#define STK_OK 0x10
|
||||
#define STK_INSYNC 0x14 // ' '
|
||||
#define CRC_EOP 0x20 // 'SPACE'
|
||||
#define STK_GET_SYNC 0x30 // '0'
|
||||
|
||||
#define STK_GET_PARAMETER 0x41 // 'A'
|
||||
#define STK_SET_DEVICE 0x42 // 'B'
|
||||
#define STK_SET_DEVICE_EXT 0x45 // 'E'
|
||||
#define STK_LOAD_ADDRESS 0x55 // 'U'
|
||||
#define STK_UNIVERSAL 0x56 // 'V'
|
||||
#define STK_PROG_PAGE 0x64 // 'd'
|
||||
#define STK_READ_PAGE 0x74 // 't'
|
||||
#define STK_READ_SIGN 0x75 // 'u'
|
||||
|
||||
extern const u8 _readSize[] PROGMEM;
|
||||
const u8 _readSize[] =
|
||||
{
|
||||
STK_GET_PARAMETER, 1,
|
||||
STK_SET_DEVICE, 20,
|
||||
STK_SET_DEVICE_EXT, 5,
|
||||
STK_UNIVERSAL, 4,
|
||||
STK_LOAD_ADDRESS, 2,
|
||||
STK_PROG_PAGE, 3,
|
||||
STK_READ_PAGE, 3,
|
||||
0,0
|
||||
};
|
||||
|
||||
extern const u8 _consts[] PROGMEM;
|
||||
const u8 _consts[] =
|
||||
{
|
||||
SIGNATURE_0,
|
||||
SIGNATURE_1,
|
||||
SIGNATURE_2,
|
||||
HW_VER, // Hardware version
|
||||
SW_MAJOR, // Software major version
|
||||
SW_MINOR, // Software minor version
|
||||
0x03, // Unknown but seems to be required by avr studio 3.56
|
||||
0x00, //
|
||||
};
|
||||
|
||||
|
||||
void USBInit(void);
|
||||
int main(void) __attribute__ ((naked));
|
||||
|
||||
// STK500v1 main loop, very similar to optiboot in protocol and implementation
|
||||
int main()
|
||||
{
|
||||
wdt_disable();
|
||||
TXLED0;
|
||||
RXLED0;
|
||||
LED0;
|
||||
BOARD_INIT();
|
||||
USBInit();
|
||||
|
||||
_inSync = STK_INSYNC;
|
||||
_ok = STK_OK;
|
||||
|
||||
if (pgm_read_word(0) != -1)
|
||||
_ejected = 1;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
u8* packet = _flashbuf;
|
||||
u16 address = 0;
|
||||
for (;;)
|
||||
{
|
||||
u8 cmd = getch();
|
||||
|
||||
// Read packet contents
|
||||
u8 len;
|
||||
const u8* rs = _readSize;
|
||||
for(;;)
|
||||
{
|
||||
u8 c = pgm_read_byte(rs++);
|
||||
len = pgm_read_byte(rs++);
|
||||
if (c == cmd || c == 0)
|
||||
break;
|
||||
}
|
||||
_timeout = 0;
|
||||
// Read params
|
||||
Recv(CDC_RX,packet,len);
|
||||
|
||||
// Send a response
|
||||
u8 send = 0;
|
||||
const u8* pgm = _consts+7; // 0
|
||||
if (STK_GET_PARAMETER == cmd)
|
||||
{
|
||||
u8 i = packet[0] - 0x80;
|
||||
if (i > 2)
|
||||
i = (i == 0x18) ? 3 : 4; // 0x80:HW_VER,0x81:SW_MAJOR,0x82:SW_MINOR,0x18:3 or 0
|
||||
pgm = _consts + i + 3;
|
||||
send = 1;
|
||||
}
|
||||
|
||||
else if (STK_UNIVERSAL == cmd)
|
||||
{
|
||||
if (packet[0] == 0x30)
|
||||
pgm = _consts + packet[2]; // read signature
|
||||
send = 1;
|
||||
}
|
||||
|
||||
// Read signature bytes
|
||||
else if (STK_READ_SIGN == cmd)
|
||||
{
|
||||
pgm = _consts;
|
||||
send = 3;
|
||||
}
|
||||
|
||||
else if (STK_LOAD_ADDRESS == cmd)
|
||||
{
|
||||
address = *((u16*)packet); // word addresses
|
||||
address += address;
|
||||
}
|
||||
|
||||
else if (STK_PROG_PAGE == cmd)
|
||||
{
|
||||
Program(CDC_RX,address,packet[1]);
|
||||
}
|
||||
|
||||
else if (STK_READ_PAGE == cmd)
|
||||
{
|
||||
send = packet[1];
|
||||
pgm = (const u8*)address;
|
||||
address += send; // not sure of this is required
|
||||
}
|
||||
|
||||
// Check sync
|
||||
if (getch() != ' ')
|
||||
break;
|
||||
Transfer(CDC_TX,&_inSync,1);
|
||||
|
||||
// Send result
|
||||
if (send)
|
||||
Transfer(CDC_TX|TRANSFER_PGM,pgm,send); // All from pgm memory
|
||||
|
||||
// Send ok
|
||||
Transfer(CDC_TX|TRANSFER_RELEASE,&_ok,1);
|
||||
|
||||
if (cmd == 'Q')
|
||||
break;
|
||||
}
|
||||
_timeout = 500; // wait a moment before exiting the bootloader - may need to finish responding to 'Q' for example
|
||||
_ejected = 1;
|
||||
}
|
||||
}
|
||||
|
||||
// Nice breathing LED indicates we are in the firmware
|
||||
u16 _pulse;
|
||||
void LEDPulse()
|
||||
{
|
||||
_pulse += 4;
|
||||
u8 p = _pulse >> 9;
|
||||
if (p > 63)
|
||||
p = 127-p;
|
||||
p += p;
|
||||
if (((u8)_pulse) > p)
|
||||
LED0;
|
||||
else
|
||||
LED1;
|
||||
}
|
||||
|
||||
void Reboot()
|
||||
{
|
||||
TXLED0; // switch off the RX and TX LEDs before starting the user sketch
|
||||
RXLED0;
|
||||
UDCON = 1; // Detatch USB
|
||||
UDIEN = 0;
|
||||
asm volatile ( // Reset vector to run firmware
|
||||
"clr r30\n"
|
||||
"clr r31\n"
|
||||
"ijmp\n"
|
||||
::);
|
||||
}
|
|
@ -1,51 +0,0 @@
|
|||
|
||||
#include <inttypes.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/boot.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/wdt.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned long u32;
|
||||
|
||||
|
||||
#define CPU_PRESCALE(n) (CLKPR = 0x80, CLKPR = (n))
|
||||
#define DISABLE_JTAG() MCUCR = (1 << JTD) | (1 << IVCE) | (0 << PUD); MCUCR = (1 << JTD) | (0 << IVSEL) | (0 << IVCE) | (0 << PUD);
|
||||
|
||||
#define USB_PID_LEONARDO 0x0034
|
||||
#define USB_PID_MICRO 0x0035
|
||||
#define USB_VID 0x2341 // arduino LLC vid
|
||||
#define USB_PID ARDUINO_MODEL_PID // passed in by Makefile - 0x0034 for Leonardo, 0x0035 for MIcro
|
||||
|
||||
#define USB_SERIAL_STRING '0','0','0','0','0','0','0','0','1','7','0','1'
|
||||
|
||||
#define OEM_NAME 'l','e','o','n','a','r','d','o' // 8 chars
|
||||
#define BOARD_INIT() DDRC |= (1<<7); DDRB |= (1<<0); DDRD |= (1<<5); CPU_PRESCALE(0); DISABLE_JTAG();
|
||||
#define LED0 PORTC &= ~(1<<7)
|
||||
#define LED1 PORTC |= (1<<7)
|
||||
#define TXLED0 PORTD |= (1<<5)
|
||||
#define TXLED1 PORTD &= ~(1<<5)
|
||||
#define RXLED0 PORTB |= (1<<0)
|
||||
#define RXLED1 PORTB &= ~(1<<0)
|
||||
|
||||
#define TRANSFER_PGM 0x80
|
||||
#define TRANSFER_RELEASE 0x40
|
||||
#define TRANSFER_ZERO 0x20
|
||||
|
||||
void Transfer(u8 ep, const u8* data, int len);
|
||||
void Recv(u8 ep, u8* dst, u8 len);
|
||||
void Program(u8 ep, u16 page, u8 count);
|
||||
|
||||
#define CDC_ENABLED
|
||||
|
||||
#include "USBCore.h"
|
||||
#include "USBDesc.h"
|
||||
|
||||
|
|
@ -1,510 +0,0 @@
|
|||
|
||||
|
||||
/* Copyright (c) 2010, Peter Barrett
|
||||
**
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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 "Platform.h"
|
||||
|
||||
#define CDC_TX CDC_ENDPOINT_IN
|
||||
#define CDC_RX CDC_ENDPOINT_OUT
|
||||
|
||||
#define EP_TYPE_CONTROL 0x00
|
||||
#define EP_TYPE_BULK_IN 0x81
|
||||
#define EP_TYPE_BULK_OUT 0x80
|
||||
#define EP_TYPE_INTERRUPT_IN 0xC1
|
||||
#define EP_TYPE_INTERRUPT_OUT 0xC0
|
||||
#define EP_TYPE_ISOCHRONOUS_IN 0x41
|
||||
#define EP_TYPE_ISOCHRONOUS_OUT 0x40
|
||||
|
||||
/** Pulse generation counters to keep track of the number of milliseconds remaining for each pulse type */
|
||||
#define TX_RX_LED_PULSE_MS 100
|
||||
u8 TxLEDPulse; /**< Milliseconds remaining for data Tx LED pulse */
|
||||
u8 RxLEDPulse; /**< Milliseconds remaining for data Rx LED pulse */
|
||||
|
||||
void Reboot();
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u32 dwDTERate;
|
||||
u8 bCharFormat;
|
||||
u8 bParityType;
|
||||
u8 bDataBits;
|
||||
u8 lineState;
|
||||
} LineInfo;
|
||||
|
||||
static volatile LineInfo _usbLineInfo = { 57600, 0x00, 0x00, 0x00, 0x00 };
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
// 4 bytes of RAM
|
||||
volatile u8 _usbConfiguration;
|
||||
volatile u8 _ejected;
|
||||
volatile u16 _timeout;
|
||||
|
||||
static inline void WaitIN(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<TXINI)));
|
||||
}
|
||||
|
||||
static inline void ClearIN(void)
|
||||
{
|
||||
UEINTX = ~(1<<TXINI);
|
||||
}
|
||||
|
||||
static inline void WaitOUT(void)
|
||||
{
|
||||
while (!(UEINTX & (1<<RXOUTI)))
|
||||
;
|
||||
}
|
||||
|
||||
static inline u8 WaitForINOrOUT()
|
||||
{
|
||||
while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
|
||||
;
|
||||
return (UEINTX & (1<<RXOUTI)) == 0;
|
||||
}
|
||||
|
||||
static inline void ClearOUT(void)
|
||||
{
|
||||
UEINTX = ~(1<<RXOUTI);
|
||||
}
|
||||
|
||||
static
|
||||
void Send(volatile const u8* data, u8 count)
|
||||
{
|
||||
TXLED1; // light the TX LED
|
||||
TxLEDPulse = TX_RX_LED_PULSE_MS;
|
||||
while (count--)
|
||||
UEDATX = *data++;
|
||||
}
|
||||
|
||||
void Recv(volatile u8* data, u8 count)
|
||||
{
|
||||
RXLED1; // light the RX LED
|
||||
RxLEDPulse = TX_RX_LED_PULSE_MS;
|
||||
while (count--)
|
||||
*data++ = UEDATX;
|
||||
}
|
||||
|
||||
static inline u8 Recv8()
|
||||
{
|
||||
RXLED1; // light the RX LED
|
||||
RxLEDPulse = TX_RX_LED_PULSE_MS;
|
||||
return UEDATX;
|
||||
}
|
||||
|
||||
static inline void Send8(u8 d)
|
||||
{
|
||||
TXLED1; // light the TX LED
|
||||
TxLEDPulse = TX_RX_LED_PULSE_MS;
|
||||
UEDATX = d;
|
||||
}
|
||||
|
||||
static inline void SetEP(u8 ep)
|
||||
{
|
||||
UENUM = ep;
|
||||
}
|
||||
|
||||
static inline u8 FifoByteCount()
|
||||
{
|
||||
return UEBCLX;
|
||||
}
|
||||
|
||||
static inline u8 ReceivedSetupInt()
|
||||
{
|
||||
return UEINTX & (1<<RXSTPI);
|
||||
}
|
||||
|
||||
static inline void ClearSetupInt()
|
||||
{
|
||||
UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
|
||||
}
|
||||
|
||||
static inline void Stall()
|
||||
{
|
||||
UECONX = (1<<STALLRQ) | (1<<EPEN);
|
||||
}
|
||||
|
||||
static inline u8 ReadWriteAllowed()
|
||||
{
|
||||
return UEINTX & (1<<RWAL);
|
||||
}
|
||||
|
||||
static inline u8 Stalled()
|
||||
{
|
||||
return UEINTX & (1<<STALLEDI);
|
||||
}
|
||||
|
||||
static inline u8 FifoFree()
|
||||
{
|
||||
return UEINTX & (1<<FIFOCON);
|
||||
}
|
||||
|
||||
static inline void ReleaseRX()
|
||||
{
|
||||
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
|
||||
}
|
||||
|
||||
static inline void ReleaseTX()
|
||||
{
|
||||
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
|
||||
}
|
||||
|
||||
static inline u8 FrameNumber()
|
||||
{
|
||||
return UDFNUML;
|
||||
}
|
||||
|
||||
//==================================================================
|
||||
//==================================================================
|
||||
|
||||
#define EP_SINGLE_64 0x32 // EP0
|
||||
#define EP_DOUBLE_64 0x36 // Other endpoints
|
||||
|
||||
static void InitEP(u8 index, u8 type, u8 size)
|
||||
{
|
||||
UENUM = index;
|
||||
UECONX = 1;
|
||||
UECFG0X = type;
|
||||
UECFG1X = size;
|
||||
}
|
||||
|
||||
// API
|
||||
void USBInit(void)
|
||||
{
|
||||
_timeout = 0;
|
||||
_usbConfiguration = 0;
|
||||
_ejected = 0;
|
||||
|
||||
UHWCON = 0x01; // power internal reg (don't need this?)
|
||||
USBCON = (1<<USBE)|(1<<FRZCLK); // clock frozen, usb enabled
|
||||
PLLCSR = 0x12; // Need 16 MHz xtal
|
||||
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
|
||||
;
|
||||
USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock
|
||||
UDCON = 0; // enable attach resistor
|
||||
}
|
||||
|
||||
u8 USBGetConfiguration(void)
|
||||
{
|
||||
return _usbConfiguration;
|
||||
}
|
||||
|
||||
u8 HasData(u8 ep)
|
||||
{
|
||||
SetEP(ep);
|
||||
return ReadWriteAllowed(); // count in fifo
|
||||
}
|
||||
|
||||
int USBGetChar();
|
||||
void Recv(u8 ep, u8* dst, u8 len)
|
||||
{
|
||||
SetEP(ep);
|
||||
while (len--)
|
||||
{
|
||||
while (!ReadWriteAllowed())
|
||||
;
|
||||
*dst++ = Recv8();
|
||||
if (!ReadWriteAllowed()) // release empty buffer
|
||||
ReleaseRX();
|
||||
}
|
||||
}
|
||||
|
||||
// Transmit a packet to endpoint
|
||||
void Transfer(u8 ep, const u8* data, int len)
|
||||
{
|
||||
u8 zero = ep & TRANSFER_ZERO;
|
||||
SetEP(ep & 7);
|
||||
while (len--)
|
||||
{
|
||||
while (!ReadWriteAllowed())
|
||||
; // TODO Check for STALL etc
|
||||
|
||||
u8 d = (ep & TRANSFER_PGM) ? pgm_read_byte(data) : data[0];
|
||||
data++;
|
||||
if (zero)
|
||||
d = 0;
|
||||
Send8(d);
|
||||
|
||||
if (!ReadWriteAllowed())
|
||||
ReleaseTX();
|
||||
}
|
||||
if (ep & TRANSFER_RELEASE)
|
||||
ReleaseTX();
|
||||
}
|
||||
|
||||
extern const u8 _initEndpoints[] PROGMEM;
|
||||
const u8 _initEndpoints[] =
|
||||
{
|
||||
0,
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
EP_TYPE_INTERRUPT_IN, // CDC_ENDPOINT_ACM
|
||||
EP_TYPE_BULK_OUT, // CDC_ENDPOINT_OUT
|
||||
EP_TYPE_BULK_IN, // CDC_ENDPOINT_IN
|
||||
#endif
|
||||
|
||||
EP_TYPE_INTERRUPT_IN, // HID_ENDPOINT_INT
|
||||
};
|
||||
|
||||
static void InitEndpoints()
|
||||
{
|
||||
for (u8 i = 1; i < sizeof(_initEndpoints); i++)
|
||||
{
|
||||
UENUM = i;
|
||||
UECONX = 1;
|
||||
UECFG0X = pgm_read_byte(_initEndpoints+i);
|
||||
UECFG1X = EP_DOUBLE_64;
|
||||
}
|
||||
UERST = 0x7E; // And reset them
|
||||
UERST = 0;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 bmRequestType;
|
||||
u8 bRequest;
|
||||
u8 wValueL;
|
||||
u8 wValueH;
|
||||
u16 wIndex;
|
||||
u16 wLength;
|
||||
} Setup;
|
||||
Setup _setup;
|
||||
|
||||
//bool USBHook(Setup& setup)
|
||||
bool USBHook()
|
||||
{
|
||||
Setup& setup = _setup;
|
||||
u8 r = setup.bRequest;
|
||||
|
||||
// CDC Requests
|
||||
if (CDC_GET_LINE_CODING == r)
|
||||
{
|
||||
Send((const volatile u8*)&_usbLineInfo,7);
|
||||
}
|
||||
|
||||
else if (CDC_SET_LINE_CODING == r)
|
||||
{
|
||||
WaitOUT();
|
||||
Recv((volatile u8*)&_usbLineInfo,7);
|
||||
ClearOUT();
|
||||
}
|
||||
|
||||
else if (CDC_SET_CONTROL_LINE_STATE == r)
|
||||
{
|
||||
_usbLineInfo.lineState = setup.wValueL;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
extern const u8 _rawHID[] PROGMEM;
|
||||
#define LSB(_x) ((_x) & 0xFF)
|
||||
#define MSB(_x) ((_x) >> 8)
|
||||
|
||||
#define RAWHID_USAGE_PAGE 0xFFC0
|
||||
#define RAWHID_USAGE 0x0C00
|
||||
#define RAWHID_TX_SIZE 64
|
||||
#define RAWHID_RX_SIZE 64
|
||||
|
||||
const u8 _rawHID[] =
|
||||
{
|
||||
// RAW HID
|
||||
0x06, LSB(RAWHID_USAGE_PAGE), MSB(RAWHID_USAGE_PAGE), // 30
|
||||
0x0A, LSB(RAWHID_USAGE), MSB(RAWHID_USAGE),
|
||||
|
||||
0xA1, 0x01, // Collection 0x01
|
||||
0x85, 0x03, // REPORT_ID (3)
|
||||
0x75, 0x08, // report size = 8 bits
|
||||
0x15, 0x00, // logical minimum = 0
|
||||
0x26, 0xFF, 0x00, // logical maximum = 255
|
||||
|
||||
0x95, 64, // report count TX
|
||||
0x09, 0x01, // usage
|
||||
0x81, 0x02, // Input (array)
|
||||
|
||||
0x95, 64, // report count RX
|
||||
0x09, 0x02, // usage
|
||||
0x91, 0x02, // Output (array)
|
||||
0xC0 // end collection
|
||||
};
|
||||
|
||||
u8 _cdcComposite = 0;
|
||||
|
||||
bool SendDescriptor()
|
||||
{
|
||||
Setup& setup = _setup;
|
||||
u8 desc_length = 0;
|
||||
const u8* desc_addr = 0;
|
||||
|
||||
u8 t = setup.wValueH;
|
||||
if (0x22 == t)
|
||||
{
|
||||
desc_addr = _rawHID;
|
||||
desc_length = sizeof(desc_length);
|
||||
} else if (USB_DEVICE_DESCRIPTOR_TYPE == t)
|
||||
{
|
||||
if (setup.wLength == 8)
|
||||
_cdcComposite = 1;
|
||||
desc_addr = _cdcComposite ? (const u8*)&USB_DeviceDescriptorA : (const u8*)&USB_DeviceDescriptor;
|
||||
}
|
||||
else if (USB_CONFIGURATION_DESCRIPTOR_TYPE == t)
|
||||
{
|
||||
desc_addr = (const u8*)&USB_ConfigDescriptor;
|
||||
desc_length = sizeof(USB_ConfigDescriptor);
|
||||
}
|
||||
else if (USB_STRING_DESCRIPTOR_TYPE == t)
|
||||
{
|
||||
if (setup.wValueL == 0)
|
||||
desc_addr = (const u8*)&STRING_LANGUAGE;
|
||||
else if (setup.wValueL == IPRODUCT)
|
||||
desc_addr = (const u8*)&STRING_IPRODUCT;
|
||||
else if (setup.wValueL == ISERIAL)
|
||||
desc_addr = (const u8*)&STRING_SERIAL;
|
||||
else if (setup.wValueL == IMANUFACTURER)
|
||||
desc_addr = (const u8*)&STRING_IMANUFACTURER;
|
||||
else
|
||||
return false;
|
||||
} else
|
||||
return false;
|
||||
|
||||
if (desc_length == 0)
|
||||
desc_length = pgm_read_byte(desc_addr);
|
||||
if ((u8)setup.wLength < desc_length) // bit of a cheat limiting to 255 bytes TODO (saved 8 bytes)
|
||||
desc_length = (u8)setup.wLength;
|
||||
|
||||
// Send descriptor
|
||||
// EP0 is 64 bytes long
|
||||
// RWAL and FIFOCON don't work on EP0
|
||||
u8 n = 0;
|
||||
do
|
||||
{
|
||||
if (!WaitForINOrOUT())
|
||||
return false;
|
||||
Send8(pgm_read_byte(&desc_addr[n++]));
|
||||
u8 clr = n & 0x3F;
|
||||
if (!clr)
|
||||
ClearIN(); // Fifo is full, release this packet
|
||||
} while (n < desc_length);
|
||||
return true;
|
||||
}
|
||||
|
||||
void USBSetupInterrupt()
|
||||
{
|
||||
SetEP(0);
|
||||
if (!ReceivedSetupInt())
|
||||
return;
|
||||
|
||||
Setup& setup = _setup; // global saves ~30 bytes
|
||||
Recv((u8*)&setup,8);
|
||||
ClearSetupInt();
|
||||
|
||||
if (setup.bmRequestType & DEVICETOHOST)
|
||||
WaitIN();
|
||||
else
|
||||
ClearIN();
|
||||
|
||||
bool ok = true;
|
||||
u8 r = setup.bRequest;
|
||||
if (SET_ADDRESS == r)
|
||||
{
|
||||
WaitIN();
|
||||
UDADDR = setup.wValueL | (1<<ADDEN);
|
||||
}
|
||||
else if (SET_CONFIGURATION == r)
|
||||
{
|
||||
_usbConfiguration = setup.wValueL;
|
||||
InitEndpoints();
|
||||
}
|
||||
else if (GET_CONFIGURATION == r)
|
||||
{
|
||||
Send8(_usbConfiguration);
|
||||
}
|
||||
else if (GET_STATUS == r)
|
||||
{
|
||||
Send8(0); // All good as far as I know
|
||||
}
|
||||
else if (GET_DESCRIPTOR == r)
|
||||
{
|
||||
ok = SendDescriptor();
|
||||
}
|
||||
else
|
||||
{
|
||||
ok = USBHook();
|
||||
}
|
||||
|
||||
if (ok)
|
||||
ClearIN();
|
||||
else
|
||||
Stall();
|
||||
}
|
||||
|
||||
void USBGeneralInterrupt()
|
||||
{
|
||||
u8 udint = UDINT;
|
||||
UDINT = 0;
|
||||
|
||||
// End of Reset
|
||||
if (udint & (1<<EORSTI))
|
||||
{
|
||||
InitEP(0,EP_TYPE_CONTROL,EP_SINGLE_64); // init ep0
|
||||
_usbConfiguration = 0; // not configured yet
|
||||
}
|
||||
|
||||
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
|
||||
if (udint & (1<<SOFI))
|
||||
{
|
||||
// check whether the one-shot period has elapsed. if so, turn off the LED
|
||||
if (TxLEDPulse && !(--TxLEDPulse))
|
||||
TXLED0;
|
||||
if (RxLEDPulse && !(--RxLEDPulse))
|
||||
RXLED0;
|
||||
|
||||
if (!_ejected)
|
||||
_timeout = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void LEDPulse();
|
||||
int USBGetChar()
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
USBSetupInterrupt();
|
||||
USBGeneralInterrupt();
|
||||
|
||||
// Read a char
|
||||
if (HasData(CDC_RX))
|
||||
{
|
||||
u8 c = Recv8();
|
||||
if (!ReadWriteAllowed())
|
||||
ReleaseRX();
|
||||
return c;
|
||||
}
|
||||
|
||||
if (!--_timeout) {
|
||||
Reboot(); // USB not connected, run firmware
|
||||
}
|
||||
|
||||
_delay_us(100); // stretch out the bootloader period to about 5 seconds after enumeration
|
||||
LEDPulse();
|
||||
}
|
||||
return -1;
|
||||
}
|
|
@ -1,246 +0,0 @@
|
|||
|
||||
// Copyright (c) 2010, Peter Barrett
|
||||
/*
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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.
|
||||
*/
|
||||
|
||||
#ifndef __USBCORE_H__
|
||||
#define __USBCORE_H__
|
||||
|
||||
#define GET_STATUS 0
|
||||
#define CLEAR_FEATURE 1
|
||||
#define SET_FEATURE 3
|
||||
#define SET_ADDRESS 5
|
||||
#define GET_DESCRIPTOR 6
|
||||
#define GET_CONFIGURATION 8
|
||||
#define SET_CONFIGURATION 9
|
||||
#define GET_INTERFACE 10
|
||||
#define SET_INTERFACE 11
|
||||
|
||||
// bmRequestType
|
||||
#define HOSTTODEVICE 0x00
|
||||
#define DEVICETOHOST 0x80
|
||||
#define STANDARD 0x00
|
||||
#define CLASS 0x20
|
||||
#define VENDOR 0x40
|
||||
#define DEVICE 0x00
|
||||
#define INTERFACE 0x01
|
||||
#define ENDPOINT 0x02
|
||||
#define OTHER 0x03
|
||||
|
||||
#define CDC_SET_LINE_CODING 0x20
|
||||
#define CDC_GET_LINE_CODING 0x21
|
||||
#define CDC_SET_CONTROL_LINE_STATE 0x22
|
||||
|
||||
// Descriptors
|
||||
|
||||
#define USB_DEVICE_DESC_SIZE 18
|
||||
#define USB_CONFIGUARTION_DESC_SIZE 9
|
||||
#define USB_INTERFACE_DESC_SIZE 9
|
||||
#define USB_ENDPOINT_DESC_SIZE 7
|
||||
|
||||
#define USB_DEVICE_DESCRIPTOR_TYPE 1
|
||||
#define USB_CONFIGURATION_DESCRIPTOR_TYPE 2
|
||||
#define USB_STRING_DESCRIPTOR_TYPE 3
|
||||
#define USB_INTERFACE_DESCRIPTOR_TYPE 4
|
||||
#define USB_ENDPOINT_DESCRIPTOR_TYPE 5
|
||||
|
||||
#define USB_DEVICE_CLASS_COMMUNICATIONS 0x02
|
||||
#define USB_DEVICE_CLASS_HUMAN_INTERFACE 0x03
|
||||
#define USB_DEVICE_CLASS_STORAGE 0x08
|
||||
#define USB_DEVICE_CLASS_VENDOR_SPECIFIC 0xFF
|
||||
|
||||
#define USB_CONFIG_POWERED_MASK 0x40
|
||||
#define USB_CONFIG_BUS_POWERED 0x80
|
||||
#define USB_CONFIG_SELF_POWERED 0xC0
|
||||
#define USB_CONFIG_REMOTE_WAKEUP 0x20
|
||||
|
||||
// bMaxPower in Configuration Descriptor
|
||||
#define USB_CONFIG_POWER_MA(mA) ((mA)/2)
|
||||
|
||||
// bEndpointAddress in Endpoint Descriptor
|
||||
#define USB_ENDPOINT_DIRECTION_MASK 0x80
|
||||
#define USB_ENDPOINT_OUT(addr) ((addr) | 0x00)
|
||||
#define USB_ENDPOINT_IN(addr) ((addr) | 0x80)
|
||||
|
||||
#define USB_ENDPOINT_TYPE_MASK 0x03
|
||||
#define USB_ENDPOINT_TYPE_CONTROL 0x00
|
||||
#define USB_ENDPOINT_TYPE_ISOCHRONOUS 0x01
|
||||
#define USB_ENDPOINT_TYPE_BULK 0x02
|
||||
#define USB_ENDPOINT_TYPE_INTERRUPT 0x03
|
||||
|
||||
#define TOBYTES(x) ((x) & 0xFF),(((x) >> 8) & 0xFF)
|
||||
|
||||
#define CDC_V1_10 0x0110
|
||||
#define CDC_COMMUNICATION_INTERFACE_CLASS 0x02
|
||||
|
||||
#define CDC_CALL_MANAGEMENT 0x01
|
||||
#define CDC_ABSTRACT_CONTROL_MODEL 0x02
|
||||
#define CDC_HEADER 0x00
|
||||
#define CDC_ABSTRACT_CONTROL_MANAGEMENT 0x02
|
||||
#define CDC_UNION 0x06
|
||||
#define CDC_CS_INTERFACE 0x24
|
||||
#define CDC_CS_ENDPOINT 0x25
|
||||
#define CDC_DATA_INTERFACE_CLASS 0x0A
|
||||
|
||||
|
||||
// Device
|
||||
typedef struct {
|
||||
u8 len; // 18
|
||||
u8 dtype; // 1 USB_DEVICE_DESCRIPTOR_TYPE
|
||||
u16 usbVersion; // 0x200
|
||||
u8 deviceClass;
|
||||
u8 deviceSubClass;
|
||||
u8 deviceProtocol;
|
||||
u8 packetSize0; // Packet 0
|
||||
u16 idVendor;
|
||||
u16 idProduct;
|
||||
u16 deviceVersion; // 0x100
|
||||
u8 iManufacturer;
|
||||
u8 iProduct;
|
||||
u8 iSerialNumber;
|
||||
u8 bNumConfigurations;
|
||||
} DeviceDescriptor;
|
||||
|
||||
// Config
|
||||
typedef struct {
|
||||
u8 len; // 9
|
||||
u8 dtype; // 2
|
||||
u16 clen; // total length
|
||||
u8 numInterfaces;
|
||||
u8 config;
|
||||
u8 iconfig;
|
||||
u8 attributes;
|
||||
u8 maxPower;
|
||||
} ConfigDescriptor;
|
||||
|
||||
// String
|
||||
|
||||
// Interface
|
||||
typedef struct
|
||||
{
|
||||
u8 len; // 9
|
||||
u8 dtype; // 4
|
||||
u8 number;
|
||||
u8 alternate;
|
||||
u8 numEndpoints;
|
||||
u8 interfaceClass;
|
||||
u8 interfaceSubClass;
|
||||
u8 protocol;
|
||||
u8 iInterface;
|
||||
} InterfaceDescriptor;
|
||||
|
||||
// Endpoint
|
||||
typedef struct
|
||||
{
|
||||
u8 len; // 7
|
||||
u8 dtype; // 5
|
||||
u8 addr;
|
||||
u8 attr;
|
||||
u16 packetSize;
|
||||
u8 interval;
|
||||
} EndpointDescriptor;
|
||||
|
||||
// Interface Association Descriptor
|
||||
// Used to bind 2 interfaces together in CDC compostite device
|
||||
typedef struct
|
||||
{
|
||||
u8 len; // 8
|
||||
u8 dtype; // 11
|
||||
u8 firstInterface;
|
||||
u8 interfaceCount;
|
||||
u8 functionClass;
|
||||
u8 funtionSubClass;
|
||||
u8 functionProtocol;
|
||||
u8 iInterface;
|
||||
} IADDescriptor;
|
||||
|
||||
// CDC CS interface descriptor
|
||||
typedef struct
|
||||
{
|
||||
u8 len; // 5
|
||||
u8 dtype; // 0x24
|
||||
u8 subtype;
|
||||
u8 d0;
|
||||
u8 d1;
|
||||
} CDCCSInterfaceDescriptor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 len; // 4
|
||||
u8 dtype; // 0x24
|
||||
u8 subtype;
|
||||
u8 d0;
|
||||
} CDCCSInterfaceDescriptor4;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IADDescriptor iad; // Only needed on compound device
|
||||
|
||||
// Control
|
||||
InterfaceDescriptor cif; //
|
||||
CDCCSInterfaceDescriptor header;
|
||||
CDCCSInterfaceDescriptor callManagement;
|
||||
CDCCSInterfaceDescriptor4 controlManagement;
|
||||
CDCCSInterfaceDescriptor functionalDescriptor;
|
||||
EndpointDescriptor cifin;
|
||||
|
||||
// Data
|
||||
InterfaceDescriptor dif;
|
||||
EndpointDescriptor in;
|
||||
EndpointDescriptor out;
|
||||
} CDCDescriptor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
u8 len; // 9
|
||||
u8 dtype; // 0x21
|
||||
u8 addr;
|
||||
u8 versionL; // 0x101
|
||||
u8 versionH; // 0x101
|
||||
u8 country;
|
||||
u8 desctype; // 0x22 report
|
||||
u8 descLenL;
|
||||
u8 descLenH;
|
||||
} HIDDescDescriptor;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
InterfaceDescriptor hid;
|
||||
HIDDescDescriptor desc;
|
||||
EndpointDescriptor in;
|
||||
} HIDDescriptor;
|
||||
|
||||
#define D_DEVICE(_class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs) \
|
||||
{ 18, 1, 0x200, _class,_subClass,_proto,_packetSize0,_vid,_pid,_version,_im,_ip,_is,_configs }
|
||||
|
||||
#define D_CONFIG(_totalLength,_interfaces) \
|
||||
{ 9, 2, _totalLength,_interfaces, 1, 0, USB_CONFIG_BUS_POWERED, USB_CONFIG_POWER_MA(100) }
|
||||
|
||||
#define D_INTERFACE(_n,_numEndpoints,_class,_subClass,_protocol) \
|
||||
{ 9, 4, _n, 0, _numEndpoints, _class,_subClass, _protocol, 0 }
|
||||
|
||||
#define D_ENDPOINT(_addr,_attr,_packetSize, _interval) \
|
||||
{ 7, 5, _addr,_attr,_packetSize, _interval }
|
||||
|
||||
#define D_IAD(_firstInterface, _count, _class, _subClass, _protocol) \
|
||||
{ 8, 11, _firstInterface, _count, _class, _subClass, _protocol, 0 }
|
||||
|
||||
#define D_HIDREPORT(_descriptorLength) \
|
||||
{ 9, 0x21, 0x1, 0x1, 0, 1, 0x22, _descriptorLength, 0 }
|
||||
|
||||
#define D_CDCCS(_subtype,_d0,_d1) { 5, 0x24, _subtype, _d0, _d1 }
|
||||
#define D_CDCCS4(_subtype,_d0) { 4, 0x24, _subtype, _d0 }
|
||||
|
||||
#endif
|
|
@ -1,87 +0,0 @@
|
|||
|
||||
|
||||
/* Copyright (c) 2011, Peter Barrett
|
||||
**
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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 "Platform.h"
|
||||
|
||||
//====================================================================================================
|
||||
//====================================================================================================
|
||||
// Actual device descriptors
|
||||
|
||||
const u16 STRING_LANGUAGE[2] = {
|
||||
(3<<8) | (2+2),
|
||||
0x0409 // English
|
||||
};
|
||||
|
||||
const u16 STRING_SERIAL[13] = {
|
||||
(3<<8) | (2+2*12),
|
||||
USB_SERIAL_STRING
|
||||
};
|
||||
|
||||
const u16 STRING_IPRODUCT[28] = {
|
||||
(3<<8) | (2+2*27),
|
||||
#if USB_PID == USB_PID_LEONARDO
|
||||
'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o',' ','b','o','o','t','l','o','a','d','e','r'
|
||||
#elif USB_PID == USB_PID_MICRO
|
||||
'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ','b','o','o','t','l','o','a','d','e','r',' ',' ',' '
|
||||
#endif
|
||||
};
|
||||
|
||||
const u16 STRING_IMANUFACTURER[12] = {
|
||||
(3<<8) | (2+2*11),
|
||||
'A','r','d','u','i','n','o',' ','L','L','C'
|
||||
};
|
||||
|
||||
|
||||
//#ifdef CDC_ENABLED
|
||||
DeviceDescriptor USB_DeviceDescriptorA = D_DEVICE(0X02,0X00,0X00,64,USB_VID,USB_PID,0x100,0,IPRODUCT,ISERIAL,1);
|
||||
//#else
|
||||
DeviceDescriptor USB_DeviceDescriptor = D_DEVICE(0x00,0x00,0x00,64,USB_VID,USB_PID,0x100,0,IPRODUCT,ISERIAL,1);
|
||||
//#endif
|
||||
|
||||
|
||||
Config USB_ConfigDescriptor =
|
||||
{
|
||||
D_CONFIG(sizeof(Config),INTERFACE_COUNT),
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
// CDC
|
||||
{
|
||||
D_IAD(0,2,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,1),
|
||||
|
||||
// CDC communication interface
|
||||
D_INTERFACE(CDC_ACM_INTERFACE,1,CDC_COMMUNICATION_INTERFACE_CLASS,CDC_ABSTRACT_CONTROL_MODEL,0),
|
||||
D_CDCCS(CDC_HEADER,0x10,0x01), // Header (1.10 bcd)
|
||||
D_CDCCS(CDC_CALL_MANAGEMENT,1,1), // Device handles call management
|
||||
D_CDCCS4(CDC_ABSTRACT_CONTROL_MANAGEMENT,2), // SET_LINE_CODING, GET_LINE_CODING, SET_CONTROL_LINE_STATE supported
|
||||
D_CDCCS(CDC_UNION,CDC_ACM_INTERFACE,CDC_DATA_INTERFACE), // Communication interface is master, data interface is slave 0
|
||||
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_ACM),USB_ENDPOINT_TYPE_INTERRUPT,0x10,0x40),
|
||||
|
||||
// CDC data interface
|
||||
D_INTERFACE(CDC_DATA_INTERFACE,2,CDC_DATA_INTERFACE_CLASS,0,0),
|
||||
D_ENDPOINT(USB_ENDPOINT_OUT(CDC_ENDPOINT_OUT),USB_ENDPOINT_TYPE_BULK,0x40,0),
|
||||
D_ENDPOINT(USB_ENDPOINT_IN (CDC_ENDPOINT_IN ),USB_ENDPOINT_TYPE_BULK,0x40,0)
|
||||
},
|
||||
#endif
|
||||
// HID
|
||||
{
|
||||
D_INTERFACE(HID_INTERFACE,1,3,0,0),
|
||||
D_HIDREPORT(30),
|
||||
D_ENDPOINT(USB_ENDPOINT_IN (HID_ENDPOINT_INT),USB_ENDPOINT_TYPE_INTERRUPT,0x40,0x40)
|
||||
}
|
||||
};
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
|
||||
|
||||
/* Copyright (c) 2011, Peter Barrett
|
||||
**
|
||||
** Permission to use, copy, modify, and/or distribute this software for
|
||||
** any purpose with or without fee is hereby granted, provided that the
|
||||
** above copyright notice and this permission notice appear in all copies.
|
||||
**
|
||||
** THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS 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, DIRECT, 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
|
||||
#define CDC_ACM_INTERFACE 0 // CDC ACM
|
||||
#define CDC_DATA_INTERFACE 1 // CDC Data
|
||||
#define CDC_ENDPOINT_ACM 1
|
||||
#define CDC_ENDPOINT_OUT 2
|
||||
#define CDC_ENDPOINT_IN 3
|
||||
|
||||
#define HID_INTERFACE 2 // HID Interface
|
||||
#define HID_ENDPOINT_INT 4
|
||||
|
||||
#define INTERFACE_COUNT 3 // 2 for cdc + 1 for hid
|
||||
|
||||
#else
|
||||
|
||||
#define HID_INTERFACE 2 // HID Interface
|
||||
#define HID_ENDPOINT_INT 4
|
||||
|
||||
#define INTERFACE_COUNT 1 // 1 for hid
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ConfigDescriptor config;
|
||||
#ifdef CDC_ENABLED
|
||||
CDCDescriptor cdc;
|
||||
#endif
|
||||
HIDDescriptor hid;
|
||||
} Config;
|
||||
|
||||
extern Config USB_ConfigDescriptor PROGMEM;
|
||||
extern DeviceDescriptor USB_DeviceDescriptor PROGMEM;
|
||||
extern DeviceDescriptor USB_DeviceDescriptorA PROGMEM;
|
||||
|
||||
extern const u16 STRING_LANGUAGE[2] PROGMEM;
|
||||
extern const u16 STRING_IPRODUCT[28] PROGMEM;
|
||||
extern const u16 STRING_IMANUFACTURER[12] PROGMEM;
|
||||
extern const u16 STRING_SERIAL[13] PROGMEM;
|
||||
|
||||
#define IMANUFACTURER 1
|
||||
#define IPRODUCT 2
|
||||
#define ISERIAL 3
|
||||
|
||||
#define CDC_TX CDC_ENDPOINT_IN
|
||||
#define CDC_RX CDC_ENDPOINT_OUT
|
|
@ -23,12 +23,20 @@
|
|||
#if defined(USBCON)
|
||||
#ifdef CDC_ENABLED
|
||||
|
||||
void Reboot()
|
||||
#if (RAMEND < 1000)
|
||||
#define SERIAL_BUFFER_SIZE 16
|
||||
#else
|
||||
#define SERIAL_BUFFER_SIZE 64
|
||||
#endif
|
||||
|
||||
struct ring_buffer
|
||||
{
|
||||
USB.detach();
|
||||
cli();
|
||||
asm volatile("jmp 0x7800"); // jump to bootloader - DiskLoader takes up last 2 kB
|
||||
}
|
||||
unsigned char buffer[SERIAL_BUFFER_SIZE];
|
||||
volatile int head;
|
||||
volatile int tail;
|
||||
};
|
||||
|
||||
ring_buffer cdc_rx_buffer = { { 0 }, 0, 0};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
|
@ -92,9 +100,28 @@ bool WEAK CDC_Setup(Setup& setup)
|
|||
|
||||
if (CDC_SET_CONTROL_LINE_STATE == r)
|
||||
{
|
||||
if (0 != _usbLineInfo.lineState && 1200 == _usbLineInfo.dwDTERate) // auto-reset is triggered when the port, already open at 1200 bps, is closed
|
||||
Reboot();
|
||||
_usbLineInfo.lineState = setup.wValueL;
|
||||
|
||||
// auto-reset into the bootloader is triggered when the port, already
|
||||
// open at 1200 bps, is closed. this is the signal to start the watchdog
|
||||
// with a relatively long period so it can finish housekeeping tasks
|
||||
// like servicing endpoints before the sketch ends
|
||||
if (1200 == _usbLineInfo.dwDTERate) {
|
||||
// We check DTR state to determine if host port is open (bit 0 of lineState).
|
||||
if ((_usbLineInfo.lineState & 0x01) == 0) {
|
||||
*(uint16_t *)0x0800 = 0x7777;
|
||||
wdt_enable(WDTO_120MS);
|
||||
} else {
|
||||
// Most OSs do some intermediate steps when configuring ports and DTR can
|
||||
// twiggle more than once before stabilizing.
|
||||
// To avoid spurious resets we set the watchdog to 250ms and eventually
|
||||
// cancel if DTR goes back high.
|
||||
|
||||
wdt_disable();
|
||||
wdt_reset();
|
||||
*(uint16_t *)0x0800 = 0x0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -111,33 +138,49 @@ void Serial_::end(void)
|
|||
{
|
||||
}
|
||||
|
||||
int Serial_::available(void)
|
||||
void Serial_::accept(void)
|
||||
{
|
||||
u8 avail = USB_Available(CDC_RX);
|
||||
if (_serialPeek != -1)
|
||||
avail++;
|
||||
return avail;
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
int c = USB_Recv(CDC_RX);
|
||||
int i = (unsigned int)(buffer->head+1) % SERIAL_BUFFER_SIZE;
|
||||
|
||||
// if we should be storing the received character into the location
|
||||
// just before the tail (meaning that the head would advance to the
|
||||
// current location of the tail), we're about to overflow the buffer
|
||||
// and so we don't write the character or advance the head.
|
||||
if (i != buffer->tail) {
|
||||
buffer->buffer[buffer->head] = c;
|
||||
buffer->head = i;
|
||||
}
|
||||
}
|
||||
|
||||
int Serial_::available(void)
|
||||
{
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
return (unsigned int)(SERIAL_BUFFER_SIZE + buffer->head - buffer->tail) % SERIAL_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// peek is nasty
|
||||
int Serial_::peek(void)
|
||||
{
|
||||
if (_serialPeek == -1)
|
||||
_serialPeek = read();
|
||||
return _serialPeek;
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
if (buffer->head == buffer->tail) {
|
||||
return -1;
|
||||
} else {
|
||||
return buffer->buffer[buffer->tail];
|
||||
}
|
||||
}
|
||||
|
||||
int Serial_::read(void)
|
||||
{
|
||||
int c;
|
||||
if (_serialPeek != -1)
|
||||
{
|
||||
c = _serialPeek;
|
||||
_serialPeek = -1;
|
||||
ring_buffer *buffer = &cdc_rx_buffer;
|
||||
// if the head isn't ahead of the tail, we don't have any characters
|
||||
if (buffer->head == buffer->tail) {
|
||||
return -1;
|
||||
} else {
|
||||
c = USB_Recv(CDC_RX);
|
||||
}
|
||||
return c;
|
||||
unsigned char c = buffer->buffer[buffer->tail];
|
||||
buffer->tail = (unsigned int)(buffer->tail + 1) % SERIAL_BUFFER_SIZE;
|
||||
return c;
|
||||
}
|
||||
}
|
||||
|
||||
void Serial_::flush(void)
|
||||
|
@ -169,7 +212,22 @@ size_t Serial_::write(uint8_t c)
|
|||
return 0;
|
||||
}
|
||||
|
||||
// This operator is a convenient way for a sketch to check whether the
|
||||
// port has actually been configured and opened by the host (as opposed
|
||||
// to just being connected to the host). It can be used, for example, in
|
||||
// setup() before printing to ensure that an application on the host is
|
||||
// actually ready to receive and display the data.
|
||||
// We add a short delay before returning to fix a bug observed by Federico
|
||||
// where the port is configured (lineState != 0) but not quite opened.
|
||||
Serial_::operator bool() {
|
||||
bool result = false;
|
||||
if (_usbLineInfo.lineState > 0)
|
||||
result = true;
|
||||
delay(10);
|
||||
return result;
|
||||
}
|
||||
|
||||
Serial_ Serial;
|
||||
|
||||
#endif
|
||||
#endif /* if defined(USBCON) */
|
||||
#endif /* if defined(USBCON) */
|
||||
|
|
|
@ -144,7 +144,6 @@ u8 _hid_protocol = 1;
|
|||
u8 _hid_idle = 1;
|
||||
|
||||
#define WEAK __attribute__ ((weak))
|
||||
#define WEAK
|
||||
|
||||
int WEAK HID_GetInterface(u8* interfaceNum)
|
||||
{
|
||||
|
@ -202,7 +201,15 @@ bool WEAK HID_Setup(Setup& setup)
|
|||
//================================================================================
|
||||
// Mouse
|
||||
|
||||
Mouse_::Mouse_() : _buttons(0)
|
||||
Mouse_::Mouse_(void) : _buttons(0)
|
||||
{
|
||||
}
|
||||
|
||||
void Mouse_::begin(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Mouse_::end(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -245,7 +252,7 @@ void Mouse_::release(uint8_t b)
|
|||
|
||||
bool Mouse_::isPressed(uint8_t b)
|
||||
{
|
||||
if (b & _buttons > 0)
|
||||
if ((b & _buttons) > 0)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -254,7 +261,15 @@ bool Mouse_::isPressed(uint8_t b)
|
|||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
Keyboard_::Keyboard_() : _keyMap(0)
|
||||
Keyboard_::Keyboard_(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Keyboard_::begin(void)
|
||||
{
|
||||
}
|
||||
|
||||
void Keyboard_::end(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -263,11 +278,6 @@ void Keyboard_::sendReport(KeyReport* keys)
|
|||
HID_SendReport(2,keys,sizeof(KeyReport));
|
||||
}
|
||||
|
||||
void Keyboard_::setKeyMap(KeyMap* keyMap)
|
||||
{
|
||||
_keyMap = keyMap;
|
||||
}
|
||||
|
||||
extern
|
||||
const uint8_t _asciimap[128] PROGMEM;
|
||||
|
||||
|
@ -406,41 +416,105 @@ const uint8_t _asciimap[128] =
|
|||
};
|
||||
|
||||
uint8_t USBPutChar(uint8_t c);
|
||||
size_t Keyboard_::write(uint8_t c)
|
||||
|
||||
// press() adds the specified key (printing, non-printing, or modifier)
|
||||
// to the persistent key report and sends the report. Because of the way
|
||||
// USB HID works, the host acts like the key remains pressed until we
|
||||
// call release(), releaseAll(), or otherwise clear the report and resend.
|
||||
size_t Keyboard_::press(uint8_t k)
|
||||
{
|
||||
// Keydown
|
||||
{
|
||||
KeyReport keys = {0};
|
||||
if (_keyMap)
|
||||
_keyMap->charToKey(c,&keys);
|
||||
else
|
||||
{
|
||||
if (c >= 128) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
c = pgm_read_byte(_asciimap + c);
|
||||
if (!c) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
if (c & 0x80)
|
||||
{
|
||||
keys.modifiers |= KEY_MODIFIER_LEFT_SHIFT;
|
||||
c &= 0x7F;
|
||||
}
|
||||
keys.keys[0] = c;
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers |= (1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
if (k & 0x80) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers |= 0x02; // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
sendReport(&keys);
|
||||
}
|
||||
// Keyup
|
||||
{
|
||||
KeyReport keys = {0};
|
||||
sendReport(&keys);
|
||||
|
||||
// Add k to the key report only if it's not already present
|
||||
// and if there is an empty slot.
|
||||
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k &&
|
||||
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
|
||||
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {
|
||||
|
||||
for (i=0; i<6; i++) {
|
||||
if (_keyReport.keys[i] == 0x00) {
|
||||
_keyReport.keys[i] = k;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == 6) {
|
||||
setWriteError();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// release() takes the specified key out of the persistent key report and
|
||||
// sends the report. This tells the OS the key is no longer pressed and that
|
||||
// it shouldn't be repeated any more.
|
||||
size_t Keyboard_::release(uint8_t k)
|
||||
{
|
||||
uint8_t i;
|
||||
if (k >= 136) { // it's a non-printing key (not a modifier)
|
||||
k = k - 136;
|
||||
} else if (k >= 128) { // it's a modifier key
|
||||
_keyReport.modifiers &= ~(1<<(k-128));
|
||||
k = 0;
|
||||
} else { // it's a printing key
|
||||
k = pgm_read_byte(_asciimap + k);
|
||||
if (!k) {
|
||||
return 0;
|
||||
}
|
||||
if (k & 0x80) { // it's a capital letter or other character reached with shift
|
||||
_keyReport.modifiers &= ~(0x02); // the left shift modifier
|
||||
k &= 0x7F;
|
||||
}
|
||||
}
|
||||
|
||||
// Test the key report to see if k is present. Clear it if it exists.
|
||||
// Check all positions in case the key is present more than once (which it shouldn't be)
|
||||
for (i=0; i<6; i++) {
|
||||
if (0 != k && _keyReport.keys[i] == k) {
|
||||
_keyReport.keys[i] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
sendReport(&_keyReport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Keyboard_::releaseAll(void)
|
||||
{
|
||||
_keyReport.keys[0] = 0;
|
||||
_keyReport.keys[1] = 0;
|
||||
_keyReport.keys[2] = 0;
|
||||
_keyReport.keys[3] = 0;
|
||||
_keyReport.keys[4] = 0;
|
||||
_keyReport.keys[5] = 0;
|
||||
_keyReport.modifiers = 0;
|
||||
sendReport(&_keyReport);
|
||||
}
|
||||
|
||||
size_t Keyboard_::write(uint8_t c)
|
||||
{
|
||||
uint8_t p = press(c); // Keydown
|
||||
uint8_t r = release(c); // Keyup
|
||||
return (p); // just return the result of press() since release() almost always returns 1
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* if defined(USBCON) */
|
|
@ -398,6 +398,10 @@ size_t HardwareSerial::write(uint8_t c)
|
|||
return 1;
|
||||
}
|
||||
|
||||
HardwareSerial::operator bool() {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||
|
||||
#if defined(UBRRH) && defined(UBRRL)
|
||||
|
|
|
@ -57,6 +57,7 @@ class HardwareSerial : public Stream
|
|||
virtual void flush(void);
|
||||
virtual size_t write(uint8_t);
|
||||
using Print::write; // pull in write(str) and write(buf, size) from Print
|
||||
operator bool();
|
||||
};
|
||||
|
||||
#if defined(UBRRH) || defined(UBRR0H)
|
||||
|
|
|
@ -244,3 +244,27 @@ size_t Stream::readBytesUntil(char terminator, char *buffer, size_t length)
|
|||
return index; // return number of characters, not including null terminator
|
||||
}
|
||||
|
||||
String Stream::readString()
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
String Stream::readStringUntil(char terminator)
|
||||
{
|
||||
String ret;
|
||||
int c = timedRead();
|
||||
while (c >= 0 && c != terminator)
|
||||
{
|
||||
ret += (char)c;
|
||||
c = timedRead();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -82,6 +82,8 @@ class Stream : public Print
|
|||
// returns the number of characters placed in the buffer (0 means no valid data found)
|
||||
|
||||
// Arduino String functions to be added here
|
||||
String readString();
|
||||
String readStringUntil(char terminator);
|
||||
|
||||
protected:
|
||||
long parseInt(char skipChar); // as above but the given skipChar is ignored
|
||||
|
|
|
@ -9,17 +9,17 @@
|
|||
//================================================================================
|
||||
// USB
|
||||
|
||||
class USB_
|
||||
class USBDevice_
|
||||
{
|
||||
public:
|
||||
USB_();
|
||||
USBDevice_();
|
||||
bool configured();
|
||||
|
||||
void attach();
|
||||
void detach(); // Serial port goes down too...
|
||||
void poll();
|
||||
};
|
||||
extern USB_ USB;
|
||||
extern USBDevice_ USBDevice;
|
||||
|
||||
//================================================================================
|
||||
//================================================================================
|
||||
|
@ -27,15 +27,19 @@ extern USB_ USB;
|
|||
|
||||
class Serial_ : public Stream
|
||||
{
|
||||
private:
|
||||
ring_buffer *_cdc_rx_buffer;
|
||||
public:
|
||||
void begin(uint16_t baud_count);
|
||||
void end(void);
|
||||
|
||||
virtual int available(void);
|
||||
virtual void accept(void);
|
||||
virtual int peek(void);
|
||||
virtual int read(void);
|
||||
virtual void flush(void);
|
||||
virtual size_t write(uint8_t);
|
||||
operator bool();
|
||||
};
|
||||
extern Serial_ Serial;
|
||||
|
||||
|
@ -54,12 +58,14 @@ private:
|
|||
uint8_t _buttons;
|
||||
void buttons(uint8_t b);
|
||||
public:
|
||||
Mouse_();
|
||||
Mouse_(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
void click(uint8_t b = MOUSE_LEFT);
|
||||
void move(signed char x, signed char y, signed char wheel = 0);
|
||||
void press(uint8_t b = MOUSE_LEFT); // press LEFT by default
|
||||
void release(uint8_t b = MOUSE_LEFT); // release LEFT by default
|
||||
bool isPressed(uint8_t b = MOUSE_ALL); // check all buttons by default
|
||||
bool isPressed(uint8_t b = MOUSE_LEFT); // check LEFT by default
|
||||
};
|
||||
extern Mouse_ Mouse;
|
||||
|
||||
|
@ -67,14 +73,42 @@ extern Mouse_ Mouse;
|
|||
//================================================================================
|
||||
// Keyboard
|
||||
|
||||
#define KEY_MODIFIER_LEFT_CTRL 0x01
|
||||
#define KEY_MODIFIER_LEFT_SHIFT 0x02
|
||||
#define KEY_MODIFIER_LEFT_ALT 0x04
|
||||
#define KEY_MODIFIER_LEFT_GUI 0x08
|
||||
#define KEY_MODIFIER_RIGHT_CTRL 0x010
|
||||
#define KEY_MODIFIER_RIGHT_SHIFT 0x020
|
||||
#define KEY_MODIFIER_RIGHT_ALT 0x040
|
||||
#define KEY_MODIFIER_RIGHT_GUI 0x080
|
||||
#define KEY_LEFT_CTRL 0x80
|
||||
#define KEY_LEFT_SHIFT 0x81
|
||||
#define KEY_LEFT_ALT 0x82
|
||||
#define KEY_LEFT_GUI 0x83
|
||||
#define KEY_RIGHT_CTRL 0x84
|
||||
#define KEY_RIGHT_SHIFT 0x85
|
||||
#define KEY_RIGHT_ALT 0x86
|
||||
#define KEY_RIGHT_GUI 0x87
|
||||
|
||||
#define KEY_UP_ARROW 0xDA
|
||||
#define KEY_DOWN_ARROW 0xD9
|
||||
#define KEY_LEFT_ARROW 0xD8
|
||||
#define KEY_RIGHT_ARROW 0xD7
|
||||
#define KEY_BACKSPACE 0xB2
|
||||
#define KEY_TAB 0xB3
|
||||
#define KEY_RETURN 0xB0
|
||||
#define KEY_ESC 0xB1
|
||||
#define KEY_INSERT 0xD1
|
||||
#define KEY_DELETE 0xD4
|
||||
#define KEY_PAGE_UP 0xD3
|
||||
#define KEY_PAGE_DOWN 0xD6
|
||||
#define KEY_HOME 0xD2
|
||||
#define KEY_END 0xD5
|
||||
#define KEY_CAPS_LOCK 0xC1
|
||||
#define KEY_F1 0xC2
|
||||
#define KEY_F2 0xC3
|
||||
#define KEY_F3 0xC4
|
||||
#define KEY_F4 0xC5
|
||||
#define KEY_F5 0xC6
|
||||
#define KEY_F6 0xC7
|
||||
#define KEY_F7 0xC8
|
||||
#define KEY_F8 0xC9
|
||||
#define KEY_F9 0xCA
|
||||
#define KEY_F10 0xCB
|
||||
#define KEY_F11 0xCC
|
||||
#define KEY_F12 0xCD
|
||||
|
||||
// Low level key report: up to 6 keys and shift, ctrl etc at once
|
||||
typedef struct
|
||||
|
@ -84,24 +118,19 @@ typedef struct
|
|||
uint8_t keys[6];
|
||||
} KeyReport;
|
||||
|
||||
// Map a character into a key report
|
||||
// Called from Print to map text to keycodes
|
||||
class KeyMap
|
||||
{
|
||||
public:
|
||||
virtual void charToKey(int c, KeyReport* keyReport) = 0;
|
||||
};
|
||||
|
||||
//
|
||||
class Keyboard_ : public Print
|
||||
{
|
||||
private:
|
||||
KeyMap* _keyMap;
|
||||
KeyReport _keyReport;
|
||||
void sendReport(KeyReport* keys);
|
||||
void setKeyMap(KeyMap* keyMap);
|
||||
public:
|
||||
Keyboard_();
|
||||
virtual size_t write(uint8_t);
|
||||
Keyboard_(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
virtual size_t write(uint8_t k);
|
||||
virtual size_t press(uint8_t k);
|
||||
virtual size_t release(uint8_t k);
|
||||
virtual void releaseAll(void);
|
||||
};
|
||||
extern Keyboard_ Keyboard;
|
||||
|
||||
|
|
|
@ -51,16 +51,20 @@ const u16 STRING_LANGUAGE[2] = {
|
|||
|
||||
const u16 STRING_IPRODUCT[17] = {
|
||||
(3<<8) | (2+2*16),
|
||||
#if USB_PID == USB_PID_LEONARDO
|
||||
#if USB_PID == 0x8036
|
||||
'A','r','d','u','i','n','o',' ','L','e','o','n','a','r','d','o'
|
||||
#elif USB_PID == USB_PID_MICRO
|
||||
'A','r','d','u','i','n','o',' ','M','i','c','r','o',' ',' ',' '
|
||||
#else
|
||||
'U','S','B',' ','I','O',' ','B','o','a','r','d',' ',' ',' ',' '
|
||||
#endif
|
||||
};
|
||||
|
||||
const u16 STRING_IMANUFACTURER[12] = {
|
||||
(3<<8) | (2+2*11),
|
||||
#if USB_VID == 0x2341
|
||||
'A','r','d','u','i','n','o',' ','L','L','C'
|
||||
#else
|
||||
'U','n','k','n','o','w','n',' ',' ',' ',' '
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CDC_ENABLED
|
||||
|
@ -230,7 +234,7 @@ int USB_Recv(u8 ep, void* d, int len)
|
|||
n = len;
|
||||
u8* dst = (u8*)d;
|
||||
while (n--)
|
||||
*dst++ = USBD_Recv8();
|
||||
*dst++ = Recv8();
|
||||
if (len && !FifoByteCount()) // release empty buffer
|
||||
ReleaseRX();
|
||||
|
||||
|
@ -599,6 +603,8 @@ ISR(USB_GEN_vect)
|
|||
{
|
||||
#ifdef CDC_ENABLED
|
||||
USB_Flush(CDC_TX); // Send a tx frame if found
|
||||
while (USB_Available(CDC_RX)) // Handle received bytes (if any)
|
||||
Serial.accept();
|
||||
#endif
|
||||
|
||||
// check whether the one-shot period has elapsed. if so, turn off the LED
|
||||
|
@ -621,13 +627,13 @@ u8 USBConnected()
|
|||
//=======================================================================
|
||||
//=======================================================================
|
||||
|
||||
USB_ USB;
|
||||
USBDevice_ USBDevice;
|
||||
|
||||
USB_::USB_()
|
||||
USBDevice_::USBDevice_()
|
||||
{
|
||||
}
|
||||
|
||||
void USB_::attach()
|
||||
void USBDevice_::attach()
|
||||
{
|
||||
_usbConfiguration = 0;
|
||||
UHWCON = 0x01; // power internal reg
|
||||
|
@ -635,6 +641,12 @@ void USB_::attach()
|
|||
PLLCSR = 0x12; // Need 16 MHz xtal
|
||||
while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
|
||||
;
|
||||
|
||||
// Some tests on specific versions of macosx (10.7.3), reported some
|
||||
// strange behaviuors when the board is reset using the serial
|
||||
// port touch at 1200 bps. This delay fixes this behaviour.
|
||||
delay(1);
|
||||
|
||||
USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock
|
||||
UDIEN = (1<<EORSTE)|(1<<SOFE); // Enable interrupts for EOR (End of Reset) and SOF (start of frame)
|
||||
UDCON = 0; // enable attach resistor
|
||||
|
@ -642,19 +654,19 @@ void USB_::attach()
|
|||
TX_RX_LED_INIT;
|
||||
}
|
||||
|
||||
void USB_::detach()
|
||||
void USBDevice_::detach()
|
||||
{
|
||||
}
|
||||
|
||||
// Check for interrupts
|
||||
// TODO: VBUS detection
|
||||
bool USB_::configured()
|
||||
bool USBDevice_::configured()
|
||||
{
|
||||
return _usbConfiguration;
|
||||
}
|
||||
|
||||
void USB_::poll()
|
||||
void USBDevice_::poll()
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* if defined(USBCON) */
|
||||
#endif /* if defined(USBCON) */
|
||||
|
|
|
@ -60,8 +60,4 @@
|
|||
|
||||
#define IMANUFACTURER 1
|
||||
#define IPRODUCT 2
|
||||
#define USB_PID_LEONARDO 0x0034
|
||||
#define USB_PID_MICRO 0x0035
|
||||
#define USB_VID 0x2341 // arduino LLC vid
|
||||
#define USB_PID ARDUINO_MODEL_USB_PID
|
||||
|
||||
|
|
|
@ -47,7 +47,19 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
|
|||
// Enable the interrupt.
|
||||
|
||||
switch (interruptNum) {
|
||||
#if defined(EICRA) && defined(EICRB) && defined(EIMSK)
|
||||
#if defined(__AVR_ATmega32U4__)
|
||||
// I hate doing this, but the register assignment differs between the 1280/2560
|
||||
// and the 32U4. Since avrlib defines registers PCMSK1 and PCMSK2 that aren't
|
||||
// even present on the 32U4 this is the only way to distinguish between them.
|
||||
case 0:
|
||||
EICRA = (EICRA & ~((1<<ISC00) | (1<<ISC01))) | (mode << ISC00);
|
||||
EIMSK |= (1<<INT0);
|
||||
break;
|
||||
case 1:
|
||||
EICRA = (EICRA & ~((1<<ISC10) | (1<<ISC11))) | (mode << ISC10);
|
||||
EIMSK |= (1<<INT1);
|
||||
break;
|
||||
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
|
||||
case 2:
|
||||
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
|
||||
EIMSK |= (1 << INT0);
|
||||
|
@ -80,7 +92,7 @@ void attachInterrupt(uint8_t interruptNum, void (*userFunc)(void), int mode) {
|
|||
EICRB = (EICRB & ~((1 << ISC70) | (1 << ISC71))) | (mode << ISC70);
|
||||
EIMSK |= (1 << INT7);
|
||||
break;
|
||||
#else
|
||||
#else
|
||||
case 0:
|
||||
#if defined(EICRA) && defined(ISC00) && defined(EIMSK)
|
||||
EICRA = (EICRA & ~((1 << ISC00) | (1 << ISC01))) | (mode << ISC00);
|
||||
|
@ -134,7 +146,14 @@ void detachInterrupt(uint8_t interruptNum) {
|
|||
// to the number of the EIMSK bit to clear, as this isn't true on the
|
||||
// ATmega8. There, INT0 is 6 and INT1 is 7.)
|
||||
switch (interruptNum) {
|
||||
#if defined(EICRA) && defined(EICRB) && defined(EIMSK)
|
||||
#if defined(__AVR_ATmega32U4__)
|
||||
case 0:
|
||||
EIMSK &= ~(1<<INT0);
|
||||
break;
|
||||
case 1:
|
||||
EIMSK &= ~(1<<INT1);
|
||||
break;
|
||||
#elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
|
||||
case 2:
|
||||
EIMSK &= ~(1 << INT0);
|
||||
break;
|
||||
|
@ -196,7 +215,18 @@ void attachInterruptTwi(void (*userFunc)(void) ) {
|
|||
}
|
||||
*/
|
||||
|
||||
#if defined(EICRA) && defined(EICRB)
|
||||
#if defined(__AVR_ATmega32U4__)
|
||||
SIGNAL(INT0_vect) {
|
||||
if(intFunc[EXTERNAL_INT_0])
|
||||
intFunc[EXTERNAL_INT_0]();
|
||||
}
|
||||
|
||||
SIGNAL(INT1_vect) {
|
||||
if(intFunc[EXTERNAL_INT_1])
|
||||
intFunc[EXTERNAL_INT_1]();
|
||||
}
|
||||
|
||||
#elif defined(EICRA) && defined(EICRB)
|
||||
|
||||
SIGNAL(INT0_vect) {
|
||||
if(intFunc[EXTERNAL_INT_2])
|
||||
|
|
|
@ -5,7 +5,7 @@ int main(void)
|
|||
init();
|
||||
|
||||
#if defined(USBCON)
|
||||
USB.attach();
|
||||
USBDevice.attach();
|
||||
#endif
|
||||
|
||||
setup();
|
||||
|
|
|
@ -278,12 +278,21 @@ void init()
|
|||
sbi(TCCR3B, CS30);
|
||||
sbi(TCCR3A, WGM30); // put timer 3 in 8-bit phase correct pwm mode
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(TCCR4A) && defined(TCCR4B) && defined(TCCR4D) /* beginning of timer4 block for 32U4 and similar */
|
||||
sbi(TCCR4B, CS42); // set timer4 prescale factor to 64
|
||||
sbi(TCCR4B, CS41);
|
||||
sbi(TCCR4B, CS40);
|
||||
sbi(TCCR4D, WGM40); // put timer 4 in phase- and frequency-correct PWM mode
|
||||
sbi(TCCR4A, PWM4A); // enable PWM mode for comparator OCR4A
|
||||
sbi(TCCR4C, PWM4D); // enable PWM mode for comparator OCR4D
|
||||
#else /* beginning of timer4 block for ATMEGA1280 and ATMEGA2560 */
|
||||
#if defined(TCCR4B) && defined(CS41) && defined(WGM40)
|
||||
sbi(TCCR4B, CS41); // set timer 4 prescale factor to 64
|
||||
sbi(TCCR4B, CS40);
|
||||
sbi(TCCR4A, WGM40); // put timer 4 in 8-bit phase correct pwm mode
|
||||
#endif
|
||||
#endif /* end timer4 block for ATMEGA1280/2560 and similar */
|
||||
|
||||
#if defined(TCCR5B) && defined(CS51) && defined(WGM50)
|
||||
sbi(TCCR5B, CS51); // set timer 5 prescale factor to 64
|
||||
|
|
|
@ -206,14 +206,17 @@ void analogWrite(uint8_t pin, int val)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#if defined(TCCR4A) && defined(COM4A1)
|
||||
#if defined(TCCR4A)
|
||||
case TIMER4A:
|
||||
// connect pwm to pin on timer 4, channel A
|
||||
//connect pwm to pin on timer 4, channel A
|
||||
sbi(TCCR4A, COM4A1);
|
||||
OCR4A = val; // set pwm duty
|
||||
#if defined(COM4A0) // only used on 32U4
|
||||
cbi(TCCR4A, COM4A0);
|
||||
#endif
|
||||
OCR4A = val; // set pwm duty
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(TCCR4A) && defined(COM4B1)
|
||||
case TIMER4B:
|
||||
// connect pwm to pin on timer 4, channel B
|
||||
|
@ -230,14 +233,18 @@ void analogWrite(uint8_t pin, int val)
|
|||
break;
|
||||
#endif
|
||||
|
||||
#if defined(TCCR4A) && defined(COM4D1)
|
||||
case TIMER4D:
|
||||
#if defined(TCCR4C) && defined(COM4D1)
|
||||
case TIMER4D:
|
||||
// connect pwm to pin on timer 4, channel D
|
||||
sbi(TCCR4A, COM4D1);
|
||||
OCR4D = val; // set pwm duty
|
||||
sbi(TCCR4C, COM4D1);
|
||||
#if defined(COM4D0) // only used on 32U4
|
||||
cbi(TCCR4C, COM4D0);
|
||||
#endif
|
||||
OCR4D = val; // set pwm duty
|
||||
break;
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(TCCR5A) && defined(COM5A1)
|
||||
case TIMER5A:
|
||||
// connect pwm to pin on timer 5, channel A
|
||||
|
@ -272,3 +279,4 @@ void analogWrite(uint8_t pin, int val)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,13 +115,17 @@ static void turnOffPWM(uint8_t timer)
|
|||
|
||||
#if defined(TCCR4A) && defined(COM4A1)
|
||||
case TIMER4A: cbi(TCCR4A, COM4A1); break;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(TCCR4A) && defined(COM4B1)
|
||||
case TIMER4B: cbi(TCCR4A, COM4B1); break;
|
||||
#endif
|
||||
#if defined(TCCR4A) && defined(COM4C1)
|
||||
case TIMER4C: cbi(TCCR4A, COM4C1); break;
|
||||
#endif
|
||||
#endif
|
||||
#if defined(TCCR4C) && defined(COM4D1)
|
||||
case TIMER4D: cbi(TCCR4C, COM4D1); break;
|
||||
#endif
|
||||
|
||||
#if defined(TCCR5A)
|
||||
case TIMER5A: cbi(TCCR5A, COM5A1); break;
|
||||
case TIMER5B: cbi(TCCR5A, COM5B1); break;
|
||||
|
|
|
@ -14,7 +14,11 @@ byte value;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// initialize serial and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
created 18 Dec 2009
|
||||
by David A. Mellis
|
||||
modified 12 March 2012
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
*/
|
||||
|
@ -39,8 +39,13 @@ void setup() {
|
|||
Ethernet.begin(mac, ip, gateway, subnet);
|
||||
// start listening for clients
|
||||
server.begin();
|
||||
// open the serial port
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.print("Chat server address:");
|
||||
Serial.println(Ethernet.localIP());
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* Ethernet shield attached to pins 10, 11, 12, 13
|
||||
|
||||
created 12 April 2011
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
*/
|
||||
|
@ -27,8 +28,13 @@ byte mac[] = {
|
|||
EthernetClient client;
|
||||
|
||||
void setup() {
|
||||
// start the serial library:
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
// this check is only needed on the Leonardo:
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
// start the Ethernet connection:
|
||||
if (Ethernet.begin(mac) == 0) {
|
||||
Serial.println("Failed to configure Ethernet using DHCP");
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
* Ethernet shield attached to pins 10, 11, 12, 13
|
||||
|
||||
created 21 May 2011
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
Based on ChatServer example by David A. Mellis
|
||||
|
||||
|
@ -34,8 +35,14 @@ EthernetServer server(23);
|
|||
boolean gotAMessage = false; // whether or not you got a message from the client yet
|
||||
|
||||
void setup() {
|
||||
// open the serial port
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
// this check is only needed on the Leonardo:
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// start the Ethernet connection:
|
||||
Serial.println("Trying to get an IP address using DHCP");
|
||||
if (Ethernet.begin(mac) == 0) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
created 18 Dec 2009
|
||||
by David A. Mellis
|
||||
modified 12 April 2011
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe, based on work by Adrian McEwen
|
||||
|
||||
*/
|
||||
|
@ -28,8 +28,13 @@ char serverName[] = "www.google.com";
|
|||
EthernetClient client;
|
||||
|
||||
void setup() {
|
||||
// start the serial library:
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// start the Ethernet connection:
|
||||
if (Ethernet.begin(mac) == 0) {
|
||||
Serial.println("Failed to configure Ethernet using DHCP");
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* Ethernet shield attached to pins 10, 11, 12, 13
|
||||
|
||||
created 15 March 2010
|
||||
updated 16 Mar 2012
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe with input from Usman Haque and Joe Saavedra
|
||||
|
||||
http://arduino.cc/en/Tutorial/PachubeClient
|
||||
|
@ -53,8 +53,13 @@ boolean lastConnected = false; // state of the connection last t
|
|||
const unsigned long postingInterval = 10*1000; //delay between updates to Pachube.com
|
||||
|
||||
void setup() {
|
||||
// start serial port:
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// start the Ethernet connection:
|
||||
if (Ethernet.begin(mac) == 0) {
|
||||
Serial.println("Failed to configure Ethernet using DHCP");
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
/*
|
||||
Pachube sensor client with Strings
|
||||
Cosm sensor client with Strings
|
||||
|
||||
This sketch connects an analog sensor to Pachube (http://www.pachube.com)
|
||||
This sketch connects an analog sensor to Cosm (http://www.cosm.com)
|
||||
using a Wiznet Ethernet shield. You can use the Arduino Ethernet shield, or
|
||||
the Adafruit Ethernet shield, either one will work, as long as it's got
|
||||
a Wiznet Ethernet module on board.
|
||||
|
||||
This example has been updated to use version 2.0 of the Pachube.com API.
|
||||
This example has been updated to use version 2.0 of the Cosm.com API.
|
||||
To make it work, create a feed with two datastreams, and give them the IDs
|
||||
sensor1 and sensor2. Or change the code below to match your feed.
|
||||
|
||||
|
@ -18,10 +18,10 @@
|
|||
* Ethernet shield attached to pins 10, 11, 12, 13
|
||||
|
||||
created 15 March 2010
|
||||
updated 16 Mar 2012
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe with input from Usman Haque and Joe Saavedra
|
||||
|
||||
http://arduino.cc/en/Tutorial/PachubeClientString
|
||||
http://arduino.cc/en/Tutorial/CosmClientString
|
||||
This code is in the public domain.
|
||||
|
||||
*/
|
||||
|
@ -30,14 +30,16 @@
|
|||
#include <Ethernet.h>
|
||||
|
||||
|
||||
#define APIKEY "YOUR API KEY GOES HERE" // replace your pachube api key here
|
||||
/#define APIKEY "YOUR API KEY GOES HERE" // replace your Cosm api key here
|
||||
#define FEEDID 00000 // replace your feed ID
|
||||
#define USERAGENT "My Project" // user agent is the project name
|
||||
|
||||
|
||||
// assign a MAC address for the ethernet controller.
|
||||
// fill in your address here:
|
||||
byte mac[] = {
|
||||
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
|
||||
|
||||
// fill in an available IP address on your network here,
|
||||
// for manual configuration:
|
||||
IPAddress ip(10,0,1,20);
|
||||
|
@ -47,16 +49,21 @@ EthernetClient client;
|
|||
|
||||
// if you don't want to use DNS (and reduce your sketch size)
|
||||
// use the numeric IP instead of the name for the server:
|
||||
//IPAddress server(216,52,233,122); // numeric IP for api.pachube.com
|
||||
char server[] = "api.pachube.com"; // name address for pachube API
|
||||
IPAddress server(216,52,233,121); // numeric IP for api.cosm.com
|
||||
//char server[] = "api.cosm.com"; // name address for Cosm API
|
||||
|
||||
unsigned long lastConnectionTime = 0; // last time you connected to the server, in milliseconds
|
||||
boolean lastConnected = false; // state of the connection last time through the main loop
|
||||
const unsigned long postingInterval = 10*1000; //delay between updates to Pachube.com
|
||||
const unsigned long postingInterval = 10*1000; //delay between updates to Cosm.com
|
||||
|
||||
void setup() {
|
||||
// start serial port:
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// give the ethernet module time to boot up:
|
||||
delay(1000);
|
||||
// start the Ethernet connection:
|
||||
|
@ -76,7 +83,7 @@ void loop() {
|
|||
dataString += sensorReading;
|
||||
|
||||
// you can append multiple readings to this String if your
|
||||
// pachube feed is set up to handle multiple values:
|
||||
// Cosm feed is set up to handle multiple values:
|
||||
int otherSensorReading = analogRead(A1);
|
||||
dataString += "\nsensor2,";
|
||||
dataString += otherSensorReading;
|
||||
|
@ -116,8 +123,8 @@ void sendData(String thisData) {
|
|||
client.print("PUT /v2/feeds/");
|
||||
client.print(FEEDID);
|
||||
client.println(".csv HTTP/1.1");
|
||||
client.println("Host: api.pachube.com");
|
||||
client.print("X-PachubeApiKey: ");
|
||||
client.println("Host: api.cosm.com");
|
||||
client.print("X-CosmApiKey: ");
|
||||
client.println(APIKEY);
|
||||
client.print("User-Agent: ");
|
||||
client.println(USERAGENT);
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
* Ethernet shield attached to pins 10, 11, 12, 13
|
||||
|
||||
created 14 Sep 2010
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
*/
|
||||
|
@ -38,8 +39,13 @@ EthernetClient client;
|
|||
void setup() {
|
||||
// start the Ethernet connection:
|
||||
Ethernet.begin(mac, ip);
|
||||
// start the serial library:
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// give the Ethernet shield a second to initialize:
|
||||
delay(1000);
|
||||
Serial.println("connecting...");
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* Ethernet shield attached to pins 10, 11, 12, 13
|
||||
|
||||
created 21 May 2011
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This code is in the public domain.
|
||||
|
@ -51,8 +52,13 @@ void setup() {
|
|||
currentLine.reserve(256);
|
||||
tweet.reserve(150);
|
||||
|
||||
// initialize serial:
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// attempt a DHCP connection:
|
||||
Serial.println("Attempting to get an IP address using DHCP:");
|
||||
if (!Ethernet.begin(mac)) {
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
created 4 Sep 2010
|
||||
by Michael Margolis
|
||||
modified 17 Sep 2010
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This code is in the public domain.
|
||||
|
@ -38,7 +38,12 @@ EthernetUDP Udp;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// start Ethernet and UDP
|
||||
if (Ethernet.begin(mac) == 0) {
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
* Ethernet shield attached to pins 10, 11, 12, 13
|
||||
|
||||
created 18 Dec 2009
|
||||
modified 9 Apr 2012
|
||||
by David A. Mellis
|
||||
|
||||
*/
|
||||
|
@ -26,8 +27,12 @@ IPAddress server(173,194,33,104); // Google
|
|||
EthernetClient client;
|
||||
|
||||
void setup() {
|
||||
// start the serial library:
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
// start the Ethernet connection:
|
||||
if (Ethernet.begin(mac) == 0) {
|
||||
Serial.println("Failed to configure Ethernet using DHCP");
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
created 18 Dec 2009
|
||||
by David A. Mellis
|
||||
modified 20 Mar 2012
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
*/
|
||||
|
@ -30,7 +30,13 @@ IPAddress ip(192,168,1, 177);
|
|||
EthernetServer server(80);
|
||||
|
||||
void setup() {
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// start the Ethernet connection and the server:
|
||||
Ethernet.begin(mac, ip);
|
||||
server.begin();
|
||||
|
|
|
@ -327,7 +327,11 @@ private:
|
|||
inline static void initSS() { DDRB |= _BV(4); };
|
||||
inline static void setSS() { PORTB &= ~_BV(4); };
|
||||
inline static void resetSS() { PORTB |= _BV(4); };
|
||||
#elif defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
inline static void initSS() { DDRB |= _BV(6); };
|
||||
inline static void setSS() { PORTB &= ~_BV(6); };
|
||||
inline static void resetSS() { PORTB |= _BV(6); };
|
||||
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB162__)
|
||||
inline static void initSS() { DDRB |= _BV(0); };
|
||||
inline static void setSS() { PORTB &= ~_BV(0); };
|
||||
inline static void resetSS() { PORTB |= _BV(0); };
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalAutoscroll
|
||||
|
||||
*/
|
||||
|
||||
// include the library code:
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalBlink
|
||||
|
||||
*/
|
||||
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalCursor
|
||||
|
||||
*/
|
||||
|
||||
// include the library code:
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalDisplay
|
||||
|
||||
*/
|
||||
|
||||
// include the library code:
|
||||
|
|
|
@ -33,7 +33,8 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalScroll
|
||||
|
||||
*/
|
||||
|
||||
// include the library code:
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalSerial
|
||||
*/
|
||||
|
||||
// include the library code:
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalTextDirection
|
||||
|
||||
*/
|
||||
|
||||
|
@ -49,7 +49,6 @@ void setup() {
|
|||
lcd.begin(16, 2);
|
||||
// turn on the cursor:
|
||||
lcd.cursor();
|
||||
Serial.begin(9600);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
|
@ -32,7 +32,8 @@
|
|||
|
||||
This example code is in the public domain.
|
||||
|
||||
http://www.arduino.cc/en/Tutorial/LiquidCrystal
|
||||
http://arduino.cc/en/Tutorial/LiquidCrystalSetCursor
|
||||
|
||||
*/
|
||||
|
||||
// include the library code:
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
created 28 Mar 2011
|
||||
by Limor Fried
|
||||
modified 16 Mar 2011
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
*/
|
||||
// include the SD library:
|
||||
|
@ -35,7 +35,13 @@ const int chipSelect = 4;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.print("\nInitializing SD card...");
|
||||
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
|
||||
// Note that even if it's not used as the CS pin, the hardware SS pin
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
** CS - pin 4
|
||||
|
||||
created 24 Nov 2010
|
||||
updated 2 Dec 2010
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
@ -30,7 +30,13 @@ const int chipSelect = 4;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.print("Initializing SD card...");
|
||||
// make sure that the default chip select pin is set to
|
||||
// output, even if you don't use it:
|
||||
|
|
|
@ -12,6 +12,9 @@
|
|||
** CS - pin 4
|
||||
|
||||
created 22 December 2010
|
||||
by Limor Fried
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
||||
|
@ -27,7 +30,13 @@ const int chipSelect = 4;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.print("Initializing SD card...");
|
||||
// make sure that the default chip select pin is set to
|
||||
// output, even if you don't use it:
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
created Nov 2010
|
||||
by David A. Mellis
|
||||
updated 2 Dec 2010
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
@ -23,7 +23,13 @@ File myFile;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.print("Initializing SD card...");
|
||||
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
|
||||
// Note that even if it's not used as the CS pin, the hardware SS pin
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
created Nov 2010
|
||||
by David A. Mellis
|
||||
updated 2 Dec 2010
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
@ -24,7 +24,13 @@ File myFile;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.print("Initializing SD card...");
|
||||
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
|
||||
// Note that even if it's not used as the CS pin, the hardware SS pin
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
created Nov 2010
|
||||
by David A. Mellis
|
||||
updated 2 Dec 2010
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
|
||||
This example code is in the public domain.
|
||||
|
@ -23,7 +23,13 @@ File root;
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.print("Initializing SD card...");
|
||||
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
|
||||
// Note that even if it's not used as the CS pin, the hardware SS pin
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
* TX is digital pin 3 (connect to RX of other device)
|
||||
|
||||
created back in the mists of time
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
based on Mikal Hart's example
|
||||
|
||||
|
@ -21,7 +22,13 @@ SoftwareSerial mySerial(2, 3); // RX, TX
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(57600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
Serial.println("Goodnight moon!");
|
||||
|
||||
// set the data rate for the SoftwareSerial port
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* Second serial device's TX attached to digital pin 4, RX to pin 5
|
||||
|
||||
created 18 Apr. 2011
|
||||
modified 9 Apr 2012
|
||||
by Tom Igoe
|
||||
based on Mikal Hart's twoPortRXExample
|
||||
|
||||
|
@ -33,8 +34,12 @@ SoftwareSerial portTwo(4, 5);
|
|||
|
||||
void setup()
|
||||
{
|
||||
// Start the hardware serial port
|
||||
// Open serial communications and wait for port to open:
|
||||
Serial.begin(9600);
|
||||
while (!Serial) {
|
||||
; // wait for serial port to connect. Needed for Leonardo only
|
||||
}
|
||||
|
||||
|
||||
// Start each software serial port
|
||||
portOne.begin(9600);
|
||||
|
|
|
@ -26,11 +26,10 @@ const int stepsPerRevolution = 200; // change this to fit the number of steps p
|
|||
// initialize the stepper library on pins 8 through 11:
|
||||
Stepper myStepper(stepsPerRevolution, 8,9,10,11);
|
||||
|
||||
int stepCount = 0; // number of steps the motor has taken
|
||||
int stepCount = 0; // number of steps the motor has taken
|
||||
|
||||
void setup() {
|
||||
// initialize the serial port:
|
||||
Serial.begin(9600);
|
||||
// nothing to do inside the setup
|
||||
}
|
||||
|
||||
void loop() {
|
||||
|
|
|
@ -6,12 +6,12 @@ name=Arduino
|
|||
# Default "compiler.path" is correct, change only if you want to overidde the initial value
|
||||
#compiler.path={ide.path}/tools/avr/bin/..
|
||||
compiler.c.cmd=avr-gcc
|
||||
compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections
|
||||
compiler.c.flags=-c -g -Os -w -ffunction-sections -fdata-sections -MMD
|
||||
compiler.c.elf.flags=-Os -Wl,--gc-sections
|
||||
compiler.c.elf.cmd=avr-gcc
|
||||
compiler.S.flags=-c -g -assembler-with-cpp
|
||||
compiler.cpp.cmd=avr-g++
|
||||
compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections
|
||||
compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -MMD
|
||||
compiler.ar.cmd=avr-ar
|
||||
compiler.ar.flags=rcs
|
||||
compiler.objcopy.cmd=avr-objcopy
|
||||
|
@ -25,10 +25,10 @@ compiler.size.cmd=avr-size
|
|||
# --------------------
|
||||
|
||||
## Compile c files
|
||||
recipe.c.o.pattern={compiler.path}{compiler.c.cmd} {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {includes} {source_file} -o {object_file}
|
||||
recipe.c.o.pattern={compiler.path}{compiler.c.cmd} {compiler.c.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {includes} {source_file} -o {object_file}
|
||||
|
||||
## Compile c++ files
|
||||
recipe.cpp.o.pattern={compiler.path}{compiler.cpp.cmd} {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {includes} {source_file} -o {object_file}
|
||||
recipe.cpp.o.pattern={compiler.path}{compiler.cpp.cmd} {compiler.cpp.flags} -mmcu={build.mcu} -DF_CPU={build.f_cpu} -D{software}={runtime.ide.version} {build.extra_flags} {includes} {source_file} -o {object_file}
|
||||
|
||||
## Create archives
|
||||
recipe.ar.pattern={compiler.path}{compiler.ar.cmd} {compiler.ar.flags} {build.path}/{archive_file} {object_file}
|
||||
|
|
|
@ -27,8 +27,6 @@
|
|||
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
#define ARDUINO_MODEL_USB_PID 0x0034
|
||||
|
||||
#define TX_RX_LED_INIT DDRD |= (1<<5), DDRB |= (1<<0)
|
||||
#define TXLED0 PORTD |= (1<<5)
|
||||
#define TXLED1 PORTD &= ~(1<<5)
|
||||
|
@ -59,6 +57,11 @@ static const uint8_t A9 = 27; // D9
|
|||
static const uint8_t A10 = 28; // D10
|
||||
static const uint8_t A11 = 29; // D12
|
||||
|
||||
#define digitalPinToPCICR(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCICR) : ((uint8_t *)0))
|
||||
#define digitalPinToPCICRbit(p) 0
|
||||
#define digitalPinToPCMSK(p) ((((p) >= 8 && (p) <= 11) || ((p) >= 14 && (p) <= 17) || ((p) >= A8 && (p) <= A10)) ? (&PCMSK0) : ((uint8_t *)0))
|
||||
#define digitalPinToPCMSKbit(p) ( ((p) >= 8 && (p) <= 11) ? (p) - 4 : ((p) == 14 ? 3 : ((p) == 15 ? 1 : ((p) == 16 ? 2 : ((p) == 17 ? 0 : (p - A8 + 4))))))
|
||||
|
||||
// __AVR_ATmega32U4__ has an unusual mapping of pins to channels
|
||||
extern const uint8_t PROGMEM analog_pin_to_channel_PGM[];
|
||||
#define analogPinToChannel(P) ( pgm_read_byte( analog_pin_to_channel_PGM + (P) ) )
|
||||
|
@ -212,7 +215,7 @@ const uint8_t PROGMEM digital_pin_to_bit_mask_PGM[30] = {
|
|||
_BV(6), // D29 / D12 - A11 - PD6
|
||||
};
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_timer_PGM[18] = {
|
||||
const uint8_t PROGMEM digital_pin_to_timer_PGM[16] = {
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
NOT_ON_TIMER,
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
pins_arduino.h - Pin definition functions for Arduino
|
||||
Part of Arduino - http://www.arduino.cc/
|
||||
|
||||
Copyright (c) 2007 David A. Mellis
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General
|
||||
Public License along with this library; if not, write to the
|
||||
Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
Boston, MA 02111-1307 USA
|
||||
|
||||
$Id: wiring.h 249 2007-02-03 16:52:51Z mellis $
|
||||
*/
|
||||
|
||||
#include "../leonardo/pins_arduino.h"
|
||||
#undef ARDUINO_MODEL_USB_PID
|
||||
#define ARDUINO_MODEL_USB_PID 0x0035
|
Loading…
Reference in New Issue