diff --git a/firmware-fret/fret-tester.py b/firmware-fret/fret-tester.py new file mode 100644 index 00000000..d6bbb797 --- /dev/null +++ b/firmware-fret/fret-tester.py @@ -0,0 +1,73 @@ +from periphery import * + +i = I2C("/dev/i2c-0") + +I2C_ADDRESS = 0x25 + +def process_key(key, size): + if type(key) is int: + start = key + length = 1 + else: + slice_start, slice_stop, slice_step = key.indices(size) + if slice_step != 1: + raise AttributeError("Can't have non 1 step.") + + start = slice_start + length = slice_stop - slice_start + return start, length + +class FretRegisters(object): + def __getitem__(self, key): + start, length = process_key(key, 256) + + msg = [ + I2C.Message([start, 0x00]), + I2C.Message([0x00] * length, read=True) + ]; + + i.transfer(I2C_ADDRESS, msg); + + if type(key) is int: + return msg[1].data[0]; + else: + return msg[1].data; + + def __setitem__(self, key, value): + start, length = process_key(key, 256) + if type(key) is int: + value = [value] + else: + value = list(value) + + i.transfer(I2C_ADDRESS, [I2C.Message([start, 0x00] + value)]); + + def __repr__(self): + return "FretRegisters"+repr(f[:]) + +f=FretRegisters() + +def dynamic_led_test(): + def rotate(l,n): + return l[n:] + l[:n] + + colors = ( + [[255-x,0,x] for x in range(255)] + + [[0,x,255-x] for x in range(255)] + + [[x,255-x,0] for x in range(255)] + ) + colors=colors[::6] #faster + #colors = [[b,b,b] for r,g,b in colors] #white glow + + while True: + for j in range(len(colors)): + c=rotate(colors,j)[::len(colors)//6] + #for g in range(20*2//10): + ##what if we had more frets(20x slower), was doing touch(2x slower), but increased the i2c speed(10x faster) too + f[0x80:]=sum(c,[])+[0x00] + #for g in range(20*2//10): + ##blink test to show the fps + #f[0x80:]=[0x00]*6*3+[0x00] + +if __name__=="__main__": + dynamic_led_test() diff --git a/firmware-fret/main.c b/firmware-fret/main.c index 7341ef0c..4a10afb5 100644 --- a/firmware-fret/main.c +++ b/firmware-fret/main.c @@ -36,6 +36,7 @@ #include #include "timer.c" #include "i2c_slave.c" +#include "ws2812.c" static void gpio_setup(void) { @@ -47,6 +48,9 @@ static void gpio_setup(void) rcc_periph_clock_enable(RCC_GPIOC); gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO6 | GPIO7 | GPIO8 | GPIO9); gpio_clear(GPIOC, GPIO6 | GPIO7 | GPIO8 | GPIO9); + + rcc_periph_clock_enable(RCC_GPIOC); + gpio_mode_setup(GPIOC, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO12); } int _write(int file, char *ptr, int len) @@ -87,19 +91,30 @@ void usart_setup(void) } unsigned char registers[0x100]; +/* + * Map: + * 0x00 : CHIP_ID "0x25" + * 0x80-0x91 : RGB LEDs values + * 0x92 : Commit the RGB LEDs (write anything) + * + */ +uint8_t *ws2812_colors = registers + 0X80; #define CHIP_ID 0x25 -void registers_init() { - registers[0] = CHIP_ID; - +void registers_init(void) { + registers[0x00] = CHIP_ID; } void registers_read_callback(uint16_t address) { //printf("r 0x%04x==0x%02x\n", address, registers[address]); } void registers_write_callback(uint16_t address) { - printf("w 0x%04x:0x%02x\n", address, registers[address]); +// printf("w 0x%04x:0x%02x\n", address, registers[address]); + if (address == 0x92) { +// printf("set leds"); + ws2812_sendarray(ws2812_colors,6*3); + } } int main(void) @@ -108,6 +123,7 @@ int main(void) systick_setup(); usart_setup(); gpio_setup(); + registers_init(); gpio_set LED_GREEN; printf("\n\nGuitar Fret Discovery Board\n"); @@ -117,6 +133,8 @@ int main(void) i2c_setup(); + ws2812_sendarray(ws2812_colors,6*3); + while(1){ printf("."); msleep(100); diff --git a/firmware-fret/ws2812.c b/firmware-fret/ws2812.c new file mode 100644 index 00000000..0bd3b3e2 --- /dev/null +++ b/firmware-fret/ws2812.c @@ -0,0 +1,40 @@ +//Bitbanging ws2812 implementation +//Requires disabled interrupts to run +//Dependent on system clock being 48MHz +//Here be dragons, don't touch + +#include + +__attribute__((optimize("unroll-loops"))) +__attribute__((always_inline)) +inline void ws2812_write_byte(uint8_t byte) { + for(int j = 7; j >= 0; j--) + { + bool bit = (byte & (1 << j)) == 0; + gpio_set(GPIOC,GPIO12); + GPIOC_BSRR = 1 << 12; + if(bit) + GPIOC_BSRR = 1 << 12 << 16; + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + __asm__("nop"); + GPIOC_BSRR = 1 << 12 << 16; + } +} + +__attribute__((optimize("unroll-loops"))) +void ws2812_sendarray(uint8_t *buf, uint16_t size) { + for(volatile int i = 0; i < 100; i++); + + cm_disable_interrupts(); + for(uint16_t i = 0; i < size; i+=3) + { + ws2812_write_byte(buf[i+1]); + ws2812_write_byte(buf[i+0]); + ws2812_write_byte(buf[i+2]); + } + cm_enable_interrupts(); +}