created git repo for libfn

This commit is contained in:
Steffen Vogel 2010-10-31 22:07:24 +01:00
commit 40e9691497
10 changed files with 821 additions and 0 deletions

105
color.h Normal file
View file

@ -0,0 +1,105 @@
/* vim:ts=4 sts=4 et tw=80
*
* fnordlicht firmware
*
* for additional information please
* see http://lochraster.org/fnordlichtmini
*
* (c) by Alexander Neumann <alexander@bumpern.de>
* Lars Noschinski <lars@public.noschinski.de>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
#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 {
struct {
uint8_t red;
uint8_t green;
uint8_t blue;
};
uint8_t rgb[3];
};
};
struct rgb_color_offset_t {
union {
struct {
int8_t red;
int8_t green;
int8_t blue;
};
int8_t rgb[3];
};
};
struct hsv_color_t
{
union {
struct {
uint16_t hue;
uint8_t saturation;
uint8_t value;
};
uint8_t hsv[4];
};
};
struct hsv_color_offset_t {
int16_t hue;
int8_t saturation;
int8_t value;
};
struct dual_color_t
{
struct rgb_color_t rgb;
struct hsv_color_t hsv;
};
union color_t
{
/* rgb */
struct {
union {
struct {
uint8_t red;
uint8_t green;
uint8_t blue;
};
uint8_t rgb[3];
};
/* marker, 0xff if rgb */
uint8_t rgb_marker;
};
/* hsv */
struct {
uint8_t saturation;
uint8_t value;
/* 0 <= hue <= 349, otherwise rgb might be assumed */
uint16_t hue;
};
};
#endif

BIN
fnctl Executable file

Binary file not shown.

290
fnctl.c Normal file
View file

@ -0,0 +1,290 @@
#include <stdio.h> /* Standard input/output definitions */
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include "libfn.h"
typedef struct { char * name; char * description; uint8_t cmd; } command_t;
static 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},
{"stop", "stop color changing", REMOTE_CMD_STOP},
{"start", "start program", REMOTE_CMD_START_PROGRAM},
{"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 */
};
static struct option long_options[] = {
{"delay", required_argument, 0, 'd'},
{"step", required_argument, 0, 's'},
{"address", required_argument, 0, 'a'},
{"mask", required_argument, 0, 'm'},
{"slot", required_argument, 0, 't'},
{"pause", required_argument, 0, 'p'},
{"color", required_argument, 0, 'c'},
{"help", required_argument, 0, 'h'},
{"port", required_argument, 0, 'P'},
{"host", required_argument, 0, 'H'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0} /* stop condition for iterator */
};
void print_cmd(struct remote_msg_t * msg) {
printf("sending: ");
int i;
for (i = 0; i < REMOTE_MSG_LEN; i++) {
printf("%X", *((uint8_t *) msg+i));
}
printf("\n");
}
void usage(char ** argv) {
printf("usage: %s command [options]\n\n", argv[0]);
printf(" following commands are available:\n");
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++;
}
printf("\n");
printf(" following options are available\n");
struct option * op = long_options;
while (op->name) {
printf("\t--%s,%s-%c\n", op->name, (strlen(op->name) < 5) ? "\t\t" : "\t", op->val);
op++;
}
}
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;
uint8_t step = 255;
uint8_t slot = 0;
uint8_t delay = 0;
uint8_t pause = 0;
char host[255];
char port[255] = "7970";
int verbose;
struct rgb_color_t color;
struct remote_msg_t msg;
memset(&msg, 0, sizeof msg);
/* connection */
int fd;
struct addrinfo hints, *res;
struct termios oldtio;
/* parse command */
if (argc <= 1) {
fprintf(stderr, "command required\n");
usage(argv);
exit(-1);
}
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);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c) {
case 'a':
address = atoi(optarg);
break;
case 'm':
fprintf(stderr, "not yet implemented\n");
exit(-1);
break;
case 's':
step = atoi(optarg);
break;
case 'd':
delay = atoi(optarg);
break;
case 't':
slot = atoi(optarg);
break;
case 'p':
pause = atoi(optarg);
break;
case 'c':
color = parse_color(optarg);
break;
case 'H': {
char * ps = strrchr(optarg, ':');
if (ps) { /* with port: "localhost:1234" */
strcpy(port, optarg + 1);
strncpy(host, optarg, ps - optarg);
}
else { /* without port */
strcpy(host, optarg);
}
}
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);
break;
case 'v':
verbose = 1;
break;
case 'h':
case '?':
usage(argv);
exit((c == '?') ? -1 : 0);
}
}
/* check address */
if (strlen(host) == 0 && address != 255 && address > fn_count_devices(fd)) {
fprintf(stderr, "device with address %d not found\n", address);
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));
}
switch (cp->cmd) {
case REMOTE_CMD_FADE_RGB: {
struct remote_msg_fade_rgb_t * param = (void *) &msg;
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 rgb_color_offset_t ofs = {50,50,50};
param->step = step;
param->delay = delay;
param->rgb = ofs;
}
break;
case REMOTE_CMD_SAVE_RGB: {
struct remote_msg_save_rgb_t * param = (void *) &msg;
param->slot = slot;
param->step = step;
param->delay = delay;
param->pause = pause;
param->color = color;
}
break;
case REMOTE_CMD_START_PROGRAM: {
struct remote_msg_start_program_t * param = (void *) &msg;
}
break;
case REMOTE_CMD_STOP: {
struct remote_msg_stop_t * param = (void *) &msg;
}
break;
case REMOTE_CMD_POWERDOWN:
case REMOTE_CMD_BOOTLOADER:
break;
default:
fprintf(stderr, "unknown subcomand: %s\n", argv[1]);
usage(argv);
exit(-1);
}
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);
}
return 0;
}

BIN
fnctl.o Normal file

Binary file not shown.

BIN
fnvum/dump Normal file

Binary file not shown.

BIN
fnvum/fnvum Executable file

Binary file not shown.

85
fnvum/fnvum.c Normal file
View file

@ -0,0 +1,85 @@
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <pulse/simple.h>
#include <pulse/error.h>
#include <pulse/gccmacro.h>
#define BUFSIZE 1024
static ssize_t loop_write(int fd, const void*data, size_t size) {
ssize_t ret = 0;
while (size > 0) {
ssize_t r;
if ((r = write(fd, data, size)) < 0)
return r;
if (r == 0)
break;
ret += r;
data = (const uint8_t*) data + r;
size -= (size_t) r;
}
return ret;
}
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;
int error;
/* Create the recording stream */
if (!(s = pa_simple_new(NULL, "fnordlicht VU Meter", PA_STREAM_RECORD, NULL, "record", &ss, NULL, NULL, &error))) {
fprintf(stderr, __FILE__": pa_simple_new() failed: %s\n", pa_strerror(error));
exit(-1);
}
for (;;) {
uint32_t level = 0;
for (int i = 0;i < 40;i++) {
int16_t buf[BUFSIZE];
/* Record some data ... */
if (pa_simple_read(s, buf, sizeof(buf), &error) < 0) {
fprintf(stderr, __FILE__": pa_simple_read() failed: %s\n", pa_strerror(error));
exit(-1);
}
/* for (int i = 0; i < sizeof(buf); i++) {
int16_t sample = *(buf+i);
if (sample < 0)
sample *= -1;
level += sample;
}*/
if (loop_write(STDOUT_FILENO, buf, sizeof(buf)) != sizeof(buf)) {
fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno));
exit(-1);
}
}
// printf("%i\n", level);
}
}

77
libfn.c Normal file
View file

@ -0,0 +1,77 @@
#include "libfn.h"
#include <unistd.h>
#include <sys/ioctl.h>
#include <stdio.h>
struct termios fn_init(int fd) {
struct termios oldtio, newtio;
tcgetattr(fd, &oldtio); /* save current port settings */
memset(&newtio, 0, sizeof(newtio));
newtio.c_cflag = CS8 | CLOCAL | CREAD;
newtio.c_iflag= 0;
newtio.c_oflag= 0;
newtio.c_lflag= 0;
newtio.c_cc[VMIN] = 1;
newtio.c_cc[VTIME] = 5;
cfsetispeed(&newtio, FN_BAUDRATE);
cfsetospeed(&newtio, FN_BAUDRATE);
tcflush(fd, TCIFLUSH);
tcsetattr(fd, TCSANOW, &newtio);
fn_sync(fd);
return oldtio;
}
size_t fn_send(int fd, struct remote_msg_t * msg) {
return write(fd, msg, REMOTE_MSG_LEN);
}
/*size_t fn_send_mask(int mask, struct remote_msg_t * msg) {
return 0;
}*/
size_t fn_sync(int fd) {
uint8_t sync[REMOTE_SYNC_LEN+1];
memset(sync, REMOTE_SYNC_BYTE, REMOTE_SYNC_LEN);
sync[REMOTE_SYNC_LEN] = 0; /* address byte */
return write(fd, sync, REMOTE_SYNC_LEN+1);
}
uint8_t fn_count_devices(int fd) {
struct remote_msg_pull_int_t msg;
memset(&msg, 0, REMOTE_MSG_LEN);
msg.address = 0;
msg.cmd = REMOTE_CMD_PULL_INT;
msg.delay = 1;
while (1) {
fn_send(fd, (struct remote_msg_t *) &msg);
usleep(25000);
if (fn_get_int(fd)) {
msg.address++;
usleep(25000);
}
else {
break;
}
}
return msg.address;
}
int fn_get_int(int fd) {
int i;
ioctl (fd, TIOCMGET, &i);
return i & FN_INT_LINE;
}

22
libfn.h Normal file
View file

@ -0,0 +1,22 @@
#ifndef LIBFN_H
#define LIBFN_H
#include <stdint.h>
#include <termios.h>
#include <string.h>
#include "color.h"
#include "remote-proto.h"
#define FN_BAUDRATE B19200
#define FN_MAX_DEVICES 254
#define FN_INT_LINE TIOCM_CTS
struct termios fn_init(int fd);
size_t fn_send(int fd, struct remote_msg_t * msg);
size_t fn_send_mask(int mask, struct remote_msg_t * msg);
size_t fn_sync(int fd);
int fn_get_int(int fd);
uint8_t fn_count_devices(int fd);
#endif

242
remote-proto.h Normal file
View file

@ -0,0 +1,242 @@
/* vim:ts=4 sts=4 et tw=80
*
* fnordlicht firmware
*
* for additional information please
* see http://lochraster.org/fnordlichtmini
*
* (c) by Alexander Neumann <alexander@bumpern.de>
*
* 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 <http://www.gnu.org/licenses/>.
*/
#ifndef __REMOTE_PROTO_COMMON
#define __REMOTE_PROTO_COMMON 1
#define REMOTE_MSG_LEN 15
#define REMOTE_SYNC_LEN 15
#define REMOTE_SYNC_BYTE 0x1b
/* 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,
* minus 1 for startup_mode enum */
#define REMOTE_STARTUP_MAX_PARAMSIZE 11
/* normal commands */
#define REMOTE_CMD_FADE_RGB 0x01
#define REMOTE_CMD_FADE_HSV 0x02
#define REMOTE_CMD_SAVE_RGB 0x03
#define REMOTE_CMD_SAVE_HSV 0x04
#define REMOTE_CMD_SAVE_CURRENT 0x05
#define REMOTE_CMD_CONFIG_OFFSETS 0x06
#define REMOTE_CMD_START_PROGRAM 0x07
#define REMOTE_CMD_STOP 0x08
#define REMOTE_CMD_MODIFY_CURRENT 0x09
#define REMOTE_CMD_PULL_INT 0x0A
#define REMOTE_CMD_CONFIG_STARTUP 0x0B
#define REMOTE_CMD_POWERDOWN 0x0C
#define REMOTE_CMD_RESYNC 0x1b
/* bootloader commands */
#define REMOTE_CMD_BOOTLOADER 0x80
#define REMOTE_CMD_BOOT_CONFIG 0x81
#define REMOTE_CMD_BOOT_INIT 0x82
#define REMOTE_CMD_BOOT_DATA 0x83
#define REMOTE_CMD_CRC_CHECK 0x84
#define REMOTE_CMD_CRC_FLASH 0x85
#define REMOTE_CMD_FLASH 0x86
#define REMOTE_CMD_ENTER_APP 0x87
#define REMOTE_ADDR_BROADCAST 0xff
/* normal commands */
struct remote_msg_t
{
uint8_t address;
uint8_t cmd;
uint8_t data[REMOTE_MSG_LEN-2];
};
struct remote_msg_fade_rgb_t
{
uint8_t address;
uint8_t cmd;
uint8_t step;
uint8_t delay;
struct rgb_color_t color;
};
struct remote_msg_fade_hsv_t
{
uint8_t address;
uint8_t cmd;
uint8_t step;
uint8_t delay;
struct hsv_color_t color;
};
struct remote_msg_save_rgb_t
{
uint8_t address;
uint8_t cmd;
uint8_t slot;
uint8_t step;
uint8_t delay;
uint16_t pause;
struct rgb_color_t color;
};
struct remote_msg_save_hsv_t
{
uint8_t address;
uint8_t cmd;
uint8_t slot;
uint8_t step;
uint8_t delay;
uint16_t pause;
struct hsv_color_t color;
};
struct remote_msg_save_current_t
{
uint8_t address;
uint8_t cmd;
uint8_t slot;
uint8_t step;
uint8_t delay;
uint16_t pause;
};
struct remote_msg_config_offsets_t
{
uint8_t address;
uint8_t cmd;
int8_t step;
int8_t delay;
int16_t hue;
uint8_t saturation;
uint8_t value;
};
struct remote_msg_start_program_t
{
uint8_t address;
uint8_t cmd;
uint8_t script;
// union program_params_t params;
};
struct remote_msg_stop_t
{
uint8_t address;
uint8_t cmd;
uint8_t fade;
};
struct remote_msg_modify_current_t
{
uint8_t address;
uint8_t cmd;
uint8_t step;
uint8_t delay;
struct rgb_color_offset_t rgb;
struct hsv_color_offset_t hsv;
};
struct remote_msg_pull_int_t
{
uint8_t address;
uint8_t cmd;
uint8_t delay;
};
enum startup_mode_t
{
STARTUP_NOTHING = 0,
STARTUP_PROGRAM = 1,
};
/* startup parameters including mode, size: 12 byte */
struct startup_parameters_t
{
enum startup_mode_t mode;
union {
/* raw access to data, size: 11 byte */
uint8_t raw[11];
/* structure for startup_mode == STARTUP_PROGRAM
* size: 11 byte */
struct {
uint8_t program;
uint8_t program_parameters[10];
};
};
};
struct remote_msg_config_startup_t
{
uint8_t address;
uint8_t cmd;
struct startup_parameters_t params;
};
/* bootloader commands */
#define BOOTLOADER_MAGIC_BYTE1 0x6b
#define BOOTLOADER_MAGIC_BYTE2 0x56
#define BOOTLOADER_MAGIC_BYTE3 0x27
#define BOOTLOADER_MAGIC_BYTE4 0xfc
struct remote_msg_bootloader_t
{
uint8_t address;
uint8_t cmd;
uint8_t magic[4];
};
struct remote_msg_boot_config_t
{
uint8_t address;
uint8_t cmd;
uint16_t start_address;
uint8_t buffersize;
};
struct remote_msg_boot_data_t
{
uint8_t address;
uint8_t cmd;
uint8_t data[REMOTE_MSG_LEN-2];
};
struct remote_msg_boot_crc_check_t
{
uint8_t address;
uint8_t cmd;
uint16_t len;
uint16_t checksum;
uint8_t delay;
};
struct remote_msg_boot_crc_flash_t
{
uint8_t address;
uint8_t cmd;
uint16_t start;
uint16_t len;
uint16_t checksum;
uint8_t delay;
};
#endif