test code for our MBED board

Dependencies:   mbed lwip

Revision:
1:6877bb99aa17
Parent:
0:9edfcca7cd25
--- a/i2c.c	Tue Jan 12 16:49:56 2010 +0000
+++ b/i2c.c	Wed May 04 08:30:52 2011 +0000
@@ -1,11 +1,21 @@
 #include "mbed.h"
-#include "diags.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 PIO          0x40
+#define ASCII_OFFSET 0x80
+
+
 /******************************************/
 /*                                        */
 /*   Probe the I2C bus, and show the      */
@@ -16,38 +26,26 @@
 /******************************************/
 void i2c_probe(void) 
 {
-    char buf[0x60];
-    sprintf(buf,"Searching for I2C devices...\n\r");
-    serial_output_string(buf);
-
+    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
-            sprintf(buf," - I2C device found at address 0x%02X\n\r", address);
-            serial_output_string(buf);
+            lprintf(" - I2C device found at address 0x%02X\n\r", address);
             count++;
         }
     }
-    sprintf(buf,"%d devices found\n\r", count);
-    serial_output_string(buf);
+    lprintf("%d devices found\n\r", count);
 }
 
 /******************************************/
 /*                                        */
-/*  Should display some basic data        */
-/*  on the LCD interface                  */
+/*  Should drive the I2C based LCD        */
+/*  Display If attached                   */
 /*                                        */
 /*                                        */
 /*                                        */
 /******************************************/
-/* LCD tests */
-void test_lcd(char t)
-{
-    init_lcd();
-    clear_lcd();
-    write_lcd("this is a test");
-}
-
 char init_lcd(void)
 {
     char    buf[4];
@@ -75,25 +73,22 @@
 {
     char    buf[0x60];
     if(strlen(str)>50){
-        printf("Line length to long\n\r");
+        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));
 }
+
 /******************************************/
 /*                                        */
-/*   Shoudl get some keys from the user   */
-/*   pressing keys on the keypad          */
-/*   and display this data on the LCD     */
-/*                                        */
+/*   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  */
 /*                                        */
 /******************************************/
-/* Keyboard test code here */
-void test_kbd(void)
-{
-}
 char read_keyboard(void)
 {
     char    buf[10];
@@ -134,16 +129,218 @@
 }
 /******************************************/
 /*                                        */
-/*  Should read and write data on the     */
-/*  PCF8574 I/O expander, maybe with      */
-/*  a loop back connector in time         */
+/*   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              */
 /*                                        */
 /******************************************/
-/* PCF8574 tests */
-void test_pio(char t)
+
+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   */
@@ -181,6 +378,30 @@
     }
 }
 
+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];
@@ -189,22 +410,217 @@
     buf[1]=0x27;
     buf[2]=a;
     buf[3]=b;
-    buf[4]=d; /* Digits 3 and 4 are the wrong way round */
-    buf[5]=c;
+    buf[4]=c; 
+    buf[5]=d;
     i2c.write(SEVEN_SEG,(char *)buf,7);
 }
 
-void sseg_ticker_test(int t)
+/******************************************/
+/*                                        */
+/*  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    a,b,c,d;
-    int     z;
+    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;
     
-    a = sseg_map[t/1000];
-    z = t%1000;
-    b = sseg_map[z/100];
-    z = z%100;
-    c = sseg_map[z/10];
-    z = z%10;
-    d = sseg_map[z];
-    print_seven_seg(a,b,c,d);
+    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);
+    }
 }
\ No newline at end of file