test code for our MBED board

Dependencies:   mbed lwip

i2c.c

Committer:
lolpcc
Date:
2011-05-04
Revision:
1:6877bb99aa17
Parent:
0:9edfcca7cd25

File content as of revision 1:6877bb99aa17:

#include "mbed.h"

#include "main.h"
#include "i2c.h"
#include "useful.h"
#include "pca9685_reg.h"    /* Light Driver Chip */

I2C i2c(p9, p10); // sda, scl

#define PIO          0x40
#define RELAYS       0x40
#define LCD          0xC6
#define BAT          0x76    /* Batron LCD device */
#define BATKBD       0x42    /* batron Keyboard */
#define SEVEN_SEG    0x70
#define ASCII_OFFSET 0x80


/******************************************/
/*                                        */
/*   Probe the I2C bus, and show the      */
/*   user what we have found              */
/*                                        */
/*                                        */
/*                                        */
/******************************************/
void i2c_probe(void) 
{
    lprintf("Searching for I2C devices...\n\r");
   
    int count = 0;
    for (int address=4; address<256; address+=2) {
        if (!i2c.write(address, NULL, 0)) { // 0 returned is ok
            lprintf(" - I2C device found at address 0x%02X\n\r", address);
            count++;
        }
    }
    lprintf("%d devices found\n\r", count);
}

/******************************************/
/*                                        */
/*  Should drive the I2C based LCD        */
/*  Display If attached                   */
/*                                        */
/*                                        */
/*                                        */
/******************************************/
char init_lcd(void)
{
    char    buf[4];
    buf[0]=0;
    buf[1]=19;
    return(i2c.write(LCD,buf,2));
}
char clear_lcd(void)
{
    char    buf[4];
    buf[0]=0;
    buf[1]=12;
    return(i2c.write(LCD,buf,2));
}
char set_lcd(char line, char col)
{
    char    buf[4];
    buf[0]=0;
    buf[1]=3;
    buf[2]=line;
    buf[3]=col;
    return(i2c.write(LCD,buf,4));
}
char write_lcd(char *str)
{
    char    buf[0x60];
    if(strlen(str)>50){
        lprintf("Line length to long\n\r");
        return(0);
    }
    sprintf(buf,"%c%s",'\0',str);
    buf[0]=0;
    return(i2c.write(LCD,buf,strlen(str)+1));
}

/******************************************/
/*                                        */
/*   Read key presses from the keyboard   */
/*   Attached to the LCD interface        */
/*   It returns 0 if no key is pressed    */
/*   or the ascii value of the key press  */
/*                                        */
/******************************************/
char read_keyboard(void)
{
    char    buf[10];
    i2c.read(LCD,buf,4);
    if(buf[1]!=0){
        switch(buf[1]){
            case    0x01    :
                return('1');  
            case    0x02    :
                return('2');  
            case    0x04    :
                return('3');  
            case    0x08    :
                return('4');  
            case    0x10    :
                return('5');  
            case    0x20    :
                return('6');  
            case    0x40    :
                return('7');     
            case    0x80    :
                return('8');  
        }
    }
    if(buf[2]!=0){
        switch(buf[2]){
            case    0x01    :
                return('9');  
            case    0x02    :
                return('*');  
            case    0x04    :
                return('0');  
            case    0x08    :
                return('#');  
        }
    }
    return('\0');
}
/******************************************/
/*                                        */
/*   Blocking key press, will wait for    */
/*   the user to press a key              */
/*                                        */
/******************************************/
char blocking_read_keyboard(void)
{
    char    c = 0;
    while((c=read_keyboard())==0)
   while((read_keyboard())==c);
    wait(0.5);
    return(c);
}

/******************************************/
/*                                        */
/* 1 - 8, Relays On,                      */
/*                                        */
/******************************************/
void relay_operate(char r)
{
    char buf[0x60];
        
    switch(r){
        case    0    :    /* Turn off the relays */
            buf[0]=0x00; 
            break;
        case    1    :
            buf[0]=0x01; 
            break;
        case    2    :
            buf[0]=0x02; 
            break;
        case    3    :
            buf[0]=0x04; 
            break;
        case    4    :
            buf[0]=0x08; 
            break;
        case    5    :
            buf[0]=0x10; 
            break;
        case    6    :
            buf[0]=0x20; 
            break;
        case    7    :
            buf[0]=0x40; 
            break;
        case    8    :
            buf[0]=0x80; 
            break;
        default      :
            lprintf("Unknown Relay %d\n\r",r);
            return;
    }
    i2c.write(RELAYS,buf,1);
}

/******************************************/
/*                                        */
/* Read and Write the PIO latch           */
/*                                        */
/******************************************/
void pio_write(unsigned char r, unsigned char d)
{
    unsigned char buf[0x60];
    
    buf[0]=d;
    i2c.write(r,(char *)buf,1);
}
void pio_read(unsigned char d)
{
   unsigned char r;
   unsigned char buf[0x60];
    
   i2c.read(d,(char *)buf,1);
   r = buf[0];
   
   lprintf("Returned value from the PIO was 0x%02x\n\r",r);
}

/******************************************/
/*                                        */
/* Philips PCA9685 I2C Driver, 16 channel */
/* Lighting controler chip, we have 4     */
/* running in this system, so we need to  */
/* think how the channels map ??          */
/*                                        */
/******************************************/

/******************************************/
/*                                        */
/* Init code for the PCA9685              */
/*                                        */
/******************************************/

void init_pca9685(unsigned char address)
{
    unsigned char buf[30];
    
    lprintf("Setting up channel %d\n\r",address);
    
    buf[0] = PCA9685_MODE1;
    buf[1] = PCA9685_AI;
    buf[2] = PCA9685_OUTDRV;
    i2c.write(address,(char *) buf, 3);
}

/******************************************/
/*                                        */
/* Send data to a given channle of a      */
/* given PCA9685 chip                     */
/*                                        */
/******************************************/

void pca9685_led(unsigned char addr, int led, unsigned char *values) 
{
    unsigned char buf[5];
   
    if (led == PCA9685_ALL_LEDS) {
        buf[0] = PCA9685_ALL_LED_ON_L;
    } else {
        buf[0] = PCA9685_BASE(led);
    }

    buf[1] = values[0];
    buf[2] = values[1];
    buf[3] = values[2];
    buf[4] = values[3];
    i2c.write(addr, (char *)buf, 5);
}

/******************************************/
/*                                        */
/* Calculate the register values for a    */
/* givern brightness percentage           */
/*                                        */
/******************************************/

void pca9685_brightness(int percent, unsigned char *values) 
{
    unsigned int on, off;

    if (percent == 0) {
    values[PCA9685_LED_ON_H] = 0;
    values[PCA9685_LED_OFF_H] = PCA9685_LED_OFF;
    return;
    }
    if (percent == 100) {
    values[PCA9685_LED_ON_H] = PCA9685_LED_ON;
    values[PCA9685_LED_OFF_H] = 0;
    return;
    }
    on = 0;
    off = (4096 * percent) / 100;
    values[PCA9685_LED_ON_L] = on & 0xff;
    values[PCA9685_LED_ON_H] = (on >> 8) & 0xf;
    values[PCA9685_LED_OFF_L] = off & 0xff;
    values[PCA9685_LED_OFF_H] = (off >> 8) & 0xf;
}

/******************************************/
/*                                        */
/* Set a given channel to a given level   */
/*                                        */
/******************************************/
void channel_light(unsigned char ch, unsigned char lev)
{
    char            chip,led;     /* Chip Number, channel number */
    unsigned char   v[4];         /* register data for givern level */
    
    led = ch%16;
    v[0]=0;
    v[1]=0;
    v[2]=0;
    v[3]=0;
    
    if(lev > 100){
        lprintf("Level percentage range 0 - 100 (Trying for %d)\n\r",lev);
        return;
    }
    
    switch(ch/16){
        case    0    :
            chip=LEDDRV1;
            break;
        case    1    :
            chip=LEDDRV2;
            break;
        case    2    :
            chip=LEDDRV3;
            break;
        case    3    :
            chip=LEDDRV4;
            break;
        case    4    :
            chip=LEDDRV5;
            break;
        case    5    :
            chip=LEDDRV6;
            break;
        default      :
            lprintf("Error unknown chip %d\n\r",ch/16);
            return;
    }
    
    lprintf("Setting channel %d to brightness leven %d chip = %d(%d),%d\n\r",
        ch,lev,chip,ch/16,led);
    pca9685_brightness(lev,v);    /* Calculate the brightness level */
    lprintf("Brightness level is %02x,%02x,%02x,%02x\n\r",v[0],v[1],v[2],v[3]);
    pca9685_led(chip,led,v);      /* Send to chip */
}

/******************************************/
/*                                        */
/*  Send some data to the seven segment   */
/*  display device, showing the user      */
/*  what the SAA1064 can do               */
/*                                        */
/*                                        */
/******************************************/

/* mapping of bit pattern to number 0-9 */
char sseg_map[15]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7c,0x07,0x7f,0x67};

void test_seven_seg(char loop)
{
    unsigned char buf[10];
    char    a,b,c;
    
    buf[0]=0;
    buf[1]=0x27;
    c=0;
    i2c.write(SEVEN_SEG,(char *)buf,7);
    while(c!=loop){
        a = 1;
        b = 0;
        while(b!=8){
            buf[2]=a<<b;
            buf[3]=a<<b;
            buf[4]=a<<b;
            buf[5]=a<<b;
            i2c.write(SEVEN_SEG,(char *)buf,7);
            wait(0.5);
            b++;
        }
        c++;
    }
}

void sseg_four_digits(int a)
{
    int index = 4;
    int val = a;
    char pt[5];
    
    pt[1] = 0;
    pt[2] = 0;
    pt[3] = 0;
    pt[4] = 0;
    
    do {
        register unsigned short temp;

        temp = val / 10;
        pt[index] = (char)(val - (temp * 10));
        val = temp;
        index -= 1;

    } while ( val > 0 );
    
    print_seven_seg(sseg_map[pt[1]],sseg_map[pt[2]],sseg_map[pt[3]],sseg_map[pt[4]]);
}                

void print_seven_seg(unsigned char a,unsigned char b,unsigned char c,unsigned char d)
{
    unsigned char buf[10];
    
    buf[0]=0;
    buf[1]=0x27;
    buf[2]=a;
    buf[3]=b;
    buf[4]=c; 
    buf[5]=d;
    i2c.write(SEVEN_SEG,(char *)buf,7);
}

/******************************************/
/*                                        */
/*  Test code to drive the Batron LCD     */
/*                                        */
/******************************************/

void batron_lcd_init(void)
{
    char buf[0x60];
    
    lprintf("Init Batron LCD at %02x\n\r",BAT);
    
    buf[0]=0x00;
    buf[1]=0x34;
    buf[2]=0x0c;
    buf[3]=0x06;
    buf[4]=0x35;
    buf[5]=0x04;
    buf[6]=0x10;
    buf[7]=0x42;
    buf[8]=0x9f;
    buf[9]=0x34;
    buf[10]=0x80;
    buf[11]=0x02;
    
    i2c.write(BAT,(char *)buf,12);
    batron_clear();
}
void batron(char *str)
{
    lprintf("Testing Batron LCD, Clearing Display\n\r");
    
    batron_clear();
    
    lprintf("Sending %s\n",str);
     
    batron_lcd_write(str);
}

char batron_lcd_write(char *b)
{
    char buf[0x60];
    int a;
    
    buf[0]=0x00;
    buf[1]=0x80;
    i2c.write(BAT,(char *)buf,2);
    
    a=0;
    buf[0]=0x40;
    
    while(a!=strlen(b)){
        buf[a+1]=ascii_to_lcd(b[a]);
        a++;
    }
    buf[a+1]=0x00;
    
    i2c.write(BAT,buf,strlen(b)+1);
    
    buf[0]=0x80;
    buf[1]=0x02;
    i2c.write(BAT,(char *)buf,2);
    return(0);
}

char ascii_to_lcd(char ch)
{
    char c;

    c = 0xA0;                         // default: white space

    if((ch>=' ') & (ch<='?'))
        c = ASCII_OFFSET + ch;
    if((ch>='A') & (ch<='Z'))    
        c = ASCII_OFFSET + ch;
    if((ch>='a') & (ch<='z'))
        c = ASCII_OFFSET + ch;
    return c;
}    
void batron_clear(void)
{
    batron_clear_line(0);                // clear 1st line
    batron_clear_line(1);                // clear 2nd line

    return;
}   
char batron_clear_line(char row)
{
    char i=0, state;
    do
    //state = LCD_put_xy(LCD_ascii_to_lcd(0x20), row, i);
        state = batron_put_xy(0xA0, row, i);
    while((i++<16));
    return state;
}
char batron_put_xy(char ddram_byte, char row, char column)
{
    char buf[0x10];
    char adr;

    if(row == 0)                                // line offset
        adr = column;
    else
        adr = 0x40 + column;
    
    buf[0] = 0x00;            // Enter function setting
    buf[1] = 0x80 + adr;    // LCD adr counter set to "adr"

    i2c.write(BAT,(char *)buf,2);

    buf[0] = 0x40;            // write to DDRAM
    buf[1] = ddram_byte;

    i2c.write(BAT,(char *)buf,2);

    return(0);
}
/******************************************/
/*                                        */
/* Test code for a matrix KBD built on a  */
/* PCF8574 I2C driver                     */
/* State, 0 - test, 1 - wait till a press */
/* Out on the lower nibble, in upper      */
/*                                        */
/******************************************/

char pcf8574_kbd(char state)
{
    char buf[0x60];
    
    char r = 0;
    
    buf[0]=0xf0;
    i2c.write(BATKBD,(char *)buf,1);
    while(r==0){
        i2c.read(BATKBD,(char *)buf,1);
        if((buf[0] & 0xf0)!=0xf0){
            buf[0]=0xfe;
            i2c.write(BATKBD,(char *)buf,1);
            i2c.read(BATKBD,(char *)buf,1);
            if((buf[0] & 0xf0)!=0xf0)
                r = pcf8584_sub_kbd(buf[0]);
            buf[0]=0xfd;
            i2c.write(BATKBD,(char *)buf,1);
            i2c.read(BATKBD,(char *)buf,1);
            if((buf[0] & 0xf0)!=0xf0)
                r = pcf8584_sub_kbd(buf[0]);
            buf[0]=0xfb;
            i2c.write(BATKBD,(char *)buf,1);
            i2c.read(BATKBD,(char *)buf,1);
            if((buf[0] & 0xf0)!=0xf0)
                r = pcf8584_sub_kbd(buf[0]);
            buf[0]=0xf7;
            i2c.write(BATKBD,(char *)buf,1);
            i2c.read(BATKBD,(char *)buf,1);
            if((buf[0] & 0xf0)!=0xf0)
                r = pcf8584_sub_kbd(buf[0]);
        } else {
            buf[0]=0xf0;
            i2c.write(BATKBD,(char *)buf,1);   
        }
        if(state==0)
            return(r);
        wait(0.2);
    }
    
    return(r);
}
char pcf8584_sub_kbd(unsigned char d)
{
    lprintf("Raw Code %02x, ",d);
    switch(d){
        case    0xee    :
            return('c');
        case    0xed    :
            return('d');
        case    0xeb    :
            return('e');
        case    0xe7    :
            return('f');
        case    0xde    :
            return('b');
        case    0xdd    :
            return('9');
        case    0xdb    :
            return('6');
        case    0xd7    :
            return('3');
        case    0xbe    :
            return('0');
        case    0xbd    :
            return('8');
        case    0xbb    :
            return('5');
        case    0xb7    :
            return('2');
        case    0x7e    :
            return('a');
        case    0x7d    :
            return('7');
        case    0x7b    :
            return('4');
        case    0x77    :
            return('1');
        default         :
            lprintf("Strange key value passed 0X%02x\n\r",d);
            return(0);
    }
}