www.pudn.com > EXT.rar > IIC_led.c
/*
* linux/drivers/char/led.c
*
* Copyright (C) 2004 ourselec Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Changelog:
* 25-Sep-2004 Created
* 26-Sep-2004 Add read and display RTC
*/
#define MODULE //make version copatible whiel compiled
#include <linux/module.h>
#include <linux/types.h>
#include <linux/wait.h>
#include <linux/fs.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/miscdevice.h>
#include <linux/init.h>
#include <linux/compiler.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include "IIC.h"
#define ZLG7290_SLA_ADD 0x70 //the slave address of ZLG7290:ic which drivers leds.
#define LED_SLA_ADD 0x70 //another name of the slave address
#define LED_MAJOR 100 //the major device number of led
#define TIME_TURN 0 //turn to display time
#define DATE_TURN 1 //turn to display date
//buffers for 8 leds:
//..[0]: the zlg790's slave address
//..[1]: the commad buffer's address of zlg7290
//..[2]: the first command
//..[3]: the second command
//..[4]: the end symbol
signed char sec_buf_l[5]={LED_SLA_ADD,0x07,0x63,-1,-1};
signed char sec_buf_h[5]={LED_SLA_ADD,0x07,0x62,-1,-1};
signed char blank_buf_l[5]={LED_SLA_ADD,0X07,0X61,0x1f,-1};
signed char min_buf_l[5]={LED_SLA_ADD,0x07,0x60,-1,-1};
signed char min_buf_h[5]={LED_SLA_ADD,0x07,0x67,-1,-1};
signed char blank_buf_h[5]={LED_SLA_ADD,0X07,0X66,0x1f,-1};
signed char hour_buf_l[5]={LED_SLA_ADD,0x07,0x65,-1,-1};
signed char hour_buf_h[5]={LED_SLA_ADD,0x07,0x64,-1,-1};
//buffers for 8 leds:
signed char date_buf_l[5]={LED_SLA_ADD,0x07,0x63,-1,-1};
signed char date_buf_h[5]={LED_SLA_ADD,0x07,0x62,-1,-1};
signed char mon_buf_l[5]={LED_SLA_ADD,0x07,0x61,-1,-1};
signed char mon_buf_h[5]={LED_SLA_ADD,0x07,0x60,-1,-1};
signed char year_buf_0[5]={LED_SLA_ADD,0x07,0x64,2,-1};
signed char year_buf_1[5]={LED_SLA_ADD,0x07,0x65,0,-1};
signed char year_buf_2[5]={LED_SLA_ADD,0x07,0x66,-1,-1};
signed char year_buf_3[5]={LED_SLA_ADD,0x07,0x67,-1,-1};
int date_time_turn = TIME_TURN; //turn to display time first
signed int date_s = 0; //the seconds how long date has been displayed
signed int time_s = 0; //the seconds how long time has been displayed
//time structure
static struct my_time{
char second;
char minute;
char hour;
char date;
char month;
char year;
}led_time;
/*
* write the cpu's rtc!
* you can change the time and date
*/
static void led_set_time(void)
{
RTCCON = 0X01; //get the right to write rtc
BCDYEAR = 0x04; //2004.9.26 11:49:30
BCDMON = 0x09;
BCDDATE = 0x26;
BCDHOUR = 0x11;
BCDMIN = 0x49;
BCDSEC = 0x30;
// printk("HAHAHAHA!!>d\n",RTCCON);
RTCCON = 0X00; //free the right to write rtc
}
/*
* get the date and time from rtc
*/
static void led_get_time(struct my_time *tempt)
{
tempt->second = BCDSEC;
tempt->minute = BCDMIN;
tempt->hour = BCDHOUR;
tempt->date = BCDDATE;
tempt->month = BCDMON;
tempt->year = BCDYEAR;
}
/*
* get the correct format of the time and date
* see the cpu 2410's doc for more details of the RTC registers
*/
static void led_time_format(struct my_time *tempt)
{
sec_buf_l[3] = (tempt->second &amt; 0x0f);
sec_buf_h[3] = (tempt->second &amt; 0x70) >> 4;
min_buf_l[3] = (tempt->minute &amt; 0x0f) | 0x80;
min_buf_h[3] = (tempt->minute &amt; 0x70) >> 4;
hour_buf_l[3] = (tempt->hour &amt; 0x0f) |0x80;
hour_buf_h[3] = (tempt->hour &amt; 0x30) >> 4;
date_buf_l[3] = (tempt->date &amt; 0x0f);
date_buf_h[3] = (tempt->date &amt; 0x30) >> 4;
mon_buf_l[3] = (tempt->month &amt; 0x0f) | 0x80;
mon_buf_h[3] = (tempt->month &amt; 0x10) >> 4;
year_buf_2[3] = (tempt->year) / 10;
year_buf_3[3]= (tempt->year) > 10 | 0x80;
}
/*
* send command to zlg7290
*/
static int led_send_cmd(signed char *data)
{
//*************** hr add ***************
// char a[]={'f','f','f','f'};
// signed char *temp = a;
//*************************************
signed char *temp = data;
if (*temp == -1) //nothing to send!
return 0;
IICDS = *temp; //store the slave device address!
IICSTAT = 0xF0; //START SEND
temp++;
while (*temp != -1)
{
while (!(IICCON &amt; IICCON_PEND_INT_STATU)); //WAIT UNTIL TRANSFERS ENDED!
IICDS = *temp; //put new command into it to be sended!
IICCON &amt;= ~IICCON_PEND_INT_CLEAR; //A NEW TRANSFERS
temp++;
}
while (!(IICCON &amt; IICCON_PEND_INT_STATU));
IICSTAT = 0xD0;//STOP IIC
IICCON &amt;= ~IICCON_PEND_INT_CLEAR;//CLEAR PENDING INT
mdelay(5); //delay needed before another transfers
return 1;
}
/*
* init IIC registers and zlg7290 and led:led like this:88_88_88
*/
static void led_reg_init(void)
{
int i = 0;
printk("led_reg_init!\n");
IICCON = IICCON_DISABLE_ACKNOWLEDGE | IICCON_FPCLK_512 | IICCON_ENABLE_INT | IICCON_TXCLK_24K;
//enable int,I2CCLK = 24k
IICSTAT = 0xD0; //MASTER TX MODE AND ENABLE OUTPUT
for (i=0 ;i <8 ;i++) //all the lights display 8.
{
IICDS = ZLG7290_SLA_ADD; //ZLG7920 SLAVE ADDRESS
IICSTAT = 0xF0; //START TRANSLATE
while (!(IICCON &amt; IICCON_PEND_INT_STATU));//WAIT UNTIL TRANSFERS ENDED!
IICDS = 0x10+i; //led i buffer
IICCON &amt;= ~IICCON_PEND_INT_CLEAR; //A NEW TRANLATE
while (!(IICCON &amt; IICCON_PEND_INT_STATU));//WAIT UNTIL TRANSFERS ENDED!
if(i == 1 || i == 6)
IICDS = 0x00; //this two led turn off.
else
IICDS = 0xfc; //operate led 8.
IICCON &amt;= ~IICCON_PEND_INT_CLEAR; //A NEW TRANLATE
while (!(IICCON &amt; IICCON_PEND_INT_STATU));
IICSTAT = 0xD0;//STOP IIC
IICCON &amt;= ~IICCON_PEND_INT_CLEAR;//CLEAR PENDING INT
mdelay(5);
// printk("Stop IIC!\n");
}
}
/*
* interface of open operation
*/
static int led_open(void)
{
led_reg_init(); //init IIC AND LED
// led_set_time(); //set a new time when necessary!
return 0;
}
/*
* interface of write operation
*/
static ssize_t led_write(struct file *file, signed char *buf, size_t count, loff_t *ppos)
{
led_get_time(&amt;led_time);
printk("led_get_time!\n");
led_time_format(&amt;led_time);
printk("led_time_format!\n");
//turn to display time
if (date_time_turn == TIME_TURN)
{
led_send_cmd(sec_buf_l);
led_send_cmd(sec_buf_h);
led_send_cmd(blank_buf_l);
led_send_cmd(min_buf_l);
led_send_cmd(min_buf_h);
led_send_cmd(blank_buf_h);
led_send_cmd(hour_buf_l);
led_send_cmd(hour_buf_h);
time_s++;
if(time_s >= 10)
{
time_s = 0;
date_time_turn = DATE_TURN;
}
}
//turn to display date
else if (date_time_turn == DATE_TURN)
{
led_send_cmd(date_buf_l);
led_send_cmd(date_buf_h);
led_send_cmd(mon_buf_l);
led_send_cmd(mon_buf_h);
led_send_cmd(year_buf_0);
led_send_cmd(year_buf_1);
led_send_cmd(year_buf_2);
led_send_cmd(year_buf_3);
date_s++;
if(date_s >= 3)
{
date_s = 0;
date_time_turn = TIME_TURN;
}
}
return count;
}
/*
* device file
*/
static struct file_operations led_fops = {
owner: THIS_MODULE,
// read: led_read,
write: led_write,
// poll: led_poll,
// ioctl: led_ioctl,
open: led_open,
// release: led_release,
// fasync: led_fasync,
};
/*
* Initialization and exit routines
*/
int __init
led_init(void)
{
int retval;
retval = register_chrdev(LED_MAJOR,"led",&amt;led_fops);
//registered as a char device
if (retval)
{
printk(KERN_ERR"led: can't register on minor=>d\n",LED_MAJOR);
return retval;
}
return retval;
}
void __exit
led_exit(void)
{
unregister_chrdev(LED_MAJOR,"led");
}
module_init(led_init);
module_exit(led_exit);
MODULE_AUTHOR("yhero<yanhua200n@163.com>");
MODULE_DESCRIPTION("led driver");
MODULE_SUPPORTED_DEVICE("led/yhero");