/**************************************************************
* 数码管时钟显示程序：
* 1. 宏定义SPI_CS为SPI片选引脚，根据需要修改gpio143的数字即可
* 2. cmd_dis_mode变量为数码管亮度设置变量，取值为0x88--0x8F
**************************************************************/
#include <sys/poll.h>
#include <signal.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include "iniparser.h"

#define TRUE	1
#define FALSE	0
#define SPI_CS 	"/sys/class/gpio/gpio143/value"
#define SPK_CONF    "/etc/speaker.conf"
#define _DATETIME_SIZE 32

const unsigned char BCD_LABLE_ALL[19]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,
											0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f,0xff};
unsigned char BCD_LABLE_anode[16] = {0}; 
unsigned char cmd_dis_mode = 0x8B;	/* 数码管亮度设置，最小0x88, 最大0x8F */
int fd;
static int is24Hour = TRUE;

int send_8bit(unsigned char data)
{
	unsigned char tmp[1]={0};

	data=(data<<4) | (data>>4);
	data=((data<<2)&0xcc) | ((data>>2)&0x33);
	data=((data<<1)&0xaa) | ((data>>1)&0x55);
	tmp[0] = data;
	write(fd, tmp, 1);

	return 0;
}

void send_command(unsigned char data)
{
	system("echo 1 > " SPI_CS);	
	usleep(1);
	system("echo 0 > " SPI_CS);		
	send_8bit(data);
}

void Write_String(unsigned char *p,unsigned char cnt) 
{
	unsigned char i;

	for(i=0; i<cnt; i++){
		send_8bit(*p++);
	}
}

void NE_C(unsigned char ydata,unsigned char cnt)
{
	char i=0,j=0;
	if(cnt>0){
		if(cnt>8){
			cnt = cnt - 9;
			for(i=1;i<16;i=i+2)
			{
				if(ydata&0x01 == 0x01)
				{
					BCD_LABLE_anode[i] |= (0x01<<cnt);
				}
				else
				{
					BCD_LABLE_anode[i] &= ~(0x01<<cnt); 
				}
				ydata = (ydata>>1);
			}
		}else {
			cnt = cnt -1;
			for(i=0;i<16;i=i+2)
			{
				if((ydata&0x01) == 0x01){
					BCD_LABLE_anode[i] |= (0x01<<cnt);
				}
				else{
					BCD_LABLE_anode[i] &= ~(0x01<<cnt);
				}
				ydata = (ydata>>1);
			}
		}
	}
}

int is24HourClock()
{
	dictionary  *   ini ;
	ini = iniparser_load(SPK_CONF);
	char is24hourclock[8];
	
    if (ini==NULL) {
        fprintf(stderr, "cannot parse file: %s\n", SPK_CONF);
        return FALSE ;
    }
	strcpy(is24hourclock, iniparser_getstring(ini, "system:is24hourclock", "yes"));
	
	iniparser_freedict(ini);
	if(strcmp(is24hourclock,"yes") == 0)
	{
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}

void display(unsigned char number,unsigned char cnt1)
{
	NE_C(BCD_LABLE_ALL[number],cnt1);
	send_command(0x40); 
	send_command(0xc0); 
	Write_String(BCD_LABLE_anode,16);
	send_command(cmd_dis_mode);

	system("echo 1 > " SPI_CS);	
}

void display_fixedadd(unsigned char number, unsigned char cnt1, unsigned char addr)
{
	NE_C(BCD_LABLE_ALL[number],cnt1);
	send_command(0x44); 	
	send_command(addr);
	send_8bit(BCD_LABLE_anode[number]);		
	send_command(cmd_dis_mode);

	system("echo 1 > " SPI_CS);	
}

int gettime(char *psTime)
{
	time_t nSeconds;
	struct tm *pTM;
	int tmp_hour;

	time(&nSeconds); //same with nSeconds = time(NULL);
	pTM = localtime(&nSeconds);
	if(is24Hour)
	{
		tmp_hour = pTM->tm_hour;
	}
	else
	{
		tmp_hour = pTM->tm_hour%12;
		if(tmp_hour == 0) tmp_hour = 12;
	}

	sprintf(psTime, "%02d:%02d:%02d", tmp_hour, pTM->tm_min, pTM->tm_sec);

	return 0;		
}

int main(int argc, char *argv[]){	
	int ret,i;
	char DateTime[_DATETIME_SIZE];
	char Old_Clock[5];
	unsigned int speed=8000;
	unsigned char spi_mode=0;
	char dot_flash=0;

	//printf("+----------hello world-----------+\n");
	fd = open("/dev/spidev0.0", O_RDWR);
	if(fd < 0){
		printf("open spidev error!!\n");
		return fd;
	}
	ret = ioctl(fd, SPI_IOC_WR_MODE, &spi_mode);
	ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
	is24Hour = is24HourClock();

	memset(DateTime, 0, sizeof(DateTime));
	memset(Old_Clock, 0, sizeof(Old_Clock));
	ret = gettime(DateTime);
	if(DateTime[0] - 0x30 == 0)
		display(10,1);
	else
		display(DateTime[0]-0x30, 1);
	display(DateTime[1]-0x30, 2);
	display(DateTime[3]-0x30, 3);
	display(DateTime[4]-0x30, 4);
	for(i=0; i<5; i++)	
		Old_Clock[i] = DateTime[i]-0x30;

	while(1){
		ret = gettime(DateTime);

		if(Old_Clock[0] != (DateTime[0]-0x30)){
			Old_Clock[0] = DateTime[0]-0x30;
			if(Old_Clock[0] == 0)
				display(10, 1);
			else
				display(Old_Clock[0], 1);
		}
		if(Old_Clock[1] != (DateTime[1]-0x30)){
			Old_Clock[1] = DateTime[1]-0x30;
			display(Old_Clock[1], 2);
		}
		if(Old_Clock[3] != (DateTime[3]-0x30)){
			Old_Clock[3] = DateTime[3]-0x30;
			display(Old_Clock[3], 3);
		}
		if(Old_Clock[4] != (DateTime[4]-0x30)){
			Old_Clock[4] = DateTime[4]-0x30;
			display(Old_Clock[4], 4);
		}		
		sleep(1);	
		if(!dot_flash){
			display(18, 5); 
			//display(18, 6); 
			dot_flash = 1;
		}else{
			display(0, 5); 
			//display(0, 6); 
			dot_flash = 0;			
		}
	}

	close(fd);	

	return 0;
}

