Peter Cooper
/
diags
test code for our MBED board
Diff: i2c.c
- 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