Further implement modes
This commit is contained in:
parent
6104ccd08a
commit
d85591c41e
4
Makefile
4
Makefile
@ -15,6 +15,10 @@ CFILES := main.c setup/system_init.c startup/startup_stm32f0xx.c systick.c
|
|||||||
CFILES += i2c.c
|
CFILES += i2c.c
|
||||||
CFILES += dmx.c
|
CFILES += dmx.c
|
||||||
CFILES += poti.c
|
CFILES += poti.c
|
||||||
|
CFILES += gamma.c
|
||||||
|
CFILES += pca9555.c
|
||||||
|
CFILES += animation.c
|
||||||
|
|
||||||
ASFILES =
|
ASFILES =
|
||||||
INCLUDEPATH = -Iinclude -Iinclude/cmsis
|
INCLUDEPATH = -Iinclude -Iinclude/cmsis
|
||||||
|
|
||||||
|
106
animation.c
Normal file
106
animation.c
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#include <animation.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <systick.h>
|
||||||
|
|
||||||
|
void animation_reset(struct animation *ani)
|
||||||
|
{
|
||||||
|
if (!ani)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ani->state = ANI_RED;
|
||||||
|
ani->step = 0u;
|
||||||
|
ani->last_tick = systick_get_global_tick();
|
||||||
|
ani->next_interval = 0ul;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void clear_dmx_universe(uint8_t *universe, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t idx;
|
||||||
|
|
||||||
|
for (idx = 0; idx < len; idx++) {
|
||||||
|
universe[idx] = 0u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum animation_state next_col_state(enum animation_state current)
|
||||||
|
{
|
||||||
|
enum animation_state next;
|
||||||
|
|
||||||
|
switch (current) {
|
||||||
|
case ANI_RED:
|
||||||
|
next = ANI_GREEN;
|
||||||
|
break;
|
||||||
|
case ANI_GREEN:
|
||||||
|
next = ANI_BLUE;
|
||||||
|
break;
|
||||||
|
case ANI_BLUE:
|
||||||
|
next = ANI_RAINBOW;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
next = ANI_RED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void animation_process(struct animation *ani, uint8_t *dmx_universe)
|
||||||
|
{
|
||||||
|
uint32_t tick;
|
||||||
|
uint32_t new_tick;
|
||||||
|
uint32_t i;
|
||||||
|
|
||||||
|
if (!ani || !dmx_universe)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Check if time for next step is reached */
|
||||||
|
tick = systick_get_global_tick();
|
||||||
|
/* Calculate next tick. Overflow expected */
|
||||||
|
new_tick = ani->last_tick + ani->next_interval;
|
||||||
|
if (new_tick < ani->last_tick) {
|
||||||
|
/* Tick overflowed. */
|
||||||
|
if (!(tick >= new_tick && tick < ani->last_tick))
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (tick < new_tick)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ani->last_tick = tick;
|
||||||
|
|
||||||
|
switch (ani->state) {
|
||||||
|
case ANI_RED:
|
||||||
|
case ANI_GREEN:
|
||||||
|
case ANI_BLUE:
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
dmx_universe[i * 4 + 0] = ani->state == ANI_RED ? (uint8_t)ani->step : 0u;
|
||||||
|
dmx_universe[i * 4 + 1] = ani->state == ANI_GREEN ? (uint8_t)ani->step : 0u;
|
||||||
|
dmx_universe[i * 4 + 2] = ani->state == ANI_BLUE ? (uint8_t)ani->step : 0u;
|
||||||
|
dmx_universe[i * 4 + 3] = 0u;
|
||||||
|
}
|
||||||
|
if (ani->step + 10 > 0xFFul) {
|
||||||
|
ani->step = 0;
|
||||||
|
ani->state = next_col_state(ani->state);
|
||||||
|
} else {
|
||||||
|
ani->step += 10;
|
||||||
|
}
|
||||||
|
ani->next_interval = 20;
|
||||||
|
break;
|
||||||
|
case ANI_RAINBOW:
|
||||||
|
/* TODO: Implement Rainbow mode */
|
||||||
|
ani->next_interval = 10;
|
||||||
|
clear_dmx_universe(dmx_universe, 129u);
|
||||||
|
ani->state = ANI_FLASH_WHITE;
|
||||||
|
break;
|
||||||
|
case ANI_FLASH_WHITE:
|
||||||
|
dmx_universe[128] = ani->step & 1 ? 0xFF : 0;
|
||||||
|
ani->next_interval = ani->step & 1 ? 60 : 260;
|
||||||
|
ani->step += 1u;
|
||||||
|
|
||||||
|
if (ani->step >= 11u) {
|
||||||
|
ani->state = ANI_RED;
|
||||||
|
ani->step = 0u;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
2
dmx.c
2
dmx.c
@ -64,7 +64,7 @@ void dmx_init(uint8_t *data, uint32_t universe_length, GPIO_TypeDef *tx_port, ui
|
|||||||
|
|
||||||
|
|
||||||
/* Configure TIM14 to count in 10 us steps */
|
/* Configure TIM14 to count in 10 us steps */
|
||||||
TIM14->PSC = 480u;
|
TIM14->PSC = 480u - 1u;
|
||||||
|
|
||||||
/* Configure the reload value. Must be higher or equal to 200 */
|
/* Configure the reload value. Must be higher or equal to 200 */
|
||||||
if (dmx_delay < 2000)
|
if (dmx_delay < 2000)
|
||||||
|
20
gamma.c
Normal file
20
gamma.c
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
#include <gamma.h>
|
||||||
|
|
||||||
|
const uint8_t global_gamma_correction_table[256] = {
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||||
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
||||||
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
||||||
|
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
|
||||||
|
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
||||||
|
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
|
||||||
|
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
|
||||||
|
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
|
||||||
|
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
|
||||||
|
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
|
||||||
|
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
|
||||||
|
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
|
||||||
|
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
|
||||||
|
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
|
||||||
|
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
|
||||||
|
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255
|
||||||
|
};
|
36
include/animation.h
Normal file
36
include/animation.h
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
#ifndef _ANIMATION_H_
|
||||||
|
#define _ANIMATION_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
enum animation_state {
|
||||||
|
ANI_RED,
|
||||||
|
ANI_GREEN,
|
||||||
|
ANI_BLUE,
|
||||||
|
ANI_RAINBOW,
|
||||||
|
ANI_FLASH_WHITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct animation {
|
||||||
|
enum animation_state state;
|
||||||
|
uint32_t step;
|
||||||
|
uint32_t last_tick;
|
||||||
|
uint32_t next_interval;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reset aniamtion to start conditions
|
||||||
|
*
|
||||||
|
* @param ani Animation
|
||||||
|
*/
|
||||||
|
void animation_reset(struct animation *ani);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Poll animation
|
||||||
|
*
|
||||||
|
* @param ani Animation
|
||||||
|
* @param dmx_universe Target universe to play animation into. Must be big enough
|
||||||
|
*/
|
||||||
|
void animation_process(struct animation *ani, uint8_t *dmx_universe);
|
||||||
|
|
||||||
|
#endif /* _ANIMATION_H_ */
|
13
include/gamma.h
Normal file
13
include/gamma.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _GAMMA_H_
|
||||||
|
#define _GAMMA_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
extern const uint8_t global_gamma_correction_table[256];
|
||||||
|
|
||||||
|
static inline uint8_t gamma_corr(uint8_t raw)
|
||||||
|
{
|
||||||
|
return global_gamma_correction_table[raw];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _GAMMA_H_ */
|
@ -9,6 +9,6 @@ void i2c_reset(void);
|
|||||||
|
|
||||||
int i2c_write(uint8_t i2c_addr, const uint8_t *data, uint8_t len);
|
int i2c_write(uint8_t i2c_addr, const uint8_t *data, uint8_t len);
|
||||||
|
|
||||||
int i2c_read(uint8_t i2c_addr, uint8_t command, uint8_t *data, uint8_t len);
|
|
||||||
|
|
||||||
|
int i2c_read(uint8_t i2c_addr, uint8_t command, uint8_t *data, uint8_t len);
|
||||||
#endif /* _I2C_H_ */
|
#endif /* _I2C_H_ */
|
28
include/pca9555.h
Normal file
28
include/pca9555.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _PCA9555_H_
|
||||||
|
#define _PCA9555_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define PCA9555_I2C_ADDR (0x40)
|
||||||
|
#define PCA9555_REG_IN_PORT0 (0x0)
|
||||||
|
#define PCA9555_REG_IN_PORT1 (0x1)
|
||||||
|
#define PCA9555_REG_OUT_PORT0 (0x2)
|
||||||
|
#define PCA9555_REG_OUT_PORT1 (0x3)
|
||||||
|
#define PCA9555_REG_POLARITY0 (0x4)
|
||||||
|
#define PCA9555_REG_POLARITY1 (0x5)
|
||||||
|
#define PCA9555_REG_CONFIG0 (0x6)
|
||||||
|
#define PCA9555_REG_CONFIG1 (0x7)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Init I2C and port expander
|
||||||
|
*/
|
||||||
|
void port_expander_init(void);
|
||||||
|
|
||||||
|
uint8_t port_expander_get_buttons(void);
|
||||||
|
|
||||||
|
void port_expander_set_leds(uint8_t leds);
|
||||||
|
|
||||||
|
uint8_t port_expander_get_leds(void);
|
||||||
|
|
||||||
|
void port_expander_set_single_led(uint8_t pos, uint8_t val);
|
||||||
|
#endif /* _PCA9555_H */
|
282
main.c
282
main.c
@ -1,42 +1,17 @@
|
|||||||
#include <poti.h>
|
#include <poti.h>
|
||||||
#include <i2c.h>
|
#include <pca9555.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stm32f0xx.h>
|
#include <stm32f0xx.h>
|
||||||
#include <stm-periph/stm32-gpio-macros.h>
|
#include <stm-periph/stm32-gpio-macros.h>
|
||||||
#include <systick.h>
|
#include <systick.h>
|
||||||
#include <dmx.h>
|
#include <dmx.h>
|
||||||
|
#include <gamma.h>
|
||||||
#define PCA9555_ADDR (0x40)
|
#include <animation.h>
|
||||||
#define PCA9555_REG_IN_PORT0 (0x0)
|
#include <string.h>
|
||||||
#define PCA9555_REG_IN_PORT1 (0x1)
|
#include <stdbool.h>
|
||||||
#define PCA9555_REG_OUT_PORT0 (0x2)
|
|
||||||
#define PCA9555_REG_OUT_PORT1 (0x3)
|
|
||||||
#define PCA9555_REG_POLARITY0 (0x4)
|
|
||||||
#define PCA9555_REG_POLARITY1 (0x5)
|
|
||||||
#define PCA9555_REG_CONFIG0 (0x6)
|
|
||||||
#define PCA9555_REG_CONFIG1 (0x7)
|
|
||||||
|
|
||||||
|
|
||||||
static const uint8_t gamma8[] = {
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
||||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
|
|
||||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2,
|
|
||||||
2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5,
|
|
||||||
5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10,
|
|
||||||
10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16,
|
|
||||||
17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25,
|
|
||||||
25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36,
|
|
||||||
37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50,
|
|
||||||
51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68,
|
|
||||||
69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89,
|
|
||||||
90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114,
|
|
||||||
115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142,
|
|
||||||
144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175,
|
|
||||||
177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213,
|
|
||||||
215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255
|
|
||||||
};
|
|
||||||
|
|
||||||
static uint8_t dmx_universe[129];
|
static uint8_t dmx_universe[129];
|
||||||
|
static struct animation led_animation;
|
||||||
|
|
||||||
enum color_mode {
|
enum color_mode {
|
||||||
MODE_RED,
|
MODE_RED,
|
||||||
@ -44,6 +19,10 @@ enum color_mode {
|
|||||||
MODE_BLUE,
|
MODE_BLUE,
|
||||||
MODE_RGB,
|
MODE_RGB,
|
||||||
MODE_WHITE_DISCRETE,
|
MODE_WHITE_DISCRETE,
|
||||||
|
MODE_WHITE_ANGLE,
|
||||||
|
MODE_RED_BLUE_RING,
|
||||||
|
MODE_ANIMATION,
|
||||||
|
MODE_DMX_SHUTDOWN,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void setup_pins(void)
|
static void setup_pins(void)
|
||||||
@ -87,103 +66,202 @@ static void setup_pins(void)
|
|||||||
GPIOB->PUPDR = PULLUP(1);
|
GPIOB->PUPDR = PULLUP(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void process_mode(enum color_mode mode, const struct poti_values *poti_vals)
|
||||||
|
{
|
||||||
|
uint32_t odr;
|
||||||
|
static uint32_t last_tick = 0ul;
|
||||||
|
uint32_t tick;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
odr = GPIOA->ODR;
|
||||||
|
odr &= ~((1<<5) | (1<<6) | (1<<7));
|
||||||
|
|
||||||
|
tick = systick_get_global_tick();
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_RED:
|
||||||
|
case MODE_GREEN:
|
||||||
|
case MODE_BLUE:
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
dmx_universe[i*4] = mode == MODE_RED ? poti_vals->pot_vals_filtered[0] : 0;
|
||||||
|
dmx_universe[i*4+1] = mode == MODE_GREEN ? poti_vals->pot_vals_filtered[0] : 0;
|
||||||
|
dmx_universe[i*4+2] = mode == MODE_BLUE ? poti_vals->pot_vals_filtered[0] : 0;
|
||||||
|
dmx_universe[i*4+3] = 0x0;
|
||||||
|
}
|
||||||
|
dmx_universe[128] = 0;
|
||||||
|
odr |= (1<<5);
|
||||||
|
break;
|
||||||
|
case MODE_RGB:
|
||||||
|
odr |= (1<<5) | (1<<6) | (1<<7);
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
dmx_universe[i*4] =poti_vals->pot_vals_filtered[0];
|
||||||
|
dmx_universe[i*4+1] = poti_vals->pot_vals_filtered[1];
|
||||||
|
dmx_universe[i*4+2] = poti_vals->pot_vals_filtered[2];
|
||||||
|
dmx_universe[i*4+3] = 0x0;
|
||||||
|
}
|
||||||
|
dmx_universe[128] = 0;
|
||||||
|
break;
|
||||||
|
case MODE_WHITE_DISCRETE:
|
||||||
|
odr |= (1<<5);
|
||||||
|
for (i = 0; i < 32; i++) {
|
||||||
|
dmx_universe[i*4] = 0;
|
||||||
|
dmx_universe[i*4+1] = 0;
|
||||||
|
dmx_universe[i*4+2] = 0;
|
||||||
|
dmx_universe[i*4+3] = 0;
|
||||||
|
}
|
||||||
|
dmx_universe[128] = gamma_corr(poti_vals->pot_vals_filtered[0]);
|
||||||
|
break;
|
||||||
|
case MODE_ANIMATION:
|
||||||
|
animation_process(&led_animation, dmx_universe);
|
||||||
|
break;
|
||||||
|
case MODE_DMX_SHUTDOWN:
|
||||||
|
port_expander_set_leds(0xFF);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_tick = tick;
|
||||||
|
GPIOA->ODR = odr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool filtered_poti_vals_equal(const struct poti_values *p1, const struct poti_values *p2)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
bool ret = true;
|
||||||
|
|
||||||
|
for (i = 0; i < POTI_COUNT; i++) {
|
||||||
|
if (p1->pot_vals_filtered[i] != p2->pot_vals_filtered[i]) {
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Check if a color mode requires continous updates
|
||||||
|
*
|
||||||
|
* @param mode Color mode input
|
||||||
|
* @return true Color mode requires continous updates
|
||||||
|
* @return false Color mode does not reuqire continuous update
|
||||||
|
*/
|
||||||
|
static bool mode_is_continuous(enum color_mode mode)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
switch (mode) {
|
||||||
|
case MODE_ANIMATION:
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
uint8_t i2c_command[2];
|
int i;
|
||||||
uint8_t port;
|
uint8_t port;
|
||||||
uint32_t odr;
|
uint8_t button_pressed;
|
||||||
enum color_mode mode = MODE_RED;
|
enum color_mode mode = MODE_WHITE_DISCRETE;
|
||||||
|
enum color_mode old_mode = MODE_BLUE;
|
||||||
struct poti_values poti_vals;
|
struct poti_values poti_vals;
|
||||||
|
struct poti_values old_poti_vals;
|
||||||
|
bool buttons_released_since_dual_press = true;
|
||||||
|
|
||||||
setup_pins();
|
setup_pins();
|
||||||
i2c_init();
|
dmx_init(dmx_universe, sizeof(dmx_universe), GPIOA, 2u, 2000u, 10u, 5u);
|
||||||
dmx_init(dmx_universe, sizeof(dmx_universe), GPIOA, 2u, 2300u, 10u, 5u);
|
|
||||||
poti_init_adc();
|
poti_init_adc();
|
||||||
|
port_expander_init();
|
||||||
|
|
||||||
|
port_expander_set_leds(1 << 4);
|
||||||
|
|
||||||
/* Setup Systick for 1ms ticks */
|
/* Setup Systick for 1ms ticks */
|
||||||
SysTick_Config(48000000UL/1000);
|
SysTick_Config(48000000UL/1000);
|
||||||
|
|
||||||
GPIOA->ODR |= (1<<5) | (1<<7);
|
|
||||||
|
|
||||||
/* Setup PCA */
|
for (i = 0; i < sizeof(dmx_universe); i++) {
|
||||||
i2c_command[0] = PCA9555_REG_CONFIG1;
|
dmx_universe[i] = 0x00;
|
||||||
i2c_command[1] = 0x00;
|
}
|
||||||
i2c_write(PCA9555_ADDR, i2c_command, 2u);
|
|
||||||
|
|
||||||
i2c_command[0] = PCA9555_REG_CONFIG0;
|
|
||||||
i2c_command[1] = 0xFF;
|
|
||||||
i2c_write(PCA9555_ADDR, i2c_command, 2u);
|
|
||||||
|
|
||||||
dmx_stream_start();
|
dmx_stream_start();
|
||||||
|
|
||||||
dmx_universe[0] = 0x55;
|
|
||||||
dmx_universe[1] = 0x50;
|
|
||||||
|
|
||||||
/* Blink the LEDs */
|
|
||||||
while (1) {
|
while (1) {
|
||||||
systick_wait_ms(10);
|
systick_wait_ms(20);
|
||||||
poti_get_values(&poti_vals);
|
poti_get_values(&poti_vals);
|
||||||
i2c_read(PCA9555_ADDR, PCA9555_REG_IN_PORT0, &port, 1u);
|
port = port_expander_get_buttons();
|
||||||
i2c_command[0] = PCA9555_REG_OUT_PORT1;
|
|
||||||
i2c_command[1] = ~port;
|
/* Isolate lowest set bit. This prevents edge cases where multipe switches are pressed */
|
||||||
i2c_write(PCA9555_ADDR, i2c_command, 2u);
|
button_pressed = 0u;
|
||||||
odr = GPIOA->ODR;
|
for (i = 0; i < 8; i++) {
|
||||||
odr &= ~((1<<5) | (1<<6) | (1<<7));
|
if (port & 0x1) {
|
||||||
if (port & (1<<0)) {
|
button_pressed = i + 1u;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
port >>= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button_pressed) {
|
||||||
|
if (!buttons_released_since_dual_press)
|
||||||
|
button_pressed = 0u;
|
||||||
|
} else {
|
||||||
|
buttons_released_since_dual_press = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (button_pressed) {
|
||||||
|
case 1:
|
||||||
mode = MODE_RED;
|
mode = MODE_RED;
|
||||||
}
|
break;
|
||||||
if (port & (1<<1)) {
|
case 2:
|
||||||
mode = MODE_GREEN;
|
mode = MODE_GREEN;
|
||||||
}
|
break;
|
||||||
if (port & (1<<2)) {
|
case 3:
|
||||||
mode = MODE_BLUE;
|
mode = MODE_BLUE;
|
||||||
}
|
break;
|
||||||
if (port & (1<<3)) {
|
case 4:
|
||||||
mode = MODE_RGB;
|
mode = MODE_RGB;
|
||||||
}
|
break;
|
||||||
if (port & (1<<4)) {
|
case 5:
|
||||||
mode = MODE_WHITE_DISCRETE;
|
mode = MODE_WHITE_DISCRETE;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
switch (mode) {
|
|
||||||
case MODE_RED:
|
|
||||||
case MODE_GREEN:
|
|
||||||
case MODE_BLUE:
|
|
||||||
for (int i = 0; i < 32; i++) {
|
|
||||||
dmx_universe[i*4] = mode == MODE_RED ? poti_vals.pot_vals_filtered[0] : 0;
|
|
||||||
dmx_universe[i*4+1] = mode == MODE_GREEN ? poti_vals.pot_vals_filtered[0] : 0;
|
|
||||||
dmx_universe[i*4+2] = mode == MODE_BLUE ? poti_vals.pot_vals_filtered[0] : 0;
|
|
||||||
dmx_universe[i*4+3] = 0x0;
|
|
||||||
}
|
|
||||||
dmx_universe[128] = 0;
|
|
||||||
odr |= (1<<5);
|
|
||||||
break;
|
break;
|
||||||
case MODE_RGB:
|
case 8:
|
||||||
odr |= (1<<5) | (1<<6) | (1<<7);
|
animation_reset(&led_animation);
|
||||||
for (int i = 0; i < 32; i++) {
|
mode = MODE_ANIMATION;
|
||||||
dmx_universe[i*4] =poti_vals.pot_vals_filtered[0];
|
|
||||||
dmx_universe[i*4+1] = poti_vals.pot_vals_filtered[1];
|
|
||||||
dmx_universe[i*4+2] = poti_vals.pot_vals_filtered[2];
|
|
||||||
dmx_universe[i*4+3] = 0x0;
|
|
||||||
}
|
|
||||||
dmx_universe[128] = 0;
|
|
||||||
break;
|
|
||||||
case MODE_WHITE_DISCRETE:
|
|
||||||
odr |= (1<<5);
|
|
||||||
for (int i = 0; i < 32; i++) {
|
|
||||||
dmx_universe[i*4] = 0;
|
|
||||||
dmx_universe[i*4+1] = 0;
|
|
||||||
dmx_universe[i*4+2] = 0;
|
|
||||||
dmx_universe[i*4+3] = 0;
|
|
||||||
}
|
|
||||||
dmx_universe[128] = gamma8[poti_vals.pot_vals_filtered[0]];
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIOA->ODR = odr;
|
/* Check for special case: 1 + 5 pressed simultaneously*/
|
||||||
|
if ((port & ((1<<0 | (1<<4)))) == ((1<<4) | (1<<0))) {
|
||||||
|
/* Prevent nomal logic from triggering on this */
|
||||||
|
button_pressed = 0;
|
||||||
|
|
||||||
|
/* set mode to DMX off and disable DMX */
|
||||||
|
mode = MODE_DMX_SHUTDOWN;
|
||||||
|
buttons_released_since_dual_press = false;
|
||||||
|
dmx_stream_stop();
|
||||||
|
} else if (mode != old_mode && old_mode == MODE_DMX_SHUTDOWN && buttons_released_since_dual_press) {
|
||||||
|
/* Wakeup DMX */
|
||||||
|
dmx_stream_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (button_pressed)
|
||||||
|
port_expander_set_leds((1 << (button_pressed - 1)));
|
||||||
|
|
||||||
|
if (mode != old_mode || !filtered_poti_vals_equal(&poti_vals, &old_poti_vals) ||
|
||||||
|
mode_is_continuous(mode)) {
|
||||||
|
/* The values changed. Update the DMX frame */
|
||||||
|
process_mode(mode, &poti_vals);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Move to old values. Used to detect changes */
|
||||||
|
old_mode = mode;
|
||||||
|
memcpy(&old_poti_vals, &poti_vals, sizeof(struct poti_values));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
63
pca9555.c
Normal file
63
pca9555.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include <pca9555.h>
|
||||||
|
#include <i2c.h>
|
||||||
|
|
||||||
|
static void pca_write_register(uint8_t reg, uint8_t value)
|
||||||
|
{
|
||||||
|
uint8_t i2c_command[2];
|
||||||
|
|
||||||
|
i2c_command[0] = reg;
|
||||||
|
i2c_command[1] = value;
|
||||||
|
i2c_write(PCA9555_I2C_ADDR, i2c_command, 2u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t pca_read_register(uint8_t reg)
|
||||||
|
{
|
||||||
|
uint8_t val = 0;
|
||||||
|
|
||||||
|
i2c_read(PCA9555_I2C_ADDR, reg, &val, 1u);
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_expander_init(void)
|
||||||
|
{
|
||||||
|
i2c_init();
|
||||||
|
|
||||||
|
/* Port 0: Input for buttons */
|
||||||
|
pca_write_register(PCA9555_REG_CONFIG0, 0xFF);
|
||||||
|
|
||||||
|
/* Port 1: Output for LEDs */
|
||||||
|
pca_write_register(PCA9555_REG_CONFIG1, 0x00);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t port_expander_get_buttons(void)
|
||||||
|
{
|
||||||
|
return pca_read_register(PCA9555_REG_IN_PORT0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_expander_set_leds(uint8_t leds)
|
||||||
|
{
|
||||||
|
pca_write_register(PCA9555_REG_OUT_PORT1, ~leds);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t port_expander_get_leds(void)
|
||||||
|
{
|
||||||
|
return ~pca_read_register(PCA9555_REG_OUT_PORT1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void port_expander_set_single_led(uint8_t pos, uint8_t val)
|
||||||
|
{
|
||||||
|
uint8_t port_reg = 0;
|
||||||
|
|
||||||
|
if (pos > 7)
|
||||||
|
return;
|
||||||
|
|
||||||
|
val = val ? 1 : 0;
|
||||||
|
val = (val << pos);
|
||||||
|
|
||||||
|
port_reg = port_expander_get_leds();
|
||||||
|
port_reg &= ~(1 << pos);
|
||||||
|
port_reg |= val;
|
||||||
|
|
||||||
|
port_expander_set_leds(port_reg);
|
||||||
|
}
|
11
poti.c
11
poti.c
@ -50,8 +50,8 @@ void poti_init_adc(void)
|
|||||||
}
|
}
|
||||||
ADC1->CHSELR = reg;
|
ADC1->CHSELR = reg;
|
||||||
|
|
||||||
/* Setup sample time (71.5 cycles) */
|
/* Setup sample time (239.5 cycles) */
|
||||||
ADC1->SMPR = ADC_SMPR_SMP_2 | ADC_SMPR_SMP_1;
|
ADC1->SMPR = ADC_SMPR_SMP_2 | ADC_SMPR_SMP_1 | ADC_SMPR1_SMPR_0;
|
||||||
|
|
||||||
/* Setup ADC clock (PCLK / 4) */
|
/* Setup ADC clock (PCLK / 4) */
|
||||||
ADC1->CFGR2 = ADC_CFGR2_CKMODE_1;
|
ADC1->CFGR2 = ADC_CFGR2_CKMODE_1;
|
||||||
@ -73,6 +73,8 @@ void poti_init_adc(void)
|
|||||||
DMA_CCR_CIRC | DMA_CCR_TCIE | DMA_CCR_EN;
|
DMA_CCR_CIRC | DMA_CCR_TCIE | DMA_CCR_EN;
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable Interrupt with lower priority. Prevents jitter on the DMX lines */
|
||||||
|
NVIC_SetPriority(DMA1_Channel1_IRQn, 1);
|
||||||
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
|
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
|
||||||
|
|
||||||
/* Start the conversion */
|
/* Start the conversion */
|
||||||
@ -87,8 +89,9 @@ void poti_get_values(struct poti_values *out_val)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
for (i = 0; i < POTI_COUNT; i++) {
|
for (i = 0; i < POTI_COUNT; i++) {
|
||||||
out_val->current_pot_vals[i] = adc_raw_values[i];
|
/* return iverted values, because of potentiometer polarities */
|
||||||
out_val->pot_vals_filtered[i] = adc_moving_avg_out[i];
|
out_val->current_pot_vals[i] = ~adc_raw_values[i];
|
||||||
|
out_val->pot_vals_filtered[i] = ~adc_moving_avg_out[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include <systick.h>
|
#include <systick.h>
|
||||||
|
#include <stm32f0xx.h>
|
||||||
|
|
||||||
volatile uint32_t global_systick = 0;
|
volatile uint32_t global_systick = 0;
|
||||||
volatile uint32_t systick_wait_counter;
|
volatile uint32_t systick_wait_counter;
|
||||||
@ -7,7 +8,8 @@ void systick_wait_ms(uint32_t ms)
|
|||||||
{
|
{
|
||||||
systick_wait_counter = ms;
|
systick_wait_counter = ms;
|
||||||
|
|
||||||
while (systick_wait_counter > 0);
|
while (systick_wait_counter > 0)
|
||||||
|
__WFI();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t systick_get_global_tick(void)
|
uint32_t systick_get_global_tick(void)
|
||||||
|
Loading…
Reference in New Issue
Block a user