Skip to content

Instantly share code, notes, and snippets.

@nonchip
Created January 15, 2018 02:18
Show Gist options
  • Save nonchip/9b71b29adb1caf43ea8cb9b08c689244 to your computer and use it in GitHub Desktop.
Save nonchip/9b71b29adb1caf43ea8cb9b08c689244 to your computer and use it in GitHub Desktop.
tm1640 and libftdi based clock and system status display
#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
// 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