From 37ee52ee4bbdf5913c1f8bc7721d14e81cc8077d Mon Sep 17 00:00:00 2001 From: William Toohey Date: Wed, 26 Oct 2016 19:52:03 +1000 Subject: [PATCH] V2 stuff done, initial LED support --- Firmware/Keyboard/Descriptors.c | 30 ------- Firmware/Keyboard/Keyboard.c | 101 ++++++------------------ Firmware/Keyboard/LED.c | 135 ++++++++++++++++++++++++++++++++ Firmware/Keyboard/LED.h | 13 +++ Firmware/Keyboard/makefile | 2 +- Hardware/other_bom.csv | 4 +- 6 files changed, 176 insertions(+), 109 deletions(-) create mode 100644 Firmware/Keyboard/LED.c create mode 100644 Firmware/Keyboard/LED.h diff --git a/Firmware/Keyboard/Descriptors.c b/Firmware/Keyboard/Descriptors.c index 5a63154..315e5ad 100644 --- a/Firmware/Keyboard/Descriptors.c +++ b/Firmware/Keyboard/Descriptors.c @@ -1,33 +1,3 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 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 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, 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 diff --git a/Firmware/Keyboard/Keyboard.c b/Firmware/Keyboard/Keyboard.c index 84d2bc9..e7e78a6 100644 --- a/Firmware/Keyboard/Keyboard.c +++ b/Firmware/Keyboard/Keyboard.c @@ -1,46 +1,9 @@ -/* - LUFA Library - Copyright (C) Dean Camera, 2014. - - dean [at] fourwalledcubicle [dot] com - www.lufa-lib.org -*/ - -/* - Copyright 2014 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 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, 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 Keyboard demo. This file contains the main tasks of - * the demo and is responsible for the initial application hardware configuration. - */ - #include "Keyboard.h" #include "Config.h" #include "Encoder.h" +#include "LED.h" #define READ_SWITCH(x) (!(*pins[switches[x].switchPort] & _BV(switches[x].switchPin))) -#define SET_LED(x) (*ports[switches[x].lightPort] |= _BV(switches[x].lightPin)) -#define CLEAR_LED(x) (*ports[switches[x].lightPort] &= ~_BV(switches[x].lightPin)) typedef struct { @@ -125,21 +88,19 @@ static volatile uint8_t *ddrs[] = {&DDRB, &DDRC, &DDRD}; typedef struct { port_t switchPort; uint8_t switchPin; - port_t lightPort; - uint8_t lightPin; uint8_t state; uint8_t lastReport; uint8_t debounce; } switch_t; static switch_t switches[SWITCH_COUNT] = { - {C, 7, C, 6}, // A - {B, 4, B, 5}, // B - {B, 2, B, 3}, // C - {D, 6, D, 7}, // D - {B, 6, B, 7}, // FX L - {B, 0, B, 1}, // FX R - {D, 5, D, 4} // START + {B, 1}, // A + {D, 7}, // B + {D, 5}, // C + {D, 4}, // D + {B, 0}, // FX L + {D, 6}, // FX R + {C, 2} // START }; static uint8_t switchesChanged = 1; @@ -174,13 +135,7 @@ void update_switches(void) { uint8_t i, newState; for(i = 0; i < SWITCH_COUNT; i++) { - // The I2C data starts at the 6th bit and goes down newState = READ_SWITCH(i); - if(newState) { - SET_LED(i); - } else { - CLEAR_LED(i); - } if(!switches[i].debounce && newState != switches[i].lastReport) { switches[i].state = newState; switches[i].debounce = sdvxConfig.debounce; @@ -189,32 +144,25 @@ void update_switches(void) { } } -/** Main program entry point. This routine contains the overall program flow, including initial - * setup of all components and the main program loop. - */ int main(void) { GlobalInterruptDisable(); - uint8_t i; - InitConfig(); SetupHardware(); - - // FX_L held while plugging in - if(READ_SWITCH(4)) { - RebootToBootloader(); - } - - // Blink to show we're not in bootloader - for(i = 0; i < SWITCH_COUNT; i++) { - *ports[switches[i].lightPort] |= _BV(switches[i].lightPin); - _delay_ms(50); - *ports[switches[i].lightPort] &= ~_BV(switches[i].lightPin); - } GlobalInterruptEnable(); + + // Blink to show we're not in bootloader + for(uint8_t i = 0; i < LED_COUNT; i++) { + led_set(i, 32, 0, 0); + _delay_ms(1000); + led_set(i, 0, 0, 0); + } + + // Not in SetupHardware so we don't time out + USB_Init(); for (;;) { @@ -225,7 +173,7 @@ int main(void) } } -/** Configures the board hardware and chip peripherals for the demo's functionality. */ +/** Configures the board hardware and chip peripherals */ void SetupHardware() { uint8_t i; @@ -242,15 +190,16 @@ void SetupHardware() *ddrs[switches[i].switchPort] &= ~_BV(switches[i].switchPin); // with internal pullups *ports[switches[i].switchPort] |= _BV(switches[i].switchPin); - // setup LEDs to be outputs - *ddrs[switches[i].lightPort] |= _BV(switches[i].lightPin); - // off by default - *ports[switches[i].lightPort] &= ~_BV(switches[i].lightPin); + } + + // FX_L held while plugging in + if(READ_SWITCH(4)) { + RebootToBootloader(); } /* Hardware Initialization */ encoder_init(); - USB_Init(); + led_init(); } /** HID class driver callback function for the creation of HID reports to the host. diff --git a/Firmware/Keyboard/LED.c b/Firmware/Keyboard/LED.c new file mode 100644 index 0000000..097c4c6 --- /dev/null +++ b/Firmware/Keyboard/LED.c @@ -0,0 +1,135 @@ +#include "LED.h" +//#include + +#define BRIGHTNESS_LEVELS 64 +#define GND_COUNT 4 +// RGB * 2 +#define LED_PINS 6 + +// LED gnd 0-3 are on PC7-4 +#define GND_PORT PORTC +#define GND_DDR DDRC +#define GND_MASK 0xF0 +#define GND_OFFSET 4 // in bits + +// LED power BGR BGR PB2-7 +#define LED_PORT PORTB +#define LED_DDR DDRB +#define LED_MASK (0b111111 << 2) + +#define R 2 +#define G 1 +#define B 0 + +//typedef struct { +// uint8_t gnd; +// uint8_t brightness; +//} matrix_t; + +// Arranged left to right, bottom to top +static volatile uint8_t leds[LED_COUNT][3]; +//volatile matrix_t current; +volatile uint8_t currentGnd; +// This saves us doing a costly dynamic _BV() +volatile uint8_t currentGndMask; +volatile uint8_t currentBright; + +void led_init() { + // all GNDs low level for high impedence or gnd + GND_PORT &= ~GND_MASK; + // all GNDs input + GND_DDR &= ~GND_MASK; + + // Because we roll over on each loop and want to start at 0 + currentBright = BRIGHTNESS_LEVELS - 1; + currentGnd = GND_COUNT - 1; + currentGndMask = _BV(GND_OFFSET); + + // all LEDs off + LED_PORT &= ~LED_MASK; + // all LEDs output + LED_DDR |= LED_MASK; + + for(uint8_t i = 0; i < LED_COUNT; i++) { + leds[i][R] = 0; + leds[i][G] = 0; + leds[i][B] = 0; + } + + // 64 light levels * 60Hz update * 4 different GND pins = 15360Hz + // 520 clock cycles for our interrupt handler + // CTC mode + TCCR0A = _BV(WGM01); + // clk/8 prescaler + TCCR0B = _BV(CS01); + // 0.16% error on above calculation + OCR0A = 128;//64; DEBUG SLOWER + // Enable interrupt on OCR0A + TIMSK0 = _BV(OCIE0A); + // Clear interrupt + TIFR0 = _BV(OCF0A); + + /*debug shit + sei(); + while(1) { + led_set(0, 32, 0, 0); + _delay_ms(500); + led_set(0, 0, 0, 0); + _delay_ms(500); + + currentGnd++; + currentGnd %= GND_COUNT; + GND_ENABLE(currentGnd); + LED_PORT &= ~LED_MASK; + LED_PORT |= 0b100010 << 2; + _delay_ms(500); + LED_PORT &= ~LED_MASK; + LED_PORT |= 0b010001 << 2; + _delay_ms(500); + LED_PORT &= ~LED_MASK; + LED_PORT |= 0b001100 << 2; + _delay_ms(500); + GND_DISABLE(currentGnd); + }*/ +} + +void led_set(uint8_t num, uint8_t r, uint8_t g, uint8_t b) { + leds[num][R] = r; + leds[num][G] = g; + leds[num][B] = b; +} +//if(leds[(currentGnd << 1) + side][colour] <= currentBright) +#define LED_SET(side, colour, outPin) \ + if(leds[offset + side][colour] > currentBright) \ + out |= _BV(outPin) + +// This function takes about 279 clock cycles. Could be improved :( +// Optimised GND accesses got it to 157 +ISR(TIMER0_COMPA_vect) { + uint8_t out = 0; + + currentGnd++; + currentGndMask >>= 1; + if(currentGnd >= GND_COUNT) { + currentGnd = 0; + currentGndMask = _BV(7); + ++currentBright; + currentBright %= BRIGHTNESS_LEVELS; + } + + uint8_t offset = currentGnd * 2; + // Faster than loops + LED_SET(0, 0, 2); + LED_SET(0, 1, 3); + LED_SET(0, 2, 4); + LED_SET(1, 0, 5); + LED_SET(1, 1, 6); + LED_SET(1, 2, 7); + + // Turn off before switch + LED_PORT &= ~LED_MASK; + GND_DDR &= ~GND_MASK; + // Enable new ground + GND_DDR |= currentGndMask; + LED_PORT |= out; +} \ No newline at end of file diff --git a/Firmware/Keyboard/LED.h b/Firmware/Keyboard/LED.h new file mode 100644 index 0000000..2fe24a8 --- /dev/null +++ b/Firmware/Keyboard/LED.h @@ -0,0 +1,13 @@ +#ifndef LED_h_ +#define LED_h_ + +#include +#include +#include + +#define LED_COUNT 8 + +void led_init(void); +void led_set(uint8_t num, uint8_t r, uint8_t g, uint8_t b); + +#endif diff --git a/Firmware/Keyboard/makefile b/Firmware/Keyboard/makefile index d971460..5a7300b 100644 --- a/Firmware/Keyboard/makefile +++ b/Firmware/Keyboard/makefile @@ -18,7 +18,7 @@ F_CPU = 8000000 F_USB = $(F_CPU) OPTIMIZATION = s TARGET = Keyboard -SRC = $(TARGET).c Descriptors.c Config.c Encoder.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) +SRC = $(TARGET).c Descriptors.c Config.c Encoder.c LED.c $(LUFA_SRC_USB) $(LUFA_SRC_USBCLASS) LUFA_PATH = ../LUFA CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -IConfig/ LD_FLAGS = diff --git a/Hardware/other_bom.csv b/Hardware/other_bom.csv index 44a33e6..fdc81a5 100644 --- a/Hardware/other_bom.csv +++ b/Hardware/other_bom.csv @@ -5,8 +5,8 @@ C2,YAGEO,CC0402MRX5R5BB106,1,0402 10uf R1,YAGEO,RC0603JR-0722RL,1,0603 22r R2,YAGEO,RC0402FR-0722RL,1,0402 22r R3,YAGEO,RC0402JR-0710KL,1,0402 10k -"R6,R9",YAGEO,RC0603JR-07100RL,2,0603 100r -"R4,R5,R7,R8",YAGEO,RC0603JR-07150RL,4,0603 150r +"R6,R9",YAGEO,RC0603JR-07100RL,2,0603 150r +"R4,R5,R7,R8",YAGEO,RC0603JR-07150RL,4,0603 100r U1,Atmel,ATMEGA16U2-MU,1,atmega J1,suntech,ZX62D-B-5P8,1,usb conn XT1,Murata,CSTCE8M00G15L99-R0,1,resonator