From bf2062658513e6c660c103a9b3c43aaacb74d969 Mon Sep 17 00:00:00 2001 From: tmk Date: Thu, 14 Sep 2017 23:03:28 +0900 Subject: [PATCH] onekey: Add settings for Xtal-less V-USB --- keyboard/onekey/Makefile.vusb | 8 +++-- keyboard/onekey/VUSB.md | 63 +++++++++++++++++++++++++++++++++++ keyboard/onekey/usbconfig.h | 12 ++++--- keyboard/onekey/vusb_osccal.c | 37 ++++++++++++++++++++ 4 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 keyboard/onekey/VUSB.md create mode 100644 keyboard/onekey/vusb_osccal.c diff --git a/keyboard/onekey/Makefile.vusb b/keyboard/onekey/Makefile.vusb index 1af3ebbd..06840666 100644 --- a/keyboard/onekey/Makefile.vusb +++ b/keyboard/onekey/Makefile.vusb @@ -10,6 +10,7 @@ TARGET_DIR = . # keyboard dependent files SRC = keymap.c \ onekey.c \ + vusb_osccal.c \ led.c CONFIG_H = config.h @@ -27,7 +28,9 @@ MCU = attiny85 # so your program will run at the correct speed. You should also set this # variable to same clock speed. The _delay_ms() macro uses this, and many # examples use this variable to calculate timings. Do not add a "UL" here. -F_CPU = 12000000 +#F_CPU = 12000000 +# Xtal-less internal RC oscillator +F_CPU = 16500000 # Build Options @@ -47,7 +50,8 @@ OPT_DEFS += -DNO_ACTION_MACRO #---------------- Programming Options -------------------------- AVRDUDE = avrdude # Type: avrdude -c ? to get a full listing. -AVRDUDE_PROGRAMMER = usbasp +#AVRDUDE_PROGRAMMER = usbasp +AVRDUDE_PROGRAMMER = avrispmkii AVRDUDE_PORT = AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex #AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep diff --git a/keyboard/onekey/VUSB.md b/keyboard/onekey/VUSB.md new file mode 100644 index 00000000..0cf18c0f --- /dev/null +++ b/keyboard/onekey/VUSB.md @@ -0,0 +1,63 @@ +TMK with Xtal-less V-USB +======================== + +TMK onekey works on ATtiny85. + + $ make -f Makefile.vusb + + ... + + Size after: + text data bss dec hex filename + 5518 14 254 5786 169a onekey_vusb.elf + + -------- end -------- + + +https://i.imgur.com/sNa302J.jpg + + +Program with AVRISPmkII +----------------------- +D- and D+ lines are need to be disconnected when programed. + + $ avrdude -p attiny85 -c avrispmkii -U flash:w:onekey_vusb.hex + + +Xtal-less internal RC +--------------------- +http://codeandlife.com/2012/02/22/v-usb-with-attiny45-attiny85-without-a-crystal/ + +Configure fuses for PLL, internal RC and BOD(Brown out detection). + + $ avrdude -c avrispmkii -p attiny85 -U lfuse:w:0xe1:m -U hfuse:w:0xdd:m + +Set 16.5MHz to F_CPU in Makefile + + F_CPU = 16500000 + +Add settings for calibration in usbconfig.h + + diff --git a/keyboard/onekey/usbconfig.h b/keyboard/onekey/usbconfig.h + index e9b4f98..01e5aa6 100644 + --- a/keyboard/onekey/usbconfig.h + +++ b/keyboard/onekey/usbconfig.h + @@ -161,7 +161,11 @@ section at the end of this file). + * proceed, do a return after doing your things. One possible application + * (besides debugging) is to flash a status LED on each packet. + */ + -/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ + +#define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} + +/* http://codeandlife.com/2012/02/22/v-usb-with-attiny45-attiny85-without-a-crystal/ */ + +#ifndef __ASSEMBLER__ + +extern void hadUsbReset(void); // define the function for usbdrv.c + +#endif + /* This macro is a hook if you need to know when an USB RESET occurs. It has + * one parameter which distinguishes between the start of RESET state and its + * end. + @@ -202,7 +206,7 @@ section at the end of this file). + * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable + * for each control- and out-endpoint to check for duplicate packets. + */ + -#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 + +#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 1 diff --git a/keyboard/onekey/usbconfig.h b/keyboard/onekey/usbconfig.h index e9b4f982..01e5aa6d 100644 --- a/keyboard/onekey/usbconfig.h +++ b/keyboard/onekey/usbconfig.h @@ -161,7 +161,11 @@ section at the end of this file). * proceed, do a return after doing your things. One possible application * (besides debugging) is to flash a status LED on each packet. */ -/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */ +#define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} +/* http://codeandlife.com/2012/02/22/v-usb-with-attiny45-attiny85-without-a-crystal/ */ +#ifndef __ASSEMBLER__ +extern void hadUsbReset(void); // define the function for usbdrv.c +#endif /* This macro is a hook if you need to know when an USB RESET occurs. It has * one parameter which distinguishes between the start of RESET state and its * end. @@ -202,7 +206,7 @@ section at the end of this file). * usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable * for each control- and out-endpoint to check for duplicate packets. */ -#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0 +#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 1 /* define this macro to 1 if you want the function usbMeasureFrameLength() * compiled in. This function can be used to calibrate the AVR's RC oscillator. */ @@ -250,8 +254,8 @@ section at the end of this file). * obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for * details. */ -#define USB_CFG_DEVICE_NAME 'P', 'S', '/', '2', ' ', 'k', 'e', 'y', 'b', 'o', 'a', 'r', 'd', ' ', 'c', 'o', 'n', 'v', 'e', 'r', 't', 'e', 'r' -#define USB_CFG_DEVICE_NAME_LEN 23 +#define USB_CFG_DEVICE_NAME 'O', 'n', 'e', 'k', 'e', 'y' +#define USB_CFG_DEVICE_NAME_LEN 6 /* Same as above for the device name. If you don't want a device name, undefine * the macros. See the file USB-IDs-for-free.txt before you assign a name if * you use a shared VID/PID. diff --git a/keyboard/onekey/vusb_osccal.c b/keyboard/onekey/vusb_osccal.c new file mode 100644 index 00000000..26fde1f8 --- /dev/null +++ b/keyboard/onekey/vusb_osccal.c @@ -0,0 +1,37 @@ +// V-USB with ATtiny45 / ATtiny85 without a crystal +// http://codeandlife.com/2012/02/22/v-usb-with-attiny45-attiny85-without-a-crystal/ +#include +#include + + +#define abs(x) ((x) > 0 ? (x) : (-x)) + +// Called by V-USB after device reset +void hadUsbReset() { + int frameLength, targetLength = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5); + int bestDeviation = 9999; + uint8_t trialCal, bestCal, step, region; + + // do a binary search in regions 0-127 and 128-255 to get optimum OSCCAL + for(region = 0; region <= 1; region++) { + frameLength = 0; + trialCal = (region == 0) ? 0 : 128; + + for(step = 64; step > 0; step >>= 1) { + if(frameLength < targetLength) // true for initial iteration + trialCal += step; // frequency too low + else + trialCal -= step; // frequency too high + + OSCCAL = trialCal; + frameLength = usbMeasureFrameLength(); + + if(abs(frameLength-targetLength) < bestDeviation) { + bestCal = trialCal; // new optimum found + bestDeviation = abs(frameLength -targetLength); + } + } + } + + OSCCAL = bestCal; +} -- 2.46.2