split democode stuff

This commit is contained in:
Olaf Rempel 2012-03-11 15:49:41 +01:00
parent d2e2bb1695
commit 8d8a50a4f7
7 changed files with 332 additions and 138 deletions

162
democode.c Normal file
View File

@ -0,0 +1,162 @@
/***************************************************************************
* some RGB demo modes *
* *
* Copyright (C) 2011 - 2012 by Olaf Rempel *
* razzor AT kopf MINUS tisch DOT de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License, *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdint.h>
#include <string.h>
#include "rgb16mpm.h"
struct dm001data {
uint8_t pos;
uint8_t dir;
uint16_t ramp;
uint8_t decay[16][3];
};
struct dm002data {
uint16_t ramp;
};
struct dm003data {
uint8_t step;
uint8_t pos[3];
uint8_t dir[3];
};
union demodata {
struct dm001data dm001;
struct dm002data dm002;
struct dm003data dm003;
};
static union demodata demo;
static uint16_t demomode000(void)
{
return 0;
}
static uint16_t demomode001(void)
{
struct dm001data *dm = &demo.dm001;
dm->pos = sequence_chase(dm->pos, &dm->dir, nvram_data.channels);
dm->ramp = color_ramp(dm->ramp +8, chan_value[dm->pos]);
color_div(chan_value[dm->pos], 4, dm->decay[dm->pos]);
uint8_t chan;
for (chan = 0; chan < 16; chan++) {
if (chan != dm->pos) {
color_sub(chan_value[chan], dm->decay[chan], chan_value[chan]);
}
}
return 50;
}
static uint16_t demomode002(void)
{
struct dm002data *dm = &demo.dm002;
uint8_t color[3];
dm->ramp = color_ramp(dm->ramp +1, color);
uint8_t chan;
for (chan = 0; chan < 16; chan++) {
chan_value[chan][COLOR_RED] = color[COLOR_RED];
chan_value[chan][COLOR_GREEN] = color[COLOR_GREEN];
chan_value[chan][COLOR_BLUE] = color[COLOR_BLUE];
}
return 0;
}
static uint16_t demomode003(void)
{
struct dm003data *dm = &demo.dm003;
uint8_t color;
dm->step++;
if (dm->step == 2) {
dm->step = 0;
}
for (color = 0; color < 3; color++) {
if (dm->step == 0) {
dm->pos[color] = sequence_chase(dm->pos[color], &dm->dir[color], nvram_data.channels);
}
uint8_t chan;
for (chan = 0; chan < 16; chan++) {
if (chan == dm->pos[color]) {
chan_value[chan][color] = 0xFF;
} else if (chan_value[chan][color] > 16) {
chan_value[chan][color] -= 16;
} else {
chan_value[chan][color] = 0;
}
}
}
return 50;
}
uint16_t (* demomode_run)(void) = demomode000;
void demomode_init(uint8_t mode)
{
memset(&demo, 0x00, sizeof(union demodata));
memset(chan_value, 0x00, sizeof(chan_value));
switch (mode) {
case 0x00:
/* load initial values from eeprom */
memcpy(chan_value, nvram_data.initialRGB, sizeof(chan_value));
demomode_run = demomode000;
break;
case 0x01:
/* rgb chase */
demo.dm001.dir = 1;
demomode_run = demomode001;
break;
case 0x02:
/* one color, all channes, rgb fader */
demomode_run = demomode002;
break;
case 0x03:
/* three color chaser */
demo.dm003.pos[COLOR_RED] = 0;
demo.dm003.pos[COLOR_GREEN] = 9;
demo.dm003.pos[COLOR_BLUE] = 9;
demo.dm003.dir[COLOR_RED] = 1;
demo.dm003.dir[COLOR_GREEN] = 1;
demo.dm003.dir[COLOR_BLUE] = 0;
demomode_run = demomode003;
break;
default:
/* stay black */
demomode_run = demomode000;
break;
}
}

124
demohelper.c Normal file
View File

@ -0,0 +1,124 @@
/***************************************************************************
* helper functions for demo modes *
* *
* Copyright (C) 2011 - 2012 by Olaf Rempel *
* razzor AT kopf MINUS tisch DOT de *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; version 2 of the License, *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#include <stdint.h>
#include <string.h>
#include "rgb16mpm.h"
uint8_t sequence_chase(uint8_t old_value, uint8_t *dir, uint16_t mask)
{
uint8_t value = old_value;
do {
value = (*dir) ? value +1 : value -1;
value &= 0x0F;
if (value == 0x00 || value == 0x0F) {
*dir = (value == 0x00);
}
} while (!((1<<value) & mask) || value == old_value);
return value;
}
uint16_t color_ramp(uint16_t value, uint8_t *color)
{
uint8_t col1 = (value & 0xFF);
uint8_t col2 = 0xFF - col1;
switch (value >> 8) {
default:
value = 0x0000;
/* no break */
case 0: /* red: on, green: ramp up, blue: off */
color[0] = 0xFF;
color[1] = col1;
color[2] = 0x00;
break;
case 1: /* red: ramp down, green: on, blue:off */
color[0] = col2;
color[1] = 0xFF;
color[2] = 0x00;
break;
case 2: /* red: off, green: on, blue: ramp up */
color[0] = 0x00;
color[1] = 0xFF;
color[2] = col1;
break;
case 3: /* red: off, green: ramp down: blue: on */
color[0] = 0x00;
color[1] = col2;
color[2] = 0xFF;
break;
case 4: /* red: ramp up, green: off, blue: on */
color[0] = col1;
color[1] = 0x00;
color[2] = 0xFF;
break;
case 5: /* red: on, green: off, blue: ramp down */
color[0] = 0xFF;
color[1] = 0x00;
color[2] = col2;
break;
}
return value;
}
void color_add(uint8_t *color1, uint8_t *color2, uint8_t *output)
{
uint8_t i;
for (i = 0; i < 3; i++) {
uint16_t tmp = color1[i] + color2[i];
output[i] = (tmp & 0xFF00) ? 0xFF : tmp;
}
}
void color_sub(uint8_t *color1, uint8_t *color2, uint8_t *output)
{
uint8_t i;
for (i = 0; i < 3; i++) {
uint16_t tmp = color1[i] - color2[i];
output[i] = (tmp & 0xFF00) ? 0x00 : tmp;
}
}
void color_div(uint8_t *color, uint8_t div, uint8_t *output)
{
uint8_t i;
for (i = 0; i < 3; i++) {
if (color[i] != 0) {
output[i] = color[i] / div;
if (output[i] == 0) {
output[i] = 0x01;
}
} else {
output[i] = 0x00;
}
}
}

View File

@ -77,7 +77,7 @@ void eeprom_write(void)
}
/* read nvram from eeprom and check crc */
void eeprom_read(void)
void eeprom_read(uint8_t defaults)
{
uint8_t i;
uint16_t crc = 0x0000;
@ -90,7 +90,7 @@ void eeprom_read(void)
}
/* if nvram content is invalid, overwrite with defaults */
if ((nvram_data.nvram_size != sizeof(struct _nvdata)) || (crc != 0x0000)) {
if ((nvram_data.nvram_size != sizeof(struct _nvdata)) || (crc != 0x0000) || defaults) {
memcpy_P(&nvram_data, &nvram_defaults, sizeof(struct _nvdata));
eeprom_write();
}

141
main.c
View File

@ -41,147 +41,40 @@
* PD3 -> /LED
*/
uint8_t sequence_chase(uint8_t old_value, uint8_t *dir, uint16_t mask)
{
uint8_t value = old_value;
do {
value = (*dir) ? value +1 : value -1;
value &= 0x0F;
if (value == 0x00 || value == 0x0F) {
*dir = (value == 0x00);
}
} while (!((1<<value) & mask) || value == old_value);
return value;
}
uint16_t color_ramp(uint16_t value, uint8_t *color)
{
uint8_t col1 = (value & 0xFF);
uint8_t col2 = 0xFF - col1;
switch (value >> 8) {
default:
value = 0x0000;
/* no break */
case 0: /* red: on, green: ramp up, blue: off */
color[0] = 0xFF;
color[1] = col1;
color[2] = 0x00;
break;
case 1: /* red: ramp down, green: on, blue:off */
color[0] = col2;
color[1] = 0xFF;
color[2] = 0x00;
break;
case 2: /* red: off, green: on, blue: ramp up */
color[0] = 0x00;
color[1] = 0xFF;
color[2] = col1;
break;
case 3: /* red: off, green: ramp down: blue: on */
color[0] = 0x00;
color[1] = col2;
color[2] = 0xFF;
break;
case 4: /* red: ramp up, green: off, blue: on */
color[0] = col1;
color[1] = 0x00;
color[2] = 0xFF;
break;
case 5: /* red: on, green: off, blue: ramp down */
color[0] = 0xFF;
color[1] = 0x00;
color[2] = col2;
break;
}
return value;
}
void color_add(uint8_t *color1, uint8_t *color2, uint8_t *output)
{
uint8_t i;
for (i = 0; i < 3; i++) {
uint16_t tmp = color1[i] + color2[i];
output[i] = (tmp & 0xFF00) ? 0xFF : tmp;
}
}
void color_sub(uint8_t *color1, uint8_t *color2, uint8_t *output)
{
uint8_t i;
for (i = 0; i < 3; i++) {
uint16_t tmp = color1[i] - color2[i];
output[i] = (tmp & 0xFF00) ? 0x00 : tmp;
}
}
void color_div(uint8_t *color, uint8_t div, uint8_t *output)
{
uint8_t i;
for (i = 0; i < 3; i++) {
if (color[i] != 0) {
output[i] = color[i] / div;
if (output[i] == 0) {
output[i] = 0x01;
}
} else {
output[i] = 0x00;
}
}
}
static uint8_t chan_decay[16][3];
int main(void) __attribute__ ((noreturn));
int main(void)
{
DDRD = (1<<LED);
PORTD = (1<<LED);
eeprom_read();
/* timer1: FCPU/1024 */
TCCR1B = (1<<CS12) | (1<<CS10);
TCNT1 = 0x0000;
eeprom_read(1);
rgb_init();
mpm_init();
demomode_init(nvram_data.demomode);
sei();
uint8_t x = 0;
uint8_t xdir = 1;
uint16_t ramp = 0;
/* wait for complete update */
rgb_update(COLOR_MASK, 1);
uint16_t wait = 0;
while (1) {
mpm_check_transfer();
/* wait for complete update */
rgb_update(COLOR_MASK, 1);
/* no delay or timeout reached */
if (wait == 0 || (TIFR & (1<<TOV1))) {
TIFR = (1<<TOV1);
_delay_ms(50);
/* execute periodic democode */
wait = demomode_run();
rgb_update(COLOR_MASK, UPDATE_BLOCKING);
#if 1
x = sequence_chase(x, &xdir, 0x1F1F);
ramp = color_ramp(ramp +8, chan_value[x]);
color_div(chan_value[x], 4, chan_decay[x]);
uint8_t i;
for (i = 0; i < 16; i++) {
if (x != i) {
color_sub(chan_value[i], chan_decay[i], chan_value[i]);
if (wait > 0) {
/* x * 8 / (8MHz/1024) */
TCNT1 = 0xFFFF - (wait << 3);
}
}
#endif
}
}

View File

@ -234,7 +234,7 @@ void mpm_check_transfer(void)
mpm_reply(rx_cmd, cause, 0, NULL);
if (rx_cmd == CMD_WRITE_RAW_COLOR) {
rgb_update(COLOR_MASK, 1);
rgb_update(COLOR_MASK, UPDATE_BLOCKING);
} else {
eeprom_write();

View File

@ -2,7 +2,7 @@
#define _RGB16MPM_H_
#define F_CPU 8000000
#include <util/delay.h>
//#include <util/delay.h>
#define ROW1 PORTB1 /* RED */
#define ROW2 PORTB0 /* GREEN */
@ -30,16 +30,20 @@
struct _nvdata {
uint16_t nvram_size; /* first */
uint16_t channels; /* connected channels */
uint8_t initialRGB[16][3]; /* initial color values */
uint8_t demomode; /* initial demo mode */
uint16_t nvram_crc; /* last */
};
#define NVRAM_DEFAULTS {\
.channels = 0x1F1F, \
.initialRGB = { { 0xFF, 0x00, 0x00 }, { 0xFF, 0x80, 0x00 }, { 0xFF, 0xFF, 0x00 }, { 0x80, 0xFF, 0x00 }, \
{ 0x00, 0xFF, 0x00 }, { 0x00, 0xFF, 0x80 }, { 0x00, 0xFF, 0xFF }, { 0x00, 0x80, 0xFF }, \
{ 0x00, 0x00, 0xFF }, { 0x80, 0x00, 0xFF }, { 0xFF, 0x00, 0xFF }, { 0xFF, 0x00, 0x80 }, \
{ 0x20, 0x20, 0x20 }, { 0x40, 0x40, 0x40 }, { 0x80, 0x80, 0x80 }, { 0xFF, 0xFF, 0xFF } \
}, \
.demomode = 0x03, \
};
/* eeprom.c vars */
@ -47,7 +51,18 @@ extern struct _nvdata nvram_data;
/* eeprom.c funcs */
void eeprom_write(void);
void eeprom_read(void);
void eeprom_read(uint8_t defaults);
/* democode.c funcs */
void demomode_init(uint8_t mode);
extern uint16_t (*demomode_run)(void);
/* demohelper.c funcs */
uint8_t sequence_chase(uint8_t old_value, uint8_t *dir, uint16_t mask);
uint16_t color_ramp(uint16_t value, uint8_t *color);
void color_add(uint8_t *color1, uint8_t *color2, uint8_t *output);
void color_sub(uint8_t *color1, uint8_t *color2, uint8_t *output);
void color_div(uint8_t *color, uint8_t div, uint8_t *output);
/* mpmctrl.c funcs */
void mpm_init(void);
@ -58,6 +73,10 @@ extern uint8_t chan_value[16][3];
/* rgbctrl.c funcs */
void rgb_init(void);
uint8_t rgb_update(uint8_t dirty_mask, uint8_t blocking);
uint8_t rgb_update(uint8_t dirty_mask, uint8_t update_mode);
#define UPDATE_NONE 0x00
#define UPDATE_PARTIAL 0x01
#define UPDATE_BLOCKING 0x02
#endif /* _RGB16MPM_H_ */

View File

@ -262,13 +262,13 @@ static void calculate_timer_values(uint8_t color)
*pData++ = ((chan_init >> 8) & 0xFF); /* PORTC */
}
uint8_t rgb_update(uint8_t dirty_mask, uint8_t blocking)
uint8_t rgb_update(uint8_t dirty_mask, uint8_t update_mode)
{
static uint8_t chan_dirty;
chan_dirty |= (dirty_mask & COLOR_MASK);
do {
while ((chan_dirty != 0) && (update_mode != UPDATE_NONE)) {
if ((chan_dirty & (1<<COLOR_RED)) && (nextColor == COLOR_BLUE)) {
calculate_timer_values(COLOR_RED);
chan_dirty &= ~(1<<COLOR_RED);
@ -281,11 +281,10 @@ uint8_t rgb_update(uint8_t dirty_mask, uint8_t blocking)
calculate_timer_values(COLOR_BLUE);
chan_dirty &= ~(1<<COLOR_BLUE);
} else if (!blocking) {
} else if (update_mode != UPDATE_BLOCKING) {
break;
}
} while (chan_dirty);
};
return chan_dirty;
}
@ -306,8 +305,5 @@ void rgb_init(void)
/* timer0, FCPU/64, overflow interrupt */
TCCR0 = (1<<CS01) | (1<<CS00); /* FCPU/64 */
TIMSK = (1<<TOIE0);
/* load initial values from eeprom */
memcpy(chan_value, nvram_data.initialRGB, sizeof(chan_value));
}