diff --git a/Makefile b/Makefile index 5823233..2930119 100644 --- a/Makefile +++ b/Makefile @@ -8,23 +8,49 @@ USEMODULE += shell_commands USEMODULE += ps USEMODULE += xtimer USEMODULE += nrf24l01p +USEMODULE += servo # set default device parameters in case they are undefined -SPI_PORT ?= SPI_0 +NRF_SPI_PORT ?= SPI_0 +WS2812_SPI_PORT ?= SPI_1 CE_PIN ?= GPIO_PIN\(PORT_A,6\) CS_PIN ?= GPIO_PIN\(PORT_E,3\) IRQ_PIN ?= GPIO_PIN\(PORT_A,7\) +CFLAGS_OPT = -O3 -Wno-unused # export parameters -CFLAGS += -DSPI_PORT=$(SPI_PORT) + +CFLAGS += -DENABLE_RES_LADDER=1 +CFLAGS += -DRES_LADDER_ADC=ADC_0 +CFLAGS += -DRES_LADDER_CHAN=2 + +CFLAGS += -DENABLE_LCD=1 + +CFLAGS += -DENABLE_WS2812=1 +CFLAGS += -DWS2812_SPI_PORT=$(WS2812_SPI_PORT) + +CFLAGS += -DENABLE_NRF_COMM=1 +CFLAGS += -DNRF_SPI_PORT=$(NRF_SPI_PORT) CFLAGS += -DCE_PIN=$(CE_PIN) CFLAGS += -DCS_PIN=$(CS_PIN) CFLAGS += -DIRQ_PIN=$(IRQ_PIN) -CFLAGS += -DENABLE_NRF_COMM=1 -CFLAGS += -DENABLE_WS2812=1 +CFLAGS += -DENABLE_MM5450=0 +CFLAGS += -DMM5450_CLK=GPIO_PIN\(PORT_C,5\) +CFLAGS += -DMM5450_DIN=GPIO_PIN\(PORT_C,4\) + +CFLAGS += -DENABLE_ROTARY=1 +CFLAGS += -DROTARY_PIN2=GPIO_PIN\(PORT_D,6\) +CFLAGS += -DROTARY_PIN1=GPIO_PIN\(PORT_C,7\) + +CFLAGS += -DENABLE_ROTARY_BUTTON=1 +CFLAGS += -DROTARY_BUTTON_PIN=GPIO_PIN\(PORT_D,7\) +CFLAGS += -DENABLE_BOARD_SWITCH=1 +CFLAGS += -DENABLE_SERVO=1 +CFLAGS += -DSERVO_FREQUENCY=50 -DSERVO_RESOLUTION=0xc3500 +CFLAGS += -DSERVO_PWM=PWM_2 ##CFLAGS += -I$(HOME)/git/ubberFrame include $(RIOTBASE)/Makefile.include diff --git a/main.c b/main.c index ea3cde0..7bc48de 100644 --- a/main.c +++ b/main.c @@ -1,25 +1,6 @@ -/* - * Copyright (C) 2014 Hamburg University of Applied Sciences - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. - */ - -/** - * @ingroup tests - * @{ - * - * @file - * @brief Test application for nrf24l01p lowlevel functions - * - * @author Peter Kietzmann - * - * @} - */ - -#ifndef SPI_PORT -#error "SPI_PORT not defined" +#ifdef ENABLE_NRF_COMM +#ifndef NRF_SPI_PORT +#error "NRF_SPI_PORT not defined" #endif #ifndef CE_PIN #error "CE_PIN not defined" @@ -33,10 +14,20 @@ #include "periph/spi.h" -#ifdef ENABLE_NRF_COMM #include "nrf24l01p_settings.h" #include "nrf24l01p.h" #include "nrf24l01p_settings.h" +#endif /* ENABLE_NRF_COMM */ + +#if ENABLE_SERVO +#include "servo.h" +#include "periph/pwm.h" +static unsigned int current_pulse = 1000; +static servo_t servo1; +#endif + +#if ENABLE_MM5450 +#include "mm545x.h" #endif #include @@ -57,10 +48,24 @@ #include #include "periph_conf.h" +#ifdef ENABLE_LCD #include "lcd1602d.h" +#endif + #include "uberframe.h" //#include "uberWrap.h" +#if ENABLE_MM5450 +mm545x_t mm545p = {0}; +#endif + + + + +#if ENABLE_WS2812 +#include "ws2812.h" +#endif + #define TEST_RX_MSG 1 #ifdef ENABLE_NRF_COMM @@ -80,8 +85,9 @@ static int cmd_set_dpl(int argc, char **argv); void printbin(unsigned byte); void print_register(char reg, int num_bytes); +#ifdef ENABLE_SEND_LED static gpio_t led = GPIO_PIN(PORT_F, 1); - +#endif static unsigned int display_pid = KERNEL_PID_UNDEF; @@ -90,6 +96,7 @@ static nrf24l01p_t nrf24l01p_0; static unsigned int sender_pid = KERNEL_PID_UNDEF; #endif +#ifdef ENABLE_LCD struct lcd_ctx lcd = { .rs_pin = GPIO_PIN(PORT_E, 5), .enable_pin = GPIO_PIN(PORT_E,4), @@ -97,6 +104,7 @@ struct lcd_ctx lcd = { .displayfunctions = (LCD_4BITMODE | LCD_1LINE | LCD_2LINE | LCD_5x8DOTS), .numlines = 2, }; +#endif /** * define some additional shell commands @@ -119,6 +127,8 @@ static const shell_command_t shell_commands[] = { }; // ROTARY +#ifdef ENABLE_ROTARY + // No complete step yet. #define DIR_NONE 0x0 // Clockwise step. @@ -128,6 +138,8 @@ static const shell_command_t shell_commands[] = { #define R_START 0x0 +//#define HALF_STEP 1 + #ifdef HALF_STEP // Use the half-step state table (emits a code at 00 and 11) #define R_CCW_BEGIN 0x1 @@ -199,38 +211,51 @@ const unsigned char ttable[7][4] = { unsigned int state = R_START; -/* gpio_t b1 = GPIO_PIN(PORT_C, 7); */ -/* gpio_t b2 = GPIO_PIN(PORT_D, 6); */ +void rotary_cb(void *unused) { + unsigned int b1_v = gpio_read(ROTARY_PIN1) ? 1 : 0; + unsigned int b2_v = gpio_read(ROTARY_PIN2) ? 1 : 0; -/* void rotary_cb(void *unused __attribute__((unused))) { */ -/* unsigned int b1_v = gpio_read(b1) ? 1 : 0; */ -/* unsigned int b2_v = gpio_read(b2) ? 1 : 0; */ +#if ENABLE_SERVO + int dir = 0; +#endif -/* unsigned char pinstate = ( b1_v? 2 : 0) | (b2_v ? 1 : 0); */ -/* /\* history[history_cnt] = pinstate; *\/ */ -/* /\* history_cnt++; *\/ */ + unsigned char pinstate = ( b1_v? 2 : 0) | (b2_v ? 1 : 0); -/* /\* printf("state %d pinstate : %x, b1 %d b2 %d\n", state, pinstate, b1_v, b2_v); *\/ */ -/* state = ttable[state & 0xf][pinstate]; */ - -/* switch(state & 0x30){ */ -/* case DIR_CCW: */ -/* printf("CCW\n"); */ -/* break; */ -/* case DIR_CW: */ -/* printf("CW\n"); */ -/* break; */ -/* case DIR_NONE: */ -/* // printf("noevent found\n"); */ -/* break; */ -/* default: */ -/* // printf("none of the above ?! %d\n", state); */ -/* break; */ -/* } */ -/* printf("boom\n"); */ -/* } */ - -//END ROTARY + /* printf("state %d pinstate : %x, b1 %d b2 %d\n", state, pinstate, b1_v, b2_v); */ + state = ttable[state & 0xf][pinstate]; + + switch(state & 0x30){ + case DIR_CCW: + printf("CCW\n"); +#if ENABLE_SERVO + dir=1; +#endif + break; + + case DIR_CW: + printf("CW\n"); +#if ENABLE_SERVO + dir=-1; +#endif + break; + + case DIR_NONE: + default: + break; + } + +#if ENABLE_SERVO + if(dir){ + current_pulse += (dir * 10); + printf("curr %d\n", current_pulse); + if (current_pulse >= 1000 && current_pulse <= 2000) + servo_set(&servo1, current_pulse); + } +#endif + +} + +#endif /* ENABLE_ROTARY */ void prtbin(unsigned byte) { @@ -255,7 +280,7 @@ void print_register(char reg, int num_bytes) gpio_clear(CS_PIN); xtimer_usleep(1); - ret = spi_transfer_regs(SPI_PORT, (CMD_R_REGISTER | (REGISTER_MASK & reg)), 0, buf_return, num_bytes); + ret = spi_transfer_regs(NRF_SPI_PORT, (CMD_R_REGISTER | (REGISTER_MASK & reg)), 0, buf_return, num_bytes); gpio_set(CS_PIN); if (ret < 0) { @@ -303,9 +328,13 @@ void *nrf24l01p_tx_thread(void *arg){ printf("nrf24l01p_tx got a message\n"); // lcd1602d_printstr(&lcd, 0, 1, dest_str); +#ifdef ENABLE_LCD lcd1602d_printstr(&lcd, 10, 1, "SEND..."); +#endif cmd_send(4, (char**)m.content.ptr); +#ifdef ENABLE_LCD lcd1602d_printstr(&lcd, 10, 1, "IDLE "); +#endif } return NULL; } @@ -321,6 +350,8 @@ void *display_thread(void *arg){ while (msg_receive(&m)) { printf("display_thread got a message\n"); + +#ifdef ENABLE_LCD const char *name = uber_get_name(dest); lcd1602d_printstr(&lcd, 0, 1, name); int i; @@ -328,6 +359,7 @@ void *display_thread(void *arg){ lcd1602d_printstr(&lcd, i, 1, " "); } } +#endif return NULL; } @@ -380,8 +412,11 @@ void *nrf24l01p_rx_handler(void *arg) uber_dump_frame(&frame); char buf[256] = {0}; uber_get_frame(&frame, buf); + +#ifdef ENABLE_LCD printf("lcd rx:%p\n", &lcd); lcd1602d_printstr(&lcd, 0, 0, buf); +#endif break; default: @@ -407,7 +442,7 @@ int cmd_its(int argc, char **argv) puts("Init Transceiver\n"); /* initialize transceiver device */ - if (nrf24l01p_init(&nrf24l01p_0, SPI_PORT, CE_PIN, CS_PIN, IRQ_PIN) < 0) { + if (nrf24l01p_init(&nrf24l01p_0, NRF_SPI_PORT, CE_PIN, CS_PIN, IRQ_PIN) < 0) { puts("Error in nrf24l01p_init"); return 1; } @@ -435,7 +470,7 @@ int cmd_get_config(int argc, char **argv) gpio_clear(CS_PIN); xtimer_usleep(1); - ret = spi_transfer_regs(SPI_PORT, (CMD_R_REGISTER | (REGISTER_MASK & REG_CONFIG)), 0, (char*)&buf_return, 1); + ret = spi_transfer_regs(NRF_SPI_PORT, (CMD_R_REGISTER | (REGISTER_MASK & REG_CONFIG)), 0, (char*)&buf_return, 1); gpio_set(CS_PIN); if (ret < 0) { printf("Error in read access\n"); @@ -482,7 +517,7 @@ int cmd_uber_setup(int argc, char **argv) printf("IRQ : pin %d: port %d\n", (unsigned int)(IRQ_PIN&0x0f), (unsigned int)(IRQ_PIN>>4)); /* initialize transceiver device */ - if (nrf24l01p_init(&nrf24l01p_0, SPI_PORT, CE_PIN, CS_PIN, IRQ_PIN) < 0) { + if (nrf24l01p_init(&nrf24l01p_0, NRF_SPI_PORT, CE_PIN, CS_PIN, IRQ_PIN) < 0) { puts("Error in nrf24l01p_init"); return 1; } @@ -559,7 +594,9 @@ int cmd_uber_setup(int argc, char **argv) */ int cmd_send(int argc, char **argv) { +#ifdef ENABLE_SEND_LED gpio_set(led); +#endif puts("Send"); int status = 0; @@ -625,7 +662,9 @@ int cmd_send(int argc, char **argv) puts("Error in nrf24l01p_set_rxmode"); return 1; } +#ifdef ENABLE_SEND_LED gpio_clear(led); +#endif return 0; } @@ -826,6 +865,8 @@ void test_cb(void * bid){ dest = 1; } printf("dest %d\n", dest != 8 ? dest : 0xFF); + +#ifdef ENABLE_LCD printf("lcd cb:%p\n", &lcd); // lcd1602d_printstr(&lcd, 0, 1, dest_str); if (display_pid != KERNEL_PID_UNDEF) { @@ -834,7 +875,8 @@ void test_cb(void * bid){ m.content.ptr = NULL; msg_send_int(&m, display_pid); } - +#endif + return; break; @@ -847,7 +889,7 @@ void test_cb(void * bid){ sprintf(dest_str, "%d", dest != 8 ? dest : 0xFF); dest_str[9] = 0; -#ifdef SPI_NUMOF +#ifdef ENABLE_NRF_COMM if (sender_pid != KERNEL_PID_UNDEF) { msg_t m; m.type = RCV_PKT_NRF24L01P; @@ -861,7 +903,7 @@ void test_cb(void * bid){ //cmd_send(4, argv); } -#ifdef ADC_NUMOF +#ifdef ENABLE_RES_LADDER static int res_ladder_val(adc_t adc, int channel){ int sample = adc_sample(adc, channel); const int max_v = 4095; @@ -886,42 +928,159 @@ int main(void) { puts("Uber\n"); -#ifdef ADC_NUMOF - adc_init(ADC_0, 10); +#if ENABLE_SERVO + int r = servo_init(&servo1, SERVO_PWM, 0, 1000, 2000); + printf("servo init : %d\n", r); #endif + +#if ENABLE_MM5450 + mm545x_init(&mm545p, MM5450_CLK, MM5450_DIN); + uint8_t sev1[8] = {0,1,2,3,4,5,6,7}; + uint8_t sev2[8] = {8,9,10,11,12,13,14,15}; + + /* mm545x_setupSegment(&mm545p, 0, sev1); */ + /* mm545x_setupSegment(&mm545p, 1, sev2); */ + /* mm545x_setSegment(&mm545p, 0, '8'); */ + mm545x_setLeds(&mm545p, 0xffffffffffffffff); + // mm545x_refreshSegments(&mm545p); + /* gpio_init(GPIO_PIN(PORT_C,5), GPIO_DIR_OUT, GPIO_NOPULL); */ + /* gpio_set(GPIO_PIN(PORT_C,5)); */ +#endif + + +#if ENABLE_WS2812 + +#define MAX_PIX_VAL 255 + ws2812_rgb_t led_array[] = { + OFF, + {.r=0xff, .g=0, .b=0}, + {.r=0x0, .g=0xff, .b=0}, + {.r=0x0, .g=0, .b=0xff}, + {.r=0xff, .g=0xff, .b=0}, + {.r=0xff, .g=0xff, .b=0xff}, + {.r=0xff, .g=0, .b=0}, + {.r=0xff, .g=0xff, .b=0}, + + /* RED, GREEN, BLUE, */ + /* RED, GREEN, BLUE, */ + /* RED, GREEN */ + }; + static char big_buffer[sizeof(led_array)*4] = {0}; + ws2812_rgb_t kit_leds [8] = {{0}}; + int kit_eye = 3; + + ws2812_t ws2812p; + ws2812_init(&ws2812p, WS2812_SPI_PORT ); + +#endif /* ENABLE_WS2812 */ + +#ifdef ENABLE_LCD lcd1602d_init_lcd(&lcd); // lcd1602d_setCursor(&lcd, 0,0); printf("lcd:%p\n", &lcd); + lcd1602d_printstr(&lcd, 0, 0, "STARTING"); +#endif + /* lcd1602d_printstr(&lcd, 0,0,"Bojr"); */ /* lcd1602d_printstr(&lcd, 3,1,"Bloop"); */ +#if ENABLE_BOARD_SWITCH gpio_t b1 = GPIO_PIN(PORT_F, 4); int b1_v = 1, b2_v = 2; gpio_init_int(b1, GPIO_PULLUP, GPIO_FALLING, test_cb, &b1_v); gpio_t b2 = GPIO_PIN(PORT_F, 0); gpio_init_int(b2, GPIO_PULLUP, GPIO_FALLING, test_cb, &b2_v); +#endif + +#if ENABLE_ROTARY_BUTTON + gpio_t rot_pin = ROTARY_BUTTON_PIN; + int rot_but_arg = 1; + gpio_init_int(rot_pin, GPIO_PULLUP, GPIO_BOTH, test_cb, &rot_but_arg); +#endif +#ifdef ENABLE_SEND_LED gpio_init(led, GPIO_DIR_OUT, GPIO_NOPULL); gpio_clear(led); +#endif //char line_buf[SHELL_DEFAULT_BUFSIZE]; -#ifdef SPI_NUMOF +#ifdef ENABLE_NRF_COMM cmd_uber_setup(0, NULL); #endif //shell_run(shell_commands, line_buf, SHELL_DEFAULT_BUFSIZE); +#ifdef ENABLE_ROTARY + gpio_init_int(ROTARY_PIN1, GPIO_PULLUP, GPIO_BOTH, rotary_cb, NULL); + gpio_init_int(ROTARY_PIN2, GPIO_PULLUP, GPIO_BOTH, rotary_cb, NULL); //GPIO_DIR_IN, GPIO_PULLUP); +#endif - /* gpio_init_int(b1, GPIO_PULLUP, GPIO_BOTH, rotary_cb, NULL); */ - /* gpio_init(b2, GPIO_DIR_IN, GPIO_PULLUP); */ -#ifdef ADC_NUMOF - int button_state = res_ladder_val(ADC_0, 2); +#ifdef ENABLE_RES_LADDER + adc_init(RES_LADDER_ADC, 10); + int button_state = res_ladder_val(RES_LADDER_ADC, RES_LADDER_CHAN); #endif - + + + // endless loop start + int loop_count=0; while(1){ -#ifdef ADC_NUMOF - int new_button_state = res_ladder_val(ADC_0, 2); + loop_count++; +#if ENABLE_WS2812 + { + int i; + int pos = abs(kit_eye)-1; + + for (i=0; i<8; i++){ + kit_leds[i].r = 255 / (1 << abs(i-pos)) ; + } + ws2812_write_rgb(&ws2812p, kit_leds, sizeof(kit_leds)/sizeof(ws2812_rgb_t), big_buffer); + + kit_eye++; + if (kit_eye == 9){ + kit_eye = -8; + } else if (kit_eye == -9){ + kit_eye = 8; + } else if (kit_eye == 0){ + kit_eye++; + } + } + +#endif + +#if ENABLE_WS2812 && 0 + ws2812_write_rgb(&ws2812p, led_array, sizeof(led_array)/sizeof(ws2812_rgb_t), big_buffer); + // ws2812_write(&ws2812p, led_array_2, sizeof(led_array_2)); + int idx; + for (idx=0; idx < sizeof(led_array)/sizeof(ws2812_rgb_t)-1; idx++){ + ws2812_rgb_t *cur = &led_array[idx]; + if (cur->r == 0xff && cur->g==0xff && cur->b ){ + cur->b--; + } else if (cur->r==0xff && cur->g && !cur->b){ + cur->g--; + } else if (cur->r && !cur->g && !cur->b){ + cur->r--; + } else if(!cur->r && !cur->g && cur->b != 0xff){ + cur->b++; + } else if(!cur->r && cur->g != 0xff && cur->b == 0xff){ + cur->g++; + } else if (cur->r!=0xff && cur->g==0xff && cur->b == 0xff){ + cur->r++; + } + // printf("%x %x %x\n", cur->r, cur->g, cur->b); + } + // rotate stuff + if (loop_count % 1000000){ + ws2812_rgb_t tmp = led_array[sizeof(led_array)/sizeof(ws2812_rgb_t)-1]; + for (idx=sizeof(led_array)/sizeof(ws2812_rgb_t)-1; idx > 0; idx--){ + led_array[idx] = led_array[idx-1]; + } + led_array[0] = tmp; + } +#endif + +#ifdef ENABLE_RES_LADDER + int new_button_state = res_ladder_val(RES_LADDER_ADC, RES_LADDER_CHAN); if (new_button_state != button_state){ button_state = new_button_state; @@ -939,7 +1098,8 @@ int main(void) } } #endif - xtimer_usleep(10000); + xtimer_usleep(100000/2); + // printf("tick\n"); thread_yield(); } return 0; diff --git a/mm545x.c b/mm545x.c new file mode 100644 index 0000000..c525798 --- /dev/null +++ b/mm545x.c @@ -0,0 +1,157 @@ +#include +#include "mm545x.h" +#include "xtimer.h" +/** + * Delay between clock transitions + */ +#define CLOCK_USEC_DELAY 2 + +/** + * Count of output bits + */ +#define OUTPUT_BIT_COUNT 35 + +static uint8_t digitPattern[] = { + 0x3F, /* 0 */ + 0x06, /* 1 */ + 0x5B, /* 2 */ + 0x4F, /* 3 */ + 0x66, /* 4 */ + 0x6D, /* 5 */ + 0x7D, /* 6 */ + 0x07, /* 7 */ + 0x7F, /* 8 */ + 0x6F, /* 9 */ +}; + +static uint8_t alphaPattern[] = { + 0b01110111, /* a */ + 0b01111100, /* b */ + 0b00111001, /* c */ + 0b01011110, /* d */ + 0b01111001, /* e */ + 0b01110001, /* f */ + 0b01101111, /* g */ + 0b01110110, /* h */ + 0b00110000, /* i */ + 0b00011110, /* j */ + 0b01110110, /* k */ + 0b00111000, /* l */ + 0b00010101, /* m */ + 0b01010100, /* n */ + 0b00111111, /* o */ + 0b01110011, /* p */ + 0b01100111, /* q */ + 0b01010000, /* r */ + 0b01101101, /* s */ + 0b01111000, /* t */ + 0b00111110, /* u */ + 0b00011100, /* v */ + 0b00101010, /* w */ + 0b01110110, /* x */ + 0b01101110, /* y */ + 0b01011011, /* z */ +}; + +#define COMMA 0b10000000 +#define DASH 0b01000000 +#define UNDERSCORE 0b00001000 +#define QUOTE 0b00100000 +#define EQUAL 0b01001000 + + +int mm545x_init(mm545x_t *mm, gpio_t clock_pin, gpio_t data_pin){ + int i; + mm->clock_pin = clock_pin; + mm->data_pin = data_pin; + + gpio_init(clock_pin, GPIO_DIR_OUT, GPIO_NOPULL); + gpio_init(data_pin, GPIO_DIR_OUT, GPIO_NOPULL); + + gpio_clear(clock_pin); + gpio_clear(data_pin); + + for (i = 0; i < MAX_SEGMENTS_PER_MM545X; i++) { + memset(mm->sevSegPins[i], 0, SEGMENT_COUNT); + mm->sevSegValue[i] = 0; + } + + /* reset the leds */ + mm545x_setLeds(mm, (uint64_t) 0); + return 0; +} + +void mm545x_setLeds(mm545x_t *mm, uint64_t leds) { + int i; + + /* Send the preamble */ + gpio_set(mm->data_pin); + gpio_clear(mm->clock_pin); + xtimer_usleep(CLOCK_USEC_DELAY); + gpio_set(mm->clock_pin); + + /* Then output the bits */ + for (i = 0; i < OUTPUT_BIT_COUNT; i++) { + xtimer_usleep(CLOCK_USEC_DELAY); + if ((leds >> i) & 0x1) { + gpio_set(mm->data_pin); + } else { + gpio_clear(mm->data_pin); + } + gpio_clear(mm->clock_pin); + xtimer_usleep(CLOCK_USEC_DELAY); + gpio_set(mm->clock_pin); + } + + xtimer_usleep(CLOCK_USEC_DELAY); + gpio_clear(mm->clock_pin); +} + +void mm545x_setupSegment(mm545x_t *mm, int sevSeg, uint8_t pins[SEGMENT_COUNT]) +{ + memcpy(mm->sevSegPins[sevSeg], pins, SEGMENT_COUNT); +} + +void mm545x_setSegment(mm545x_t *mm, int sevSeg, char value) +{ + if (value >= '0' && value <= '9') { + mm545x_setSegmentRaw(mm, sevSeg, digitPattern[value - '0']); + } else if (value >= 'a' && value <= 'z') { + mm545x_setSegmentRaw(mm, sevSeg, alphaPattern[value - 'a']); + } else if (value >= 'A' && value <= 'Z') { + mm545x_setSegmentRaw(mm, sevSeg, alphaPattern[value - 'A']); + } else if (value == ' ') { + mm545x_setSegmentRaw(mm, sevSeg, 0x0); + } else if (value == ',' || value == ';' || value == '.') { + mm545x_setSegmentRaw(mm, sevSeg, COMMA); + } else if (value == '_') { + mm545x_setSegmentRaw(mm, sevSeg, UNDERSCORE); + } else if (value == '-') { + mm545x_setSegmentRaw(mm, sevSeg, DASH); + } else if (value == '\'') { + mm545x_setSegmentRaw(mm, sevSeg, QUOTE); + } else if (value == '=') { + mm545x_setSegmentRaw(mm, sevSeg, QUOTE); + } +} + +void mm545x_setSegmentRaw(mm545x_t *mm, int sevSeg, uint8_t segMask) +{ + mm->sevSegValue[sevSeg] = segMask; +} + +void mm545x_refreshSegments(mm545x_t *mm) +{ + uint64_t value = 0; + int sevSeg, seg; + for (sevSeg = 0; sevSeg < MAX_SEGMENTS_PER_MM545X; sevSeg++) { + for (seg = 0; seg < SEGMENT_COUNT; seg++) { + /* If the bit is set in the value, then set the pin as high */ + if ((mm->sevSegValue[sevSeg] >> seg) & 0x1) { + value |= ((uint64_t) 0x1 << (uint64_t) mm->sevSegPins[sevSeg][seg]); + } + } + } + + mm545x_setLeds(mm, value); +} diff --git a/mm545x.h b/mm545x.h new file mode 100644 index 0000000..f278c18 --- /dev/null +++ b/mm545x.h @@ -0,0 +1,58 @@ +#pragma once + +#include +#include "periph/gpio.h" + +/** + * Maximum number of seven segments per chip + */ +#define MAX_SEGMENTS_PER_MM545X 4 + +/** + * Number of segment per display + */ +#define SEGMENT_COUNT 8 + +typedef struct { + gpio_t clock_pin; + gpio_t data_pin; + uint8_t sevSegPins[MAX_SEGMENTS_PER_MM545X][SEGMENT_COUNT]; + uint8_t sevSegValue[MAX_SEGMENTS_PER_MM545X]; +} mm545x_t; + +int mm545x_init(mm545x_t *mm, gpio_t clock_pin, gpio_t data_pin); + +/** + * Set the mask for all leds, useful when working with other leds than 7 segments + * @param bits A bitmask of all output (only the first 35 bits are significant) + * The lower bit correspond to output 0. + */ +void mm545x_setLeds(mm545x_t *mm, uint64_t bits); + +/** + * When using the chip as a seven segment controller, setup segments + * @param sevSeg Seven segment display index + * @param pins, pin mapping for the seven segment + * Pins are given in the following order: [a, b, c, d ,e , f, g, dp] + */ +void mm545x_setupSegment(mm545x_t *mm, int sevSeg, uint8_t pins[SEGMENT_COUNT]); + +/** + * Set a segment value + * @param sevSeg Seven sigment display index + * @param value Character value to display + */ +void mm545x_setSegment(mm545x_t *mm, int sevSeg, char value); + +/** + * Set a raw value for a segment + * @param sevSeg Seven sigment display index + * @param segMask Mask of segment to set (a, b, c, d ,e , f, g, dp) + * Note that the lower bit correspond to segment a. + */ +void mm545x_setSegmentRaw(mm545x_t *mm, int sevSeg, uint8_t segMask); + +/** + * Update the display and apply the previously set segments value. + */ +void mm545x_refreshSegments(mm545x_t *mm); diff --git a/ws2812.c b/ws2812.c new file mode 100644 index 0000000..d514ba2 --- /dev/null +++ b/ws2812.c @@ -0,0 +1,81 @@ +#include "ws2812.h" +#include "periph/spi.h" +#include + +#define log printf("%d\n", __LINE__) + +int ws2812_init(ws2812_t *dev, spi_t spi){ + + dev->spi = spi; + log; + /* Init SPI */ + spi_poweron(dev->spi); + log; + spi_acquire(dev->spi); + log; + int status = spi_init_master(dev->spi, SPI_CONF_FIRST_RISING, SPI_SPEED_4MHZ); + log; + spi_release(dev->spi); + log; + return status; +} + +int ws2812_write(ws2812_t *dev, char *b, unsigned len) { + static char reset_pulse[20] = {0}; + + spi_acquire(dev->spi); + /* int i = 0; */ + /* for (i=0; ispi, b, NULL, len); + + spi_transfer_bytes(dev->spi, reset_pulse, NULL, sizeof(reset_pulse)); + spi_release(dev->spi); + return 0; +} + +#define ZERO_BIT_PULSE 0x8 // 1000 (0000) ~250ns +#define ONE_BIT_PULSE 0xE // 1110 (0000) ~750ns + +#define W00 0x88 +#define W01 0x8E +#define W10 0xE8 +#define W11 0xEE + +int ws2812_write_rgb(ws2812_t *dev, ws2812_rgb_t *leds, unsigned len, char* buffer){ + int out_count = 0; + char *bytes = (char*)leds; + int led_idx; + + for (led_idx = (len*sizeof(ws2812_rgb_t))-1; led_idx >= 0; led_idx--){ + int bit_idx; + unsigned char cur_byte = bytes[led_idx]; + + for (bit_idx = 0; bit_idx < 8; bit_idx+=2){ + switch((cur_byte & 0xC0)>>6) { + case 0x0: + buffer[out_count] = W00; + break; + case 0x1: + buffer[out_count] = W01; + break; + case 0x2: + buffer[out_count] = W10; + break; + case 0x3: + buffer[out_count] = W11; + break; + } + cur_byte<<2; + /* buffer[out_count] = cur_byte & 0x80 ? ONE_BIT_PULSE : ZERO_BIT_PULSE; */ + /* cur_byte <<=1; */ + + /* buffer[out_count] |= (cur_byte & 0x80 ? ONE_BIT_PULSE : ZERO_BIT_PULSE)<<4; */ + /* cur_byte >>=1; */ + + out_count++; + } + } + return ws2812_write(dev, buffer, len*sizeof(ws2812_rgb_t)*8/2); +} diff --git a/ws2812.h b/ws2812.h new file mode 100644 index 0000000..d3bc68c --- /dev/null +++ b/ws2812.h @@ -0,0 +1,19 @@ +#pragma once + +#include "periph/spi.h" + +typedef struct { + spi_t spi; +} ws2812_t; + +typedef struct __attribute__((packed)) { + char g,r,b; +} ws2812_rgb_t; + +#define BLUE {0x00, 0x00, 0xFF} +#define RED {0x00, 0xFF, 0x00} +#define GREEN {0xFF, 0x00, 0x00} +#define OFF {0,0,0} +int ws2812_init(ws2812_t *dev, spi_t spi); +int ws2812_write(ws2812_t *dev, char *b, unsigned len); +int ws2812_write_rgb(ws2812_t *dev, ws2812_rgb_t *leds, unsigned len, char* buffer);