Skip to content

Commit

Permalink
firmware-fret: ws2812 driving
Browse files Browse the repository at this point in the history
* Bitbanged/fragile ws2812 driver
* Hooked up to the register
* Python tester to make pretty colors
  • Loading branch information
amstan committed Feb 21, 2016
1 parent 18529df commit 2551467
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 4 deletions.
73 changes: 73 additions & 0 deletions 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()
26 changes: 22 additions & 4 deletions firmware-fret/main.c
Expand Up @@ -36,6 +36,7 @@
#include <stdlib.h>
#include "timer.c"
#include "i2c_slave.c"
#include "ws2812.c"

static void gpio_setup(void)
{
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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");
Expand All @@ -117,6 +133,8 @@ int main(void)

i2c_setup();

ws2812_sendarray(ws2812_colors,6*3);

while(1){
printf(".");
msleep(100);
Expand Down
40 changes: 40 additions & 0 deletions 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 <libopencm3/cm3/cortex.h>

__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();
}

0 comments on commit 2551467

Please sign in to comment.