Code:
// gcc com.c -o com
// gcc -Wall com.c /usr/lib/libm.a -o com
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <time.h>
#include <math.h>
char devicename[] = "/dev/ttyS0";
volatile int READY = 1;
int serial;
struct termios oldtio, newtio; //place for old and new port settings for serial port
struct sigaction saio; //definition of signal action
#define MAX_CHANS 48
#define SEQ_LEN 1000
struct state {
char ch[MAX_CHANS];
};
struct state event[SEQ_LEN];
/***************************************************************************
* Incoming signal handler... called when previous block has been sent *
***************************************************************************/
void signal_handler_IO (int status)
{
READY = 1;
// printf("received SIGIO signal.\n");
}
void ser_puts(char *x)
{
int i;
char buf[MAX_CHANS*2+2] = {0x7e, 0x80}; // Packet header SYNC byte plus address/control byte
char *dest = buf+2;
// Append dimmer byte values to the packet header
// Bytes with special meaning 0x7d (Pad), 0x7e (Sync), 0x7f (Escape) are escaped by preceding with 0x7f
for (i = 0; i < MAX_CHANS; i++) {
switch (x[i]) {
case 0x7f: *dest++ = 0x7f; *dest++ = 0x31; break;
case 0x7e: *dest++ = 0x7f; *dest++ = 0x30; break;
case 0x7d: *dest++ = 0x7f; *dest++ = 0x2f; break;
default: *dest++ = x[i];
}
}
while(!READY) ; // Wait until previous buffer has been sent
READY = 0;
write(serial, buf, dest - buf); //write bytes to the port
}
void wait(unsigned msecs)
{
struct timespec req, rem;
req.tv_sec = msecs/1000;
req.tv_nsec = (msecs % 1000) * 1000000;
while (nanosleep(&req, &rem) == -1) {
if ((rem.tv_sec == 0) && (rem.tv_nsec < 1000)) return;
req = rem;
}
}
int min(int x, int y)
{
if (x < y) return x;
return y;
}
void init_serial(void)
{
//open the device(com port) to be non-blocking (read will return immediately)
serial = open(devicename, O_RDWR | O_NOCTTY | O_NONBLOCK);
if (serial < 0) {
perror(devicename);
exit(-1);
}
//install the serial handler before making the device asynchronous
saio.sa_handler = signal_handler_IO;
sigemptyset(&saio.sa_mask); //saio.sa_mask = 0;
saio.sa_flags = 0;
saio.sa_restorer = NULL;
sigaction(SIGIO,&saio,NULL);
// allow the process to receive SIGIO
fcntl(serial, F_SETOWN, getpid());
// Make the file descriptor asynchronous (the manual page says only
// O_APPEND and O_NONBLOCK, will work with F_SETFL...)
fcntl(serial, F_SETFL, FASYNC);
tcgetattr(serial, &oldtio); // save current port settings
// set new port settings for canonical input processing
newtio.c_cflag = B57600 | CS8 | CLOCAL;
newtio.c_iflag = IGNPAR;
newtio.c_oflag = 0;
newtio.c_lflag = 0; //ICANON;
newtio.c_cc[VMIN]=1;
newtio.c_cc[VTIME]=0;
tcflush(serial, TCIFLUSH);
tcsetattr(serial, TCSANOW, &newtio);
}
void board_test(char *ch, int i)
{
// LEDs on first board
ch[1] = i; // Channel 1 -- sawtooth /|
ch[4] = 0xff - i; // Channel 4 -- sawtooth |\ x
ch[5] = (i & 0x10) ? 0xff : 0; // Channel 5 -- square wave 50/50 duty cycle 5Hz
ch[6] = (i & 0x30) ? 0 : 0xff; // Channel 6 -- square wave 25/75 duty cycle 2.5Hz
// LEDs on 2nd board do the same as first board
ch[25] = i;
ch[28] = 0xff - i;
ch[29] = (i & 0x10) ? 0xff : 0;
ch[30] = (i & 0x10) ? 0 : 0xff;
// Test all PICs
ch[0] = (i & 0x10) ? 0xff : 0; // Channel 0 of PIC 0 -- square wave 50/50 duty cycle 5Hz
ch[8] = (i & 0x20) ? 0xff : 0; // Channel 0 of PIC 1 -- square wave 50/50 duty cycle 2.5Hz
ch[16] = (i & 0x30) ? i : 0; // Channel 0 of PIC 2 -- sawtooth + square wave 50/50 duty cycle 5Hz
ch[9] = 0xff - i;
ch[17] = (i & 0x10) ? 0xff : 0;
ch[18] = (i & 0x10) ? 0 : 0xff;
}
void blink_all(char *ch, int i)
{
int x;
for (x = 0; x < 12; x++) {
ch[x] = (i & 0x20) ? 0 : 0xff;
}
}
void sequence_on_off(char *ch, int i)
{
ch[0] = ch[1] = (((i >> 2) % 6) != 0) ? 0 : 0xff;
ch[2] = ch[3] = (((i >> 2) % 6) != 1) ? 0 : 0xff;
ch[4] = ch[5] = (((i >> 2) % 6) != 2) ? 0 : 0xff;
ch[6] = ch[7] = (((i >> 2) % 6) != 3) ? 0 : 0xff;
ch[8] = ch[9] = (((i >> 2) % 6) != 4) ? 0 : 0xff;
ch[10] = ch[11] = (((i >> 2) % 6) != 5) ? 0 : 0xff;
}
void sequence_pole_1_of_4(char *ch, int i)
{
ch[12] = (((i >> 2) % 4) != 0) ? 0 : 0xff;
ch[13] = (((i >> 2) % 4) != 1) ? 0 : 0xff;
ch[14] = (((i >> 2) % 4) != 2) ? 0 : 0xff;
ch[15] = (((i >> 2) % 4) != 3) ? 0 : 0xff;
}
void sequence_pole_3_of_4(char *ch, int i)
{
ch[12] = (((i >> 2) % 4) == 0) ? 0 : 0xff;
ch[13] = (((i >> 2) % 4) == 1) ? 0 : 0xff;
ch[14] = (((i >> 2) % 4) == 2) ? 0 : 0xff;
ch[15] = (((i >> 2) % 4) == 3) ? 0 : 0xff;
}
void sequence_white(char *ch, int i)
{
ch[16] = (((i >> 2) % 6) != 0) ? 0 : 0xff;
ch[17] = (((i >> 2) % 6) != 1) ? 0 : 0xff;
ch[18] = (((i >> 2) % 6) != 2) ? 0 : 0xff;
ch[19] = (((i >> 2) % 6) != 3) ? 0 : 0xff;
ch[20] = (((i >> 2) % 6) != 4) ? 0 : 0xff;
ch[21] = (((i >> 2) % 6) != 5) ? 0 : 0xff;
}
void twinkle_white(char *ch, int x)
{
int i;
for (i = 16; i < 22; i++) {
if (rand() < RAND_MAX / 4) continue;
ch[i] = rand() * (100.0 / RAND_MAX);
}
}
void sequence_fade(char *ch, int deg)
{
int i;
for (i = 0; i < 6; i++) {
int deg_diff = min(abs(i * 60 - deg)*1.5, 90);
int brightness = cos(deg_diff * M_PI / 180) * 0xff;
ch[i*2] = ch[i*2+1] = brightness;
}
}
void binary_by_strand(char *ch, int i)
{
ch[0] = ch[1] = (i & 0x04) ? 0 : 0xff;
ch[2] = ch[3] = (i & 0x08) ? 0 : 0xff;
ch[4] = ch[5] = (i & 0x10) ? 0 : 0xff;
ch[6] = ch[7] = (i & 0x20) ? 0 : 0xff;
ch[8] = ch[9] = (i & 0x40) ? 0 : 0xff;
ch[10] = ch[11] = (i & 0x80) ? 0 : 0xff;
}
void blue_green(char *ch, int i)
{
ch[0] = 0xff;
ch[2] = 0xff;
ch[4] = 0xff;
ch[6] = 0xff;
ch[8] = 0xff;
ch[10] = 0xff;
ch[1] = 0;
ch[3] = 0;
ch[5] = 0;
ch[7] = 0;
ch[9] = 0;
ch[11] = 0;
}
void red_yellow(char *ch, int i)
{
ch[0] = 0;
ch[2] = 0;
ch[4] = 0;
ch[6] = 0;
ch[8] = 0;
ch[10] = 0;
ch[1] = 0xff;
ch[3] = 0xff;
ch[5] = 0xff;
ch[7] = 0xff;
ch[9] = 0xff;
ch[11] = 0xff;
}
int main(int argc, char *argv[])
{
int i;
char ch[MAX_CHANS];
init_serial();
memset(ch, 0, sizeof(ch));
srand(time(0));
while(1) {
for (i = 0; i < 360; i += 10) {
printf("%3d\r", i); fflush(stdout);
blink_all(ch, i);
sequence_pole_3_of_4(ch, i);
twinkle_white(ch, i);
ser_puts(ch);
wait(100);
}
}
printf("\nDone\n");
memset(ch, 0, sizeof(ch));
ser_puts(ch);
wait(250);
// restore old port settings
tcsetattr(serial, TCSANOW,&oldtio);
close(serial); //close the com port
return 0;
} //end of main
Bookmarks