From 2ea30ea3d3872e624825261b29bfd174dbb12b57 Mon Sep 17 00:00:00 2001 From: Steffen Vogel Date: Wed, 26 Jan 2011 17:58:25 +0100 Subject: [PATCH] rewrite --- README | 6 +- color.h | 4 - fnctl | Bin 27702 -> 0 bytes fnctl.c | 327 ++++++++++++++------- fnctl.o | Bin 3048 -> 0 bytes fnvum.c | 181 ++++++++++++ fnvum/README | 1 - fnvum/fnvum | Bin 14177 -> 0 bytes fnvum/fnvum.c | 128 -------- iso-226_equal_loudness/iso_266_50_phon.ods | Bin 0 -> 12469 bytes iso-226_equal_loudness/iso_266_50_phon.svg | 201 +++++++++++++ iso-226_equal_loudness/lindos_1.png | Bin 0 -> 78031 bytes libfn.h | 1 + remote-proto.h | 7 +- replay.eeprom | 22 ++ static_programs.h | 81 +++++ 16 files changed, 722 insertions(+), 237 deletions(-) delete mode 100755 fnctl delete mode 100644 fnctl.o create mode 100644 fnvum.c delete mode 100644 fnvum/README delete mode 100755 fnvum/fnvum delete mode 100644 fnvum/fnvum.c create mode 100644 iso-226_equal_loudness/iso_266_50_phon.ods create mode 100644 iso-226_equal_loudness/iso_266_50_phon.svg create mode 100644 iso-226_equal_loudness/lindos_1.png create mode 100644 replay.eeprom create mode 100644 static_programs.h diff --git a/README b/README index c080d77..4807e01 100644 --- a/README +++ b/README @@ -4,7 +4,11 @@ This is a simple c lib for controlling your fnordlichts. It's written by Steffen Vogel and licenced under GPLv3 or newer. Please contact me by mail for bug reports or annotations. -The source is including a small cli program and a vu meter to show your audio level on the lights. To connect the fnordlichts to your computer you need a serial port or an USB to RS232 adapter and a RS232 to TTL level shifter (MAX232). Connect your CTS line to the interrupt line of the fnordlicht bus to be able to count the devices on the bus. + + +fnctl & fnvum +------------------------------------------------------------------------------- +The source is including a small cli program and a vu meter to show your audio level on the lights. diff --git a/color.h b/color.h index f7c64ce..d0d901a 100644 --- a/color.h +++ b/color.h @@ -26,10 +26,6 @@ #ifndef COLOR_H #define COLOR_H -#if defined(PWM_CHANNELS) && PWM_CHANNELS != 3 -#error "PWM_CHANNELS is not 3, this is unsupported!" -#endif - struct rgb_color_t { union { diff --git a/fnctl b/fnctl deleted file mode 100755 index a807bcae1a60064dd2f53440f69360c47f01b812..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 27702 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 0xA0) */ +#define LOCAL_CMD_EEPROM 0xA0 +#define LOCAL_CMD_COUNT 0xA1 + +#define DEFAULT_HOST "localhost" +#define DEFAULT_PORT "7970" +#define DEFAULT_DEVICE "/dev/ttyUSB0" + +struct command_t { + char * name; + char * description; + uint8_t cmd; +}; + +enum connection_t { + RS232, + NET +}; + +static struct command_t commands[] = { {"fade", "set color/fade to color", REMOTE_CMD_FADE_RGB}, {"save", "save color to EEPROM", REMOTE_CMD_SAVE_RGB}, {"modify", "modify current color", REMOTE_CMD_MODIFY_CURRENT}, @@ -20,7 +38,9 @@ static command_t commands[] = { {"powerdown", "power down the device", REMOTE_CMD_POWERDOWN}, {"config", "configure startup & offsets", REMOTE_CMD_CONFIG_OFFSETS}, {"reset", "reset fnordlichter", REMOTE_CMD_BOOTLOADER}, - {0, 0} /* stop condition for iterator */ + {"eeprom", "put sequence to EEPROM", LOCAL_CMD_EEPROM}, + {"count", "count modules on the bus", LOCAL_CMD_COUNT}, + {0} /* stop condition for iterator */ }; static struct option long_options[] = { @@ -28,16 +48,30 @@ static struct option long_options[] = { {"step", required_argument, 0, 's'}, {"address", required_argument, 0, 'a'}, {"mask", required_argument, 0, 'm'}, - {"slot", required_argument, 0, 't'}, + {"slot", required_argument, 0, 'w'}, {"pause", required_argument, 0, 'p'}, {"color", required_argument, 0, 'c'}, + {"start", required_argument, 0, 'f'}, + {"end", required_argument, 0, 't'}, + {"repeat", required_argument, 0, 'r'}, {"help", required_argument, 0, 'h'}, {"port", required_argument, 0, 'P'}, {"host", required_argument, 0, 'H'}, + {"filename", required_argument, 0, 'F'}, {"verbose", no_argument, 0, 'v'}, - {0, 0, 0, 0} /* stop condition for iterator */ + {0} /* stop condition for iterator */ }; +struct rgb_color_t parse_color(char * identifier) { + struct rgb_color_t color; + if (strlen(identifier) != 6) { + fprintf(stderr, "invalid color definition: %s", identifier); + } + + sscanf(identifier, "%2x%2x%2x", (unsigned int *) (&color.red), (unsigned int *) (&color.green), (unsigned int *) (&color.blue)); + return color; +} + void print_cmd(struct remote_msg_t * msg) { printf("sending: "); @@ -52,7 +86,7 @@ void usage(char ** argv) { printf("usage: %s command [options]\n\n", argv[0]); printf(" following commands are available:\n"); - command_t * cp = commands; + struct command_t * cp = commands; while (cp->name) { printf("\t%s%s%s\n", cp->name, (strlen(cp->name) < 7) ? "\t\t" : "\t", cp->description); cp++; @@ -68,17 +102,6 @@ void usage(char ** argv) { } } -struct rgb_color_t parse_color(char * color_def) { - struct rgb_color_t color; - - if (strlen(color_def) != 6) - fprintf(stderr, "invalid color definition: %s", color_def); - - sscanf(color_def, "%2x%2x%2x", (unsigned int *) (&color.red), (unsigned int *) (&color.green), (unsigned int *) (&color.blue)); - - return color; -} - int main(int argc, char ** argv) { /* options */ uint8_t address = 255; @@ -86,12 +109,19 @@ int main(int argc, char ** argv) { uint8_t slot = 0; uint8_t delay = 0; uint8_t pause = 0; - char host[255]; - char port[255] = "7970"; - int verbose; + + char mask[254] = ""; + char filename[1024] = ""; + + enum connection_t con_mode = RS232; + char host[255] = DEFAULT_HOST; + char port[255] = DEFAULT_PORT; + char device[255] = DEFAULT_DEVICE; + int verbose = 0; struct rgb_color_t color; struct remote_msg_t msg; + union program_params_t params; memset(&msg, 0, sizeof msg); /* connection */ @@ -106,15 +136,17 @@ int main(int argc, char ** argv) { exit(-1); } - command_t * cp = commands; - while (cp->name && strcmp(cp->name, argv[1]) != 0) { cp++; } + struct command_t * cp = commands; + while (cp->name && strcmp(cp->name, argv[1]) != 0) { + cp++; + } /* parse cli arguments */ while (1) { /* getopt_long stores the option index here. */ int option_index = 0; - int c = getopt_long(argc, argv, "hva:m:d:s:d:p:c:P:H:", long_options, &option_index); + int c = getopt_long(argc, argv, "hva:m:f:d:t:s:f:w:r:d:p:c:P:H:F:", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) @@ -126,8 +158,7 @@ int main(int argc, char ** argv) { break; case 'm': - fprintf(stderr, "not yet implemented\n"); - exit(-1); + strcpy(mask, optarg); break; case 's': @@ -138,7 +169,7 @@ int main(int argc, char ** argv) { delay = atoi(optarg); break; - case 't': + case 'w': slot = atoi(optarg); break; @@ -149,6 +180,30 @@ int main(int argc, char ** argv) { case 'c': color = parse_color(optarg); break; + + case 'f': + params.replay.start = atoi(optarg); + break; + + case 't': + params.replay.end = atoi(optarg); + break; + + case 'r': + if (strcmp("none", optarg) == 0) { + params.replay.repeat = REPEAT_NONE; + } + else if (strcmp("start", optarg) == 0) { + params.replay.repeat = REPEAT_START; + } + else if (strcmp("reverse", optarg) == 0) { + params.replay.repeat = REPEAT_REVERSE; + } + else { + fprintf(stderr, "invalid --repeat value: %s\n", optarg); + exit(-1); + } + break; case 'H': { char * ps = strrchr(optarg, ':'); @@ -159,34 +214,16 @@ int main(int argc, char ** argv) { else { /* without port */ strcpy(host, optarg); } + con_mode = NET; + break; } - memset(&hints, 0, sizeof hints); - hints.ai_family = AF_UNSPEC; /* both IPv4 & IPv6 */ - hints.ai_socktype = SOCK_STREAM; - - getaddrinfo(host, port, &hints, &res); - - fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); - connect(fd, res->ai_addr, res->ai_addrlen); - - if (fd < 0) { - perror(port); - exit(-1); - } - - fn_sync(fd); - usleep(200000); - break; - case 'P': - fd = open(optarg, O_RDWR | O_NOCTTY); - if (fd < 0) { - perror(optarg); - exit(-1); - } - - oldtio = fn_init(fd); + strcpy(port, optarg); + break; + + case 'F': + strcpy(filename, optarg); break; case 'v': @@ -200,91 +237,179 @@ int main(int argc, char ** argv) { } } + /* connect to fnordlichter */ + if (con_mode == NET) { + if (verbose) printf("connect via net: %s:%s\n", host, port); + memset(&hints, 0, sizeof hints); + hints.ai_family = AF_UNSPEC; /* both IPv4 & IPv6 */ + hints.ai_socktype = SOCK_STREAM; + + getaddrinfo(host, port, &hints, &res); + + fd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); + connect(fd, res->ai_addr, res->ai_addrlen); + if (fd < 0) { + perror(host); + exit(-1); + } + } + else { + if (verbose) printf("connect via rs232: %s\n", device); + fd = open(device, O_RDWR | O_NOCTTY); + if (fd < 0) { + perror(port); + exit(-1); + } + oldtio = fn_init(fd); + } + + fn_sync(fd); + /* check address */ - if (strlen(host) == 0 && address != 255 && address > fn_count_devices(fd)) { - fprintf(stderr, "device with address %d not found\n", address); + if (address > FN_MAX_DEVICES+1) { + fprintf(stderr, "sorry, the fnordlicht bus can't address more the %d devices\n", FN_MAX_DEVICES); exit(-1); } - if (verbose) { - printf("command: %s: %s\n", cp->name, cp->description); - printf("port: %s\n", port); - printf("host: %s\n", host); - printf("address: %d\n", address); - printf("found %d fnordlichts\n", fn_count_devices(fd)); - } + if (verbose) printf("command: %s (%s)\n", cp->name, cp->description); switch (cp->cmd) { + /* remote commands */ case REMOTE_CMD_FADE_RGB: { - struct remote_msg_fade_rgb_t * param = (void *) &msg; + struct remote_msg_fade_rgb_t * cmsg = (void *) &msg; + + cmsg->step = step; + cmsg->delay = delay; + cmsg->color = color; - param->step = step; - param->delay = delay; - param->color = color; - } break; + } case REMOTE_CMD_MODIFY_CURRENT: { - struct remote_msg_modify_current_t * param = (void *) &msg; + struct remote_msg_modify_current_t * cmsg = (void *) &msg; - struct rgb_color_offset_t ofs = {50,50,50}; + struct rgb_color_offset_t ofs = {50, 50, 50}; - param->step = step; - param->delay = delay; - param->rgb = ofs; + cmsg->step = step; + cmsg->delay = delay; + cmsg->rgb = ofs; - } break; + } case REMOTE_CMD_SAVE_RGB: { - struct remote_msg_save_rgb_t * param = (void *) &msg; + struct remote_msg_save_rgb_t * cmsg = (void *) &msg; - param->slot = slot; - param->step = step; - param->delay = delay; - param->pause = pause; - param->color = color; - - } + cmsg->slot = slot; + cmsg->step = step; + cmsg->delay = delay; + cmsg->pause = pause; + cmsg->color = color; + break; + } case REMOTE_CMD_START_PROGRAM: { - struct remote_msg_start_program_t * param = (void *) &msg; - - } + struct remote_msg_start_program_t * cmsg = (void *) &msg; + + cmsg->script = 2; + cmsg->params = params; + break; - - case REMOTE_CMD_STOP: { - struct remote_msg_stop_t * param = (void *) &msg; - } - break; - + + /* no special parameters */ + case REMOTE_CMD_STOP: case REMOTE_CMD_POWERDOWN: case REMOTE_CMD_BOOTLOADER: break; + /* local commands */ + case LOCAL_CMD_COUNT: + printf("%d\n", fn_count_devices(fd)); + break; + + case LOCAL_CMD_EEPROM: { + FILE *eeprom_file = fopen(filename, "r"); + char row[1024]; + + if (eeprom_file == NULL) { + perror ("error opening eeprom file"); + exit(-1); + } + + while(!feof(eeprom_file)) { + if (fgets(row, 1024, eeprom_file) && *row != '#') { /* ignore comments */ + struct remote_msg_save_rgb_t msg; + memset(&msg, 0, sizeof msg); + + msg.cmd = REMOTE_CMD_SAVE_RGB; + + sscanf(row, "%d;%d;%2x%2x%2x;%d;%d;%d", + (unsigned int *) &msg.slot, + (unsigned int *) &msg.address, + (unsigned int *) (&color.red), + (unsigned int *) (&color.green), + (unsigned int *) (&color.blue), + (unsigned int *) &msg.step, + (unsigned int *) &msg.delay, + (unsigned int *) &msg.pause + ); + + int p = fn_send(fd, (struct remote_msg_t *) &msg); + if (verbose) print_cmd((struct remote_msg_t *) &msg); + if (p < 0) { + fprintf(stderr, "failed on writing %d bytes to fnordlichts", REMOTE_MSG_LEN); + exit(-1); + } + } + } + break; + } + default: fprintf(stderr, "unknown subcomand: %s\n", argv[1]); usage(argv); exit(-1); } - msg.address = address; - msg.cmd = cp->cmd; + /* send remote commands to bus */ + if (cp->cmd < 0xA0) { + if (verbose) printf("address: %d\n", address); + msg.address = address; + msg.cmd = cp->cmd; - int i = fn_send(fd, &msg); - if (i < 0) - fprintf(stderr, "failed on writing %d bytes to fnordlichts", REMOTE_MSG_LEN); - - if (verbose) { - print_cmd(&msg); - } - - if (strlen(host) == 0) { - /* reset port to old state */ - tcsetattr(fd, TCSANOW, &oldtio); + int c = strlen(mask); + if (c > 0) { + if (verbose) printf("sending to mask: %s\n", mask); + int i; + for (i = 0; i < c; i++) { + if (mask[i] == '1') { + msg.address = i; + int p = fn_send(fd, &msg); + if (verbose) print_cmd(&msg); + if (p < 0) { + fprintf(stderr, "failed on writing %d bytes to fnordlichts", REMOTE_MSG_LEN); + exit(-1); + } + } + else if (mask[i] != '0') { + fprintf(stderr, "invalid mask! only '0' and '1' are allowed\n"); + exit(-1); + } + } + } + else { + int p = fn_send(fd, &msg); + if (verbose) print_cmd(&msg); + if (p < 0) { + fprintf(stderr, "failed on writing %d bytes to fnordlichts", REMOTE_MSG_LEN); + exit(-1); + } + } } + + if (con_mode == RS232) tcsetattr(fd, TCSANOW, &oldtio); /* reset port to old state */ return 0; } diff --git a/fnctl.o b/fnctl.o deleted file mode 100644 index ef28e66ede61100bdddfa6827ffe0bf70bc7a335..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3048 zcmbuBUuYaf9LIl`q$bv;IctT`3La=}g=V!Rimjlr$J!D9fQ3VRkY#UgFFBIiJ9g*N zR9c$aCSZVb}`=7XQvJ|Ir=-h=0EDSEs|` z@9StvtT}Mx7z$ZzKRU6_nu|o)mGvRkgqwXh1&cRVDbWME#rDdTiz{$Gw_AuB5nk(H z6CP{X*PDfv_^t}ER%-z>H|>?5_Fy6w-;rZ>GG%c}7B9|YjvY8EV3K~>{u%=mze$Tx zsTbGzo8?Wr4X|Nf!>irdv=>N#@G8M2ycRke_T|im{aI(^hTSg5_SKOe>}$*R(!<-7 zs%P4f#c%&5)-uK#jo$ehpBT7p;A21H9Jn~D7@99cY2rJ(wqy;9@>dKNPC+05a6gF|h6`kp~f7qydpczbJqHow$2{Foqkv!e4=?iSJVFtO9h z3;kKw;{H4btK@PQtYQ>_71ojtF0<+f7z=9Lx6XV}7>l^;&7gpW`O{80bgRCa=KtCp zCZO}$UAIg)DXsWz(kC;Z`Q#q%!HBcR=?<_=wZZlTUNp}Tb+C;l23|l*Tzfr;$OSo0 z%DN^!|8a~^&i^|81dgTo)6=Q>U&oln7Ht?dwNKQgv1+{HPa;d#9ubU6=u$^(>Ge}T zy>^nX%Lg(mgZq%tBbAy7=Z|V8jen_edIpsK7mbf-d`og#i~f|})AY1&D$h}Qu#{fD z{^2Fb=@{$!d`f>n=6%PtM9^^ wrl)tQs^?veQ*9LA*0{d!gYrE|hR(9mAJRDemr;CN<4Px# diff --git a/fnvum.c b/fnvum.c new file mode 100644 index 0000000..e5ff581 --- /dev/null +++ b/fnvum.c @@ -0,0 +1,181 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* third party libs */ +#include "libfn.h" +#include +#include +#include +#include +#include + +#define BUFFER_SIZE 1024 +#define SAMPLING_RATE 44100 +#define SCREEN_WIDTH (BUFFER_SIZE/2+1) +#define SCREEN_HEIGHT (SCREEN_WIDTH / 2) +#define TITLE "fnordlicht vumeter & spectrum" + +void show_level(SDL_Surface *dst, float level) { + SDL_Rect rect = dst->clip_rect; + Uint32 color = SDL_MapRGB(dst->format, 0xff, 0, 0); + Uint32 background = SDL_MapRGB(dst->format, 0, 0, 0); + + SDL_FillRect(dst, &rect, background); + + rect.w *= level; + + SDL_FillRect(dst, &rect, color); + SDL_Flip(dst); +} + +void show_spectrum(SDL_Surface * dst, complex * fft_data) { + int x, p, start, end; + double log_data[BUFFER_SIZE]; + + SDL_Rect rect; + Uint32 color = SDL_MapRGB(dst->format, 0xff, 0, 0); + Uint32 background = SDL_MapRGB(dst->format, 0, 0, 0); + + SDL_FillRect(dst, &dst->clip_rect, background); + + double ampl, db; + rect.w = 1; + + for (x = 0; x < BUFFER_SIZE/2+1; x++) { + ampl = cabs(fft_data[x]); + + rect.x = x; +// rect.h = (ampl/3000000) * SCREEN_HEIGHT; + rect.h = 10 * log10(ampl/300000) * SCREEN_HEIGHT; + rect.y = SCREEN_HEIGHT - rect.h; + + SDL_FillRect(dst, &rect, color); + } + SDL_Flip(dst); +} + +void fade_level(int fd, float level) { + struct remote_msg_fade_rgb_t fncmd; + memset(&fncmd, 0, sizeof (struct remote_msg_t)); + + fncmd.color.red = fncmd.color.green = fncmd.color.blue = (uint8_t) 255.0 * level; + fncmd.address = 255; + fncmd.cmd = REMOTE_CMD_FADE_RGB; + fncmd.step = 25; + fncmd.delay = 0; + + fn_send(fd, (struct remote_msg_t *) &fncmd); +} + +int main(int argc, char *argv[]) { + /* The sample type to use */ + static const pa_sample_spec ss = { + .format = PA_SAMPLE_S16LE, + .rate = SAMPLING_RATE, + .channels = 1 + }; + + + pa_simple *s = NULL; + SDL_Surface *screen = NULL; + SDL_Event event; + + int error, counter = 0, fd = -1; + uint32_t level; + int16_t * pcm_data; + complex * fft_data; + fftw_plan fft_plan; + + /* init fnordlichts */ + if (argc > 1) { + fd = open(argv[1], O_RDWR | O_NOCTTY); + if (fd < 0) { + perror(argv[0]); + exit(-1); + } + + fn_init(fd); + } + + /* init screen & window */ + if(SDL_Init(SDL_INIT_VIDEO) < 0) { + fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); + exit(-1); + } + + /* open sdl window */ + SDL_WM_SetCaption(TITLE, NULL); + screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, SDL_SWSURFACE|SDL_ANYFORMAT|SDL_RESIZABLE); + if (screen == NULL) { + fprintf(stderr, "Unable to set video: %s\n", SDL_GetError()); + exit(-1); + } + + /* init fftw & get buffers*/ + pcm_data = (int16_t *) malloc(BUFFER_SIZE); + fft_data = (complex *) fftw_malloc(BUFFER_SIZE * sizeof (complex)); + fft_plan = fftw_plan_dft_1d(BUFFER_SIZE, fft_data, fft_data, FFTW_FORWARD, 0); + + /* Create the recording stream */ + if (!(s = pa_simple_new(NULL, TITLE, PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) { + fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); + exit(-1); + } + pa_simple_flush(s, &error); /* flush audio buffer */ + + while (1) { + counter++; + + /* handle SDL events */ + while (SDL_PollEvent(&event)) { + if (event.type == SDL_QUIT) { + printf("Good bye!\n"); + exit(0); + } + } + + /* read PCM audio data */ + if (pa_simple_read(s, pcm_data, BUFFER_SIZE, &error) < 0) { + fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); + exit(-1); + } + + /* analyse audio data */ + uint16_t index, max = 0; + uint32_t sum = 0; + float level; + for (index = 0; index < BUFFER_SIZE; index++) { + sum += abs(pcm_data[index]); + if (abs(pcm_data[index]) > max) max = pcm_data[index]; + + fft_data[index] = (double) pcm_data[index]; + } + + /* execute fftw plan */ + fftw_execute(fft_plan); + + level = (float) sum / (BUFFER_SIZE * 32767); + + show_spectrum(screen, (complex *) fft_data); + //show_level(screen, level); + //fade_level(fd, level); + + //printf("level: %f \tsum: %d\t max: %d\n", level, sum, max); + } + + /* housekeeping */ + SDL_Quit(); + free(pcm_data); + fftw_free(fft_data); + fftw_destroy(fft_plan); + fftw_cleanup(); + + return 0; +} diff --git a/fnvum/README b/fnvum/README deleted file mode 100644 index 53ed8b7..0000000 --- a/fnvum/README +++ /dev/null @@ -1 +0,0 @@ -This is a proof of concept piece of software. Its working for me. Feel free to add options and functions.. diff --git a/fnvum/fnvum b/fnvum/fnvum deleted file mode 100755 index c326caefa72dcb0907110ecd4fbdc535bfc8b259..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14177 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 -#include -#include -#include -#include -#include - -#include "../libfn.h" -#include -#include - -#include - -#include -#include -#include - -#define BUFFER_SIZE 1024 -#define SCREEN_WIDTH 500 -#define SCREEN_HEIGHT (SCREEN_WIDTH / 20) -#define TITLE "fnordlicht vumeter" -#define DECAY 0.7 - -void show_level(SDL_Surface *dst, float level) { - SDL_Rect rect = dst->clip_rect;; - Uint32 color = SDL_MapRGB(dst->format, 0xff, 0, 0); - Uint32 background = SDL_MapRGB(dst->format, 0, 0, 0); - - SDL_FillRect(dst, &rect, background); - - rect.w *= level; - - SDL_FillRect(dst, &rect, color); - SDL_Flip(dst); -} - -int main(int argc, char*argv[]) { - /* The sample type to use */ - static const pa_sample_spec ss = { - .format = PA_SAMPLE_S16LE, - .rate = 44100, - .channels = 1 - }; - - pa_simple *s = NULL; - SDL_Surface *screen = NULL; - SDL_Event event; - - int error, counter = 0; - uint32_t level; - int16_t buffer[BUFFER_SIZE]; - - /* init fnordlichts */ - struct remote_msg_fade_rgb_t fncmd; - int fd = open("/dev/ttyUSB0", O_RDWR | O_NOCTTY); - if (fd < 0) { - perror("/dev/ttyUSB0"); - exit(-1); - } - - memset(&fncmd, 0, sizeof (struct remote_msg_t)); - fn_init(fd); - - fncmd.address = 255; - fncmd.cmd = REMOTE_CMD_FADE_RGB; - fncmd.step = 25; - fncmd.delay = 0; - - /* init screen & window */ - if(SDL_Init(SDL_INIT_VIDEO) < 0) { - fprintf(stderr, "Unable to init SDL: %s\n", SDL_GetError()); - exit(-1); - } - - SDL_WM_SetCaption(TITLE, NULL); - screen = SDL_SetVideoMode(SCREEN_WIDTH, SCREEN_HEIGHT, 16, SDL_SWSURFACE|SDL_ANYFORMAT|SDL_RESIZABLE); - if (screen == NULL) { - fprintf(stderr, "Unable to set 640x480 video: %s\n", SDL_GetError()); - exit(-1); - } - - /* Create the recording stream */ - if (!(s = pa_simple_new(NULL, TITLE, PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) { - fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error)); - exit(-1); - } - - pa_simple_flush(s, &error); /* flush audio buffer */ - while (1) { - counter++; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) { - printf("Good bye!\n"); - exit(0); - } - } - - if (pa_simple_read(s, buffer, sizeof(buffer), &error) < 0) { - fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error)); - exit(-1); - } - - int16_t * pos, max = 0; - uint32_t sum = 0; - float level; - for (pos = buffer; pos - buffer < BUFFER_SIZE; pos++) { - sum += abs(*pos); - if (abs(*pos) > max) max = abs(*pos); - } - level = (float) sum / (BUFFER_SIZE * 32767) * 1.7; - if (level > 1) level = 1; - - if (counter % (3 * 44100 / 1024) == 0) { - fn_sync(fd); - pa_simple_flush(s, &error); - printf("synced & flushed\n"); - } - - show_level(screen, level); - fncmd.color.red = fncmd.color.green = fncmd.color.blue = (uint8_t) 255.0 * level; - fn_send(fd, (struct remote_msg_t *) &fncmd); - printf("level: %d (%f) \tsum: %d\t max: %d\n", fncmd.color.red, level, sum, max); - } - - /* housekeeping */ - SDL_Quit(); - -} diff --git a/iso-226_equal_loudness/iso_266_50_phon.ods b/iso-226_equal_loudness/iso_266_50_phon.ods new file mode 100644 index 0000000000000000000000000000000000000000..0e5bc5ee6bee4185dfcc10bbf74e62f63442ed51 GIT binary patch literal 12469 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 literal 0 HcmV?d00001 diff --git a/iso-226_equal_loudness/iso_266_50_phon.svg b/iso-226_equal_loudness/iso_266_50_phon.svg new file mode 100644 index 0000000..01278c9 --- /dev/null +++ b/iso-226_equal_loudness/iso_266_50_phon.svg @@ -0,0 +1,201 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/iso-226_equal_loudness/lindos_1.png b/iso-226_equal_loudness/lindos_1.png new file mode 100644 index 0000000000000000000000000000000000000000..0b69ccdee964236fce396e27b71020b19856bafc GIT binary patch literal 78031 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 literal 0 HcmV?d00001 diff --git a/libfn.h b/libfn.h index 637b171..f621214 100644 --- a/libfn.h +++ b/libfn.h @@ -6,6 +6,7 @@ #include #include "color.h" +#include "static_programs.h" #include "remote-proto.h" #define FN_BAUDRATE B19200 diff --git a/remote-proto.h b/remote-proto.h index def8dde..bc7f0c7 100644 --- a/remote-proto.h +++ b/remote-proto.h @@ -27,6 +27,9 @@ #define REMOTE_SYNC_LEN 15 #define REMOTE_SYNC_BYTE 0x1b +/* number of color-configurations stored in EEPROM */ +#define CONFIG_EEPROM_COLORS 60 + /* max mode for startup configuration is 1 */ #define REMOTE_STARTUP_MAX_MODE 1 /* maximum parameter size (for copy loop), size of structure storage_config_t, @@ -59,7 +62,7 @@ #define REMOTE_CMD_FLASH 0x86 #define REMOTE_CMD_ENTER_APP 0x87 -#define REMOTE_ADDR_BROADCAST 0xff +#define REMOTE_ADDR_BROADCAST 0xff /* normal commands */ struct remote_msg_t @@ -135,7 +138,7 @@ struct remote_msg_start_program_t uint8_t address; uint8_t cmd; uint8_t script; -// union program_params_t params; + union program_params_t params; }; struct remote_msg_stop_t diff --git a/replay.eeprom b/replay.eeprom new file mode 100644 index 0000000..7f06cfd --- /dev/null +++ b/replay.eeprom @@ -0,0 +1,22 @@ +# This CSV file is used to easily edit the slots of your fnordlichter +# Author: Steffen Vogel +# +# There are 6 fields: +# slot | slot in the EEPROM (0-59) +# address | address of the fnordlicht on the bus (0-254, 255 for broadcast) +# color | color in hex format (ex. 'ff31A4') +# step | increment step for fading +# delay | delay between steps when fading (in 10ms) +# pause | time to wait before fading to next color (in 100ms) +# +# Lines beginning with a '#' are ignored as comments +# +# https://github.com/fd0/fnordlicht/raw/master/doc/PROTOCOL +# +#slot;address;color;step;delay;pause +0;255;ffffff;30;2;5 +1;255;000000;30;2;5 +2;255;00ff00;30;2;10 +3;255;00ffff;30;2;10 +4;255;ffff00;30;2;10 + diff --git a/static_programs.h b/static_programs.h new file mode 100644 index 0000000..3a752b9 --- /dev/null +++ b/static_programs.h @@ -0,0 +1,81 @@ +/* vim:ts=4 sts=4 et tw=80 + * + * fnordlicht firmware + * + * for additional information please + * see http://lochraster.org/fnordlichtmini + * + * (c) by Alexander Neumann + * + * This program is free software: you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 3 as published by + * the Free Software Foundation. + * + * 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, see . + */ + +#ifndef __STATIC_PROGRAMS_H +#define __STATIC_PROGRAMS_H + +#include +#include + +#define STATIC_PROGRAMS_LEN 3 + +/* configure maximal static program parameter size */ +#define PROGRAM_PARAMETER_SIZE 10 + +/* parameter structures (max 10 bytes) */ +struct colorwheel_params_t +{ + uint8_t fade_step; + uint8_t fade_delay; + uint8_t fade_sleep; + uint16_t hue_start; + int16_t hue_step; + int8_t add_addr; + uint8_t saturation; + uint8_t value; +}; + +struct random_params_t +{ + uint16_t seed; + uint8_t use_address:1; + uint8_t wait_for_fade:1; + uint8_t reserved:6; + uint8_t fade_step; + uint8_t fade_delay; + uint16_t fade_sleep; + uint8_t saturation; + uint8_t value; + uint8_t min_distance; +}; + +struct replay_params_t +{ + uint8_t start; + uint8_t end; + enum { + REPEAT_NONE = 0, + REPEAT_START = 1, + REPEAT_REVERSE = 2, + } repeat; +}; + +union program_params_t +{ + /* parameters for static programs */ + uint8_t raw[PROGRAM_PARAMETER_SIZE]; + struct colorwheel_params_t colorwheel; + struct random_params_t random; + struct replay_params_t replay; +}; + +#endif