Peter Cooper
/
diags
test code for our MBED board
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); } }