flash: all
$(AVRDUDE) -U flash:w:main.hex:i
-
# Fuse high byte:
# 0xdd = 1 1 0 1 1 1 0 1
# ^ ^ ^ ^ ^ \-+-/
$(COMPILE) -o main.bin $(OBJECTS)
main.hex: main.bin
- @rm -f main.hex main.eep.hex
+ @rm -f main.hex
@avr-objcopy -j .text -j .data -O ihex main.bin main.hex
@$(SHELL) checksize main.bin 4096 256
# do the checksize script as our last action to allow successful compilation
# on Windows with WinAVR where the Unix commands will fail.
+serial: main.bin
+ @avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" \
+ --change-section-lma .eeprom=0 -O ihex main.bin main.eep.hex
+ @python setserial.py main.eep.hex
+
+flash_serial:
+ $(AVRDUDE) -U eeprom:w:main.eep.hex:i
+
disasm: main.bin
avr-objdump -d main.bin
#include "descriptor.c"
-/* one byte reserved for oscillator calibration */
-#define CONFIG_TOP ((uint8_t *)1)
+/* one byte reserved for oscillator calibration and 6 bytes for serial number */
+#define CONFIG_TOP ((uint8_t *)1+6)
#define CONFIG_LEN 128
+char EEMEM ee_serial[USB_CFG_SERIAL_NUMBER_LEN] = { USB_CFG_SERIAL_NUMBER };
+uint8_t EEMEM ee_calibration = 0xff;
+
+/* Declare space in RAM for the default serial number. This should
+ * be overwrittern from eeprom before USB gets initialized
+ */
+int usbDescriptorStringSerialNumber[USB_CFG_SERIAL_NUMBER_LEN + 2] = {
+ USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
+ USB_CFG_SERIAL_NUMBER,
+ 0
+};
+
enum {
Modifier_NumLock = 1,
Modifier_CapsLock = 2,
uchar state;
uchar LED_state;
uchar idle_rate;
+ uint8_t calibrationValue;
keyboard_report_t keyboard_report;
} Global_t;
-static Global_t Global = {0, Led_Slow, 0, 0, 0xff, 0, {0, 0, {0, 0, 0, 0, 0, 0}}};
+static Global_t Global = {
+ 0, Led_Slow, 0, 0, 0xff, 0, 0xff, {0, 0, {0, 0, 0, 0, 0, 0}}
+};
/* called when the PC sets the LED state, we can set
* set the caps lock led indicator
void
on_usb_reset(void)
{
- calibrateOscillator();
+ calibrateOscillator();
#if F_CPU==16500000
- eeprom_write_byte(0, OSCCAL); /* store the calibrated value in EEPROM */
+ /* store the calibrated value in EEPROM only if changed */
+ if (Global.calibrationValue != OSCCAL) {
+ eeprom_write_byte(&ee_calibration, OSCCAL);
+ Global.calibrationValue = OSCCAL;
+ }
#endif
}
+static void
+load_serial_eeprom()
+{
+ uchar serial[USB_CFG_SERIAL_NUMBER_LEN + 2];
+ serial[0] = 0xff;
+ eeprom_read_block(&serial, &ee_serial, USB_CFG_SERIAL_NUMBER_LEN);
+ if (serial[0] != 0xff) {
+ int n;
+ for (n = 0; n < USB_CFG_SERIAL_NUMBER_LEN; ++n) {
+ usbDescriptorStringSerialNumber[1 + n] = (int)(serial[n]);
+ }
+ }
+}
+
int __attribute__((noreturn))
main(void)
{
#if F_CPU==16500000
- uint8_t calibrationValue;
- calibrationValue = eeprom_read_byte(0); /* calibration value from last time */
- if(calibrationValue != 0xff){
- OSCCAL = calibrationValue;
- }
+ /* read the calibration value from last time */
+ Global.calibrationValue = eeprom_read_byte(&ee_calibration);
+ if (Global.calibrationValue != 0xff){
+ OSCCAL = Global.calibrationValue;
+ }
#endif
- wdt_enable(WDTO_1S); /* setup a 1 second watchdog */
- odDebugInit();
- appInit(); /* app specific initialization */
- usbInit(); /* usb library initialization */
- usbDeviceDisconnect(); /* enforce re-enumeration */
- _delay_ms(300);
- usbDeviceConnect();
+ load_serial_eeprom(); /* load the serial number from eeprom[1..7] */
+ wdt_enable(WDTO_1S); /* setup a 1 second watchdog */
+ odDebugInit();
+ appInit(); /* app specific initialization */
+ usbInit(); /* usb library initialization */
+ usbDeviceDisconnect(); /* enforce re-enumeration */
+ _delay_ms(400);
+ usbDeviceConnect();
PORTB &= ~(_BV(PB1)); /* toggle the LED */
- sei();
- for(;;) {
- wdt_reset(); /* reset the watchdog timer */
- usbPoll();
- appPoll();
- }
+ sei();
+ for(;;) {
+ wdt_reset(); /* reset the watchdog timer */
+ usbPoll();
+ appPoll();
+ }
}
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
* you use a shared VID/PID.
*/
-#define USB_CFG_SERIAL_NUMBER 'K', '0', '0', '0', '0', '1'
+
+#define USB_CFG_SERIAL_NUMBER 'Z', '0', '0', '0', '0', '0'
#define USB_CFG_SERIAL_NUMBER_LEN 6
+
/* Same as above for the serial number. If you don't want a serial number,
* undefine the macros.
* It may be useful to provide the serial number through other means than at
#define USB_CFG_DESCR_PROPS_STRING_0 0
#define USB_CFG_DESCR_PROPS_STRING_VENDOR 0
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT 0
-#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER 0
+#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER (USB_PROP_IS_RAM | (2 * USB_CFG_SERIAL_NUMBER_LEN + 2))
#define USB_CFG_DESCR_PROPS_HID 0
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0