Fridge.c

Da raspibo.
Jump to navigation Jump to search
/*   fridge.g send text and images on a Fridge Magnet display
 *   
 *   Copyright 2013 Renzo Davoli Bologna - Italy
 *   
 * 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, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * 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.
 * see <http://www.gnu.org/licenses/>.
 */

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <poll.h>

#define DISPLAYNODE 1
/* baudrate settings are defined in <asm/termbits.h>, which is
   included by <termios.h> */
#define BAUDRATE B57600            
#define _POSIX_SOURCE 1 /* POSIX compliant source */

#define FALSE 0
#define TRUE 1

const char font[][6] =
{
  {0x00,0x00,0x00,0x00,0x00,0x00}, // SPACE

  {0x00,0x00,0x00,0x4F,0x00,0x00}, // !
  {0x00,0x00,0x07,0x00,0x07,0x00}, // "
  {0x00,0x14,0x7F,0x14,0x7F,0x14}, // #
  {0x00,0x24,0x2A,0x7F,0x2A,0x12}, // $
  {0x00,0x23,0x13,0x08,0x64,0x62}, // %
  {0x00,0x36,0x49,0x55,0x22,0x50}, // &
  {0x00,0x00,0x05,0x03,0x00,0x00}, // '
  {0x00,0x00,0x1C,0x22,0x41,0x00}, // (
  {0x00,0x00,0x41,0x22,0x1C,0x00}, // )
  {0x00,0x14,0x08,0x3E,0x08,0x14}, // *
  {0x00,0x08,0x08,0x3E,0x08,0x08}, // +
  {0x00,0x00,0x50,0x30,0x00,0x00}, // ,
  {0x00,0x08,0x08,0x08,0x08,0x08}, // -
  {0x00,0x00,0x60,0x60,0x00,0x00}, // .
  {0x00,0x20,0x10,0x08,0x04,0x02}, // /

  {0x00,0x3E,0x51,0x49,0x45,0x3E}, // 0
  {0x00,0x00,0x42,0x7F,0x40,0x00}, // 1
  {0x00,0x42,0x61,0x51,0x49,0x46}, // 2
  {0x00,0x21,0x41,0x45,0x4B,0x31}, // 3
  {0x00,0x18,0x14,0x12,0x7F,0x10}, // 4
  {0x00,0x27,0x45,0x45,0x45,0x39}, // 5
  {0x00,0x3C,0x4A,0x49,0x49,0x30}, // 6
  {0x00,0x01,0x71,0x09,0x05,0x03}, // 7
  {0x00,0x36,0x49,0x49,0x49,0x36}, // 8
  {0x00,0x06,0x49,0x49,0x29,0x1E}, // 9

  {0x00,0x36,0x36,0x00,0x00,0x00}, // :
  {0x00,0x56,0x36,0x00,0x00,0x00}, // ;
  {0x00,0x08,0x14,0x22,0x41,0x00}, // <
  {0x00,0x14,0x14,0x14,0x14,0x14}, // =
  {0x00,0x00,0x41,0x22,0x14,0x08}, // >
  {0x00,0x02,0x01,0x51,0x09,0x06}, // ?
  {0x00,0x30,0x49,0x79,0x41,0x3E}, // @

  {0x00,0x7E,0x11,0x11,0x11,0x7E}, // A
  {0x00,0x7F,0x49,0x49,0x49,0x36}, // B
  {0x00,0x3E,0x41,0x41,0x41,0x22}, // C
  {0x00,0x7F,0x41,0x41,0x22,0x1C}, // D
  {0x00,0x7F,0x49,0x49,0x49,0x41}, // E
  {0x00,0x7F,0x09,0x09,0x09,0x01}, // F
  {0x00,0x3E,0x41,0x49,0x49,0x7A}, // G
  {0x00,0x7F,0x08,0x08,0x08,0x7F}, // H
  {0x00,0x00,0x41,0x7F,0x41,0x00}, // I
  {0x00,0x20,0x40,0x41,0x3F,0x01}, // J
  {0x00,0x7F,0x08,0x14,0x22,0x41}, // K
  {0x00,0x7F,0x40,0x40,0x40,0x40}, // L
  {0x00,0x7F,0x02,0x0C,0x02,0x7F}, // M
  {0x00,0x7F,0x04,0x08,0x10,0x7F}, // N
  {0x00,0x3E,0x41,0x41,0x41,0x3E}, // O
  {0x00,0x7F,0x09,0x09,0x09,0x06}, // P
  {0x00,0x3E,0x41,0x51,0x21,0x5E}, // Q
  {0x00,0x7F,0x09,0x19,0x29,0x46}, // R
  {0x00,0x46,0x49,0x49,0x49,0x31}, // S
  {0x00,0x01,0x01,0x7F,0x01,0x01}, // T
  {0x00,0x3F,0x40,0x40,0x40,0x3F}, // U
  {0x00,0x1F,0x20,0x40,0x20,0x1F}, // V
  {0x00,0x3F,0x40,0x30,0x40,0x3F}, // W
  {0x00,0x63,0x14,0x08,0x14,0x63}, // X
  {0x00,0x07,0x08,0x70,0x08,0x07}, // Y
  {0x00,0x61,0x51,0x49,0x45,0x43}, // Z

  {0x00,0x00,0x7F,0x41,0x41,0x00}, // [
  {0x00,0x02,0x04,0x08,0x10,0x20}, // backslash
  {0x00,0x00,0x41,0x41,0x7F,0x00}, // ]
  {0x00,0x04,0x02,0x01,0x02,0x04}, // ^
  {0x00,0x40,0x40,0x40,0x40,0x40}, // _
  {0x00,0x00,0x01,0x02,0x04,0x00}, // `

  {0x00,0x20,0x54,0x54,0x54,0x78}, // a
  {0x00,0x7F,0x50,0x48,0x48,0x30}, // b
  {0x00,0x38,0x44,0x44,0x44,0x20}, // c
  {0x00,0x38,0x44,0x44,0x48,0x7F}, // d
  {0x00,0x38,0x54,0x54,0x54,0x18}, // e
  {0x00,0x08,0x7E,0x09,0x01,0x02}, // f
  {0x00,0x0C,0x52,0x52,0x52,0x3E}, // g
  {0x00,0x7F,0x08,0x04,0x04,0x78}, // h
  {0x00,0x00,0x44,0x7D,0x40,0x00}, // i
  {0x00,0x20,0x40,0x44,0x3D,0x00}, // j
  {0x00,0x7F,0x10,0x28,0x44,0x00}, // k
  {0x00,0x00,0x41,0x7F,0x40,0x00}, // l
  {0x00,0x78,0x04,0x58,0x04,0x78}, // m
  {0x00,0x7C,0x08,0x04,0x04,0x78}, // n
  {0x00,0x38,0x44,0x44,0x44,0x38}, // o
  {0x00,0x7C,0x14,0x14,0x14,0x08}, // p
  {0x00,0x08,0x14,0x14,0x18,0x7C}, // q
  {0x00,0x7C,0x08,0x04,0x04,0x08}, // r
  {0x00,0x48,0x54,0x54,0x54,0x20}, // s
  {0x00,0x04,0x3F,0x44,0x40,0x20}, // t
  {0x00,0x3C,0x40,0x40,0x20,0x7C}, // u
  {0x00,0x1C,0x20,0x40,0x20,0x1C}, // v
  {0x00,0x3C,0x40,0x30,0x40,0x3C}, // w
  {0x00,0x44,0x28,0x10,0x28,0x44}, // x
  {0x00,0x0C,0x50,0x50,0x50,0x3C}, // y
  {0x00,0x44,0x64,0x54,0x4C,0x44}, // z

  {0x00,0x00,0x08,0x36,0x41,0x00}, // {
  {0x00,0x00,0x00,0x7F,0x00,0x00}, // |
  {0x00,0x00,0x41,0x36,0x08,0x00}, // }
{0x00,0x0C,0x02,0x0C,0x10,0x0C}, // ~

{0x00,0x00,0x00,0x00,0x00,0x00}
};

unsigned char screen[176][33];

void buildgraphic(void)
{
  static int status=0;
  unsigned char *s= &screen[0][0];
  unsigned char *base=s;
  int num=0;
  int c;
  while((c=getchar()) != EOF) {
    switch (status) {
      case 0:
        if (c=='{') status = 1;
        break;
      case 1:
        if (c=='0') { status = 8; break; }
        if (c>='1' && c <= '9')
          status=10;
        else
          break;
      case 10:
        if (c>='0' && c <= '9') num = (num * 10) | (c - '0');
        else if (c==',') {
          *(s++) = num; num=0; status=1;
          if (s - base >= 5808) return;
        }
        else if (c=='}') {
          *(s++) = num; num=0; status=1;
          return;
        }
        break;
      case 8:
        if (c=='x') status = 16;
        else if (c>='0' && c <= '7') num = (num << 3) | (c - '0');
        else if (c==',') {
          *(s++) = num; num=0; status=1;
          if (s - base >= 5808) return;
        }
        else if (c=='}') {
          *(s++) = num; num=0; status=1;
          return;
        }
        break;
      case 16:
        if (c>='0' && c <= '9') num = (num << 4) | (c - '0');
        else if (c>='a' && c <= 'f') num = (num << 4) | (c + 10 - 'a');
        else if (c>='A' && c <= 'F') num = (num << 4) | (c + 10 - 'A');
        else if (c==',') {
          *(s++) = num; num=0; status=1;
          if (s - base >= 5808) return;
        }
        else if (c=='}') {
          *(s++) = num; num=0; status=1;
          return;
        }
    }
  }
}

void buildscreen(void)
{
  int i;
  char buf[4096];
  for (i=0;i<22;i++) {
    int len;
    if (fgets(buf,4096,stdin) == NULL)
      return;
    if (buf[0] == '\n')
      return;
    len=strlen(buf);
    if (len>44) len=44;
    int j;
    for (j=0; j<len; j++) {
      int ch=buf[j];
      if (ch >= ' ' && ch <= '~') {
        int k;
        ch-=' ';
        for (k=0; k<6; k++) {
          int h;
          for (h=0; h<8; h++) {
            int bit=((font[ch][k]&(1<<h))!=0);
            if (bit) {
              int posx=j*6+k;
              int posy=i*8+h;
              screen[posy][posx>>3]|= 1<<(posx&0x7);
            }
          }
        }
      }
    }
  }
}

void sendit(int fd)
{
  char buf[4096];
  int i,res;
  for (i=0; i<176; i++) {
    int j;
    FILE *f=fmemopen(buf,sizeof(buf),"w");
    fprintf(f,"%d,",i);
    for (j=0; j<33; j++)
      fprintf(f,"%d,",screen[i][j]);
    fprintf(f,"%ds\n",DISPLAYNODE);
    fclose(f);
    write(fd,buf,strlen(buf));
    res = read(fd,buf,255);
    buf[res]=0;             /* set end of string, so we can printf */
    //printf(":%s:%d\n", buf, res);
    res = read(fd,buf,255);
    buf[res]=0;             /* set end of string, so we can printf */
    //printf(":%s:%d\n", buf, res);
  }
}

int main(int argc, char*argv[])
{
  int fd,c;
  struct termios oldtio,newtio;
  struct pollfd pfd[]={{0,POLLIN,0}};

  if (argc > 2 && argv[2][0] == 'g')
    buildgraphic();
  else
    buildscreen();

  fd = open(argv[1], O_RDWR | O_NOCTTY );
  if (fd <0) {perror(argv[1]); exit(-1); }

  pfd[0].fd=fd;

  tcgetattr(fd,&oldtio);
  bzero(&newtio, sizeof(newtio));
  newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;

  newtio.c_iflag = IGNPAR;

  newtio.c_oflag = 0;
  newtio.c_lflag = ICANON;
  newtio.c_cc[VINTR]    = 0;     /* Ctrl-c */
  newtio.c_cc[VQUIT]    = 0;     /* Ctrl-\ */
  newtio.c_cc[VERASE]   = 0;     /* del */
  newtio.c_cc[VKILL]    = 0;     /* @ */
  newtio.c_cc[VEOF]     = 4;     /* Ctrl-d */
  newtio.c_cc[VTIME]    = 0;     /* inter-character timer unused */
  newtio.c_cc[VMIN]     = 1;     /* blocking read until 1 character arrives */
  newtio.c_cc[VSWTC]    = 0;     /* '\0' */
  newtio.c_cc[VSTART]   = 0;     /* Ctrl-q */
  newtio.c_cc[VSTOP]    = 0;     /* Ctrl-s */
  newtio.c_cc[VSUSP]    = 0;     /* Ctrl-z */
  newtio.c_cc[VEOL]     = 0;     /* '\0' */
  newtio.c_cc[VREPRINT] = 0;     /* Ctrl-r */
  newtio.c_cc[VDISCARD] = 0;     /* Ctrl-u */
  newtio.c_cc[VWERASE]  = 0;     /* Ctrl-w */
  newtio.c_cc[VLNEXT]   = 0;     /* Ctrl-v */
  newtio.c_cc[VEOL2]    = 0;     /* '\0' */

  tcflush(fd, TCIFLUSH);
  tcsetattr(fd,TCSANOW,&newtio);
  sleep(1);
  sendit(fd);
  sleep(1);
  sendit(fd);
  /* restore the old port settings */
  tcsetattr(fd,TCSANOW,&oldtio);
}