Created
January 15, 2018 02:18
-
-
Save nonchip/9b71b29adb1caf43ea8cb9b08c689244 to your computer and use it in GitHub Desktop.
tm1640 and libftdi based clock and system status display
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define PIN_TX 0x01 /* Orange wire on FTDI cable */ | |
#define PIX_RX 0x02 /* Yellow */ | |
#define PIN_RTS 0x04 /* Green */ | |
#define PIN_CTS 0x08 /* Brown */ | |
#define PIN_DTR 0x10 | |
#define PIN_DSR 0x20 | |
#define PIN_DCD 0x40 | |
#define PIN_RI 0x80 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// gcc tm1640.c -lftdi1 -o tm1640 -std=gnu99 | |
#include <stdio.h> | |
#include <math.h> | |
#include <errno.h> | |
#include <error.h> | |
#include <libftdi1/ftdi.h> | |
#include <time.h> | |
#include <stdbool.h> | |
#include <unistd.h> | |
#include <stdlib.h> | |
#include <sys/sysinfo.h> | |
#include <signal.h> | |
#include <linux/kernel.h> | |
#include "pins.h" | |
#define DIN PIN_TX | |
#define SCLK PIN_DTR | |
const char FONT[]={ | |
0b00111111, | |
0b00000110, | |
0b01011011, | |
0b01001111, | |
0b01100110, | |
0b01101101, | |
0b01111101, | |
0b00000111, | |
0b01111111, | |
0b01101111, | |
0b11110111, // hex | |
0b11111111, | |
0b10111001, | |
0b10111111, | |
0b11111001, | |
0b11110001 | |
}; | |
#define DOT 0b10000000 | |
//#define ftdi_write_data(a,b,c) printf("SCLK: %d DIN: %d\n", ((*b)&SCLK)>0,((*b)&DIN)>0);\ | |
ftdi_write_data(a,b,c); | |
void sendMarker(struct ftdi_context* ftdicv, struct timespec* sleeptimev,bool start){ | |
// printf("MARKER: %d\n", start); | |
char pins=0; | |
if(start){ | |
pins=SCLK|DIN; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
pins=SCLK; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
pins=0; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
}else{ | |
pins=0; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
pins=SCLK; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
pins=SCLK|DIN; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
} | |
} | |
void sendByte(struct ftdi_context* ftdicv, struct timespec* sleeptimev, unsigned char byte){ | |
// printf("BYTE: %x\n",byte); | |
char pins=0; | |
for(int i=0;i<8;i++){ | |
pins=((byte>>i)&1)<<(DIN-1); | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
pins|=SCLK; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
pins^=SCLK; | |
ftdi_write_data(ftdicv,&pins,1); | |
nanosleep(sleeptimev,NULL); | |
} | |
} | |
void sendAddressCmd(struct ftdi_context* ftdicv, struct timespec* sleeptimev, unsigned char addr){ | |
// printf("ADDRESS: %d\n", addr); | |
sendByte(ftdicv,sleeptimev,0b11000000|(0b00001111&addr)); | |
} | |
void sendDataCmd(struct ftdi_context* ftdicv, struct timespec* sleeptimev, bool autoincrement){ | |
// printf("DATA: %d\n", autoincrement); | |
if(autoincrement) | |
sendByte(ftdicv,sleeptimev,0b01000000); | |
else | |
sendByte(ftdicv,sleeptimev,0b01000100); | |
} | |
void sendBrightnessCmd(struct ftdi_context* ftdicv, struct timespec* sleeptimev, unsigned char bright){ | |
// printf("BRIGHTNESS: %d\n", bright); | |
if(bright==0) | |
sendByte(ftdicv,sleeptimev,0b10000000); | |
else | |
sendByte(ftdicv,sleeptimev,0b10001000|(0b00000111&bright-1)); | |
} | |
bool turnOff; | |
bool notify; | |
void handle_signal(int signal) { | |
switch (signal) { | |
case SIGHUP: | |
case SIGINT: | |
turnOff=true; | |
break; | |
case SIGUSR1: | |
notify=true; | |
} | |
} | |
int main(int argc, char const *argv[]) | |
{ | |
turnOff=false; | |
notify=false; | |
struct timespec sleeptime; | |
sleeptime.tv_sec=0; | |
sleeptime.tv_nsec = 500L; | |
struct sigaction sa; | |
sa.sa_handler=&handle_signal; | |
sa.sa_flags = SA_RESTART; | |
sigfillset(&sa.sa_mask); | |
if (sigaction(SIGHUP, &sa, NULL) == -1) { | |
perror("Can't handle SIGHUP"); | |
} | |
if (sigaction(SIGINT, &sa, NULL) == -1) { | |
perror("Can't handle SIGINT"); | |
} | |
if (sigaction(SIGUSR1, &sa, NULL) == -1) { | |
perror("Can't handle SIGUSR1"); | |
} | |
struct ftdi_context ftdic; | |
ftdi_init(&ftdic); | |
if(ftdi_usb_open(&ftdic, 0x0403, 0x6001) < 0) { | |
perror("Can't open device"); | |
return ENODEV; | |
} | |
if(ftdi_set_bitmode(&ftdic, DIN|SCLK,BITMODE_BITBANG)<0) { | |
perror("Can't set bitbang mode"); | |
return EIO; | |
} | |
char pins=SCLK|DIN; | |
ftdi_write_data(&ftdic,&pins,1); | |
nanosleep(&sleeptime,NULL); | |
sendMarker(&ftdic,&sleeptime,true); | |
sendBrightnessCmd(&ftdic,&sleeptime,1); | |
sendMarker(&ftdic,&sleeptime,false); | |
sendMarker(&ftdic,&sleeptime,true); | |
sendDataCmd(&ftdic,&sleeptime,true); | |
sendMarker(&ftdic,&sleeptime,false); | |
sendMarker(&ftdic,&sleeptime,true); | |
sendAddressCmd(&ftdic,&sleeptime,0); | |
for(int i=0;i<16;i++){ | |
sendByte(&ftdic,&sleeptime,0); | |
} | |
sendMarker(&ftdic,&sleeptime,false); | |
time_t *timestamp=malloc(sizeof(time_t)); | |
struct tm *timestruct=malloc(sizeof(struct tm)); | |
unsigned char h1,h2,m1,m2,s1,s2; | |
struct timespec looptime; | |
looptime.tv_sec=0; | |
looptime.tv_nsec = 50000000L; | |
char obuf[16]; | |
char obufold[16]; | |
for(int i=0;i<16;i++){ | |
obuf[i]=0; | |
obufold[i]=0; | |
} | |
FILE *psfp=fopen("/proc/stat","r"); | |
FILE *pmfp=fopen("/proc/meminfo","r"); | |
unsigned int cu,cn,cs,ci,cio,cirq,csirq,csum,cfree,coldfree,coldsum; | |
double cuse,cavg; | |
struct sysinfo *sysinfop=malloc(sizeof(struct sysinfo)); | |
double ruse; | |
unsigned int rtotal,ravail; | |
int frame=0; | |
int notifycount=-1; | |
double loadavg; | |
while(!turnOff){ | |
time(timestamp); | |
localtime_r(timestamp,timestruct); | |
h1=timestruct->tm_hour/10; | |
h2=timestruct->tm_hour%10; | |
m1=timestruct->tm_min/10; | |
m2=timestruct->tm_min%10; | |
s1=timestruct->tm_sec/10; | |
s2=timestruct->tm_sec%10; | |
obuf[0]=FONT[h1]; | |
obuf[1]=FONT[h2]|DOT; | |
obuf[2]=FONT[m1]; | |
obuf[3]=FONT[m2]|DOT; | |
obuf[4]=FONT[s1]; | |
obuf[5]=FONT[s2]|((frame%2==0)?DOT:0); | |
if(0!=sysinfo(sysinfop)) continue; | |
loadavg=sysinfop->loads[0] / (double)(1<<SI_LOAD_SHIFT); | |
if(loadavg>9.99){ | |
obuf[7]=FONT[(int)loadavg/10]; | |
obuf[8]=FONT[(int)loadavg%10]|DOT; | |
obuf[9]=FONT[(int)(loadavg*10)%10]; | |
}else{ | |
obuf[7]=FONT[(int)loadavg%10]|DOT; | |
obuf[8]=FONT[(int)(loadavg*10)%10]; | |
obuf[9]=FONT[(int)(loadavg*100)%10]; | |
} | |
if(frame%15==0 ||frame==0){ | |
freopen("/proc/stat","r",psfp); | |
fscanf(psfp,"cpu %u %u %u %u %u %u %u",&cu,&cn,&cs,&ci,&cio,&cirq,&csirq); | |
csum=cu+cn+cs+ci+cio+cirq+csirq; | |
cfree=ci+cio; | |
cuse=1.0-(double)(cfree-coldfree)/(double)(csum-coldsum); | |
coldfree=cfree; | |
coldsum=csum; | |
if(cuse>0.99){ | |
obuf[11]=1; | |
obuf[12]=1; | |
}else{ | |
obuf[11]=FONT[(int)(cuse*10)%10]; | |
obuf[12]=FONT[(int)(cuse*100)%10]; | |
} | |
freopen("/proc/meminfo","r",pmfp); | |
fscanf(pmfp,"MemTotal: %u kB MemFree: %*u kB MemAvailable: %u kB", &rtotal, &ravail); | |
ruse=1.0-((double)ravail/(double)rtotal); | |
//1.0-(double)(sysinfop->freeram + sysinfop->bufferram + sysinfop->freehigh)/(double)(sysinfop->totalhigh + sysinfop->totalram); | |
if(ruse>0.99){ | |
obuf[14]=1; | |
obuf[15]=1; | |
}else{ | |
obuf[14]=FONT[(int)(ruse*10)%10]; | |
obuf[15]=FONT[(int)(ruse*100)%10]; | |
} | |
} | |
if(notify){ | |
notifycount=4; | |
notify=false; | |
} | |
if(notifycount>0){ | |
for(int i=0;i<16;i++){ | |
if(notifycount%2==0) | |
obuf[i]=FONT[8]; | |
else | |
obuf[i]=0; | |
} | |
} | |
if(notifycount>=0){ | |
for(int i=0;i<notifycount;i++) | |
obuf[i]|=DOT; | |
notifycount--; | |
} | |
for(int i=0;i<16;i++){ | |
if(obuf[i]==obufold[i]) | |
continue; | |
sendMarker(&ftdic,&sleeptime,true); | |
sendAddressCmd(&ftdic,&sleeptime,i); | |
while(obuf[i]!=obufold[i] && i<16){ | |
// printf("buf %d\n",i); | |
sendByte(&ftdic,&sleeptime,obuf[i]); | |
obufold[i]=obuf[i]; | |
i++; | |
} | |
sendMarker(&ftdic,&sleeptime,false); | |
} | |
frame++; | |
nanosleep(&looptime,NULL); | |
} | |
sendMarker(&ftdic,&sleeptime,true); | |
sendAddressCmd(&ftdic,&sleeptime,0); | |
for(int i=0;i<16;i++){ | |
sendByte(&ftdic,&sleeptime,0); | |
} | |
sendMarker(&ftdic,&sleeptime,false); | |
pins=0; | |
ftdi_write_data(&ftdic,&pins,1); | |
fclose(psfp); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment