//--- SAA1064 (4-seven-segment) driver-------------------------------- //PIC 18F442 // // 19.12.2017 P. Viljakainen //----------------------------------------------- // Driver for SAA1064 i2c to multiplexed four-digit, seven-segment led display // #include #include #include "saa1064.h" #include "i2c.h" extern void delay_ms(char); // saa1064.c ssa //extern char LED_ADDR0; //extern char LED_CONTROL; int i,j; // SAA1064 write addresses set by connecting pin1 (ADR) to different voltages #define LED_ADDR0 0x70 // ADR to Vee #define LED_ADDR1 0x72 // ADR to 3/8 Vcc #define LED_ADDR2 0x74 // ADR to 5/8 Vcc #define LED_ADDR3 0x76 // ADR to Vcc // Control bits // C0 = 0 = static mode C0 = 1 dynamic mode // C1 = 0/1 digits 1 and 3 are blanked/not blanked // C2 = 0/1 digits 2 and 4 are blanked/not blanked // C3 = 1 all segments outputs turned on for segment test // C4 = 1 adds 3ma to segment output // C5 = 1 adds 6ma to segment output // C6 = 1 adds 12ma to segment output // C7 n/a #define LED_CONTROL 0b01110111 // Dynamic mode 21mA // Segment table (In hex: d.p.=80,g=40,f=20,e=10,d=08,c=04,b=02,a=01) char const seg_table[16]= {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; // 0,1,2,3,4,5,6,7,8,9 /* {0b11111001,0b11000000,0b10110011,0b11100011,0b11001010,0b01101011,0b01111011, 0b11100000,0b11111011,0b11101011,0b11111010,0b01011011,0b00111001,0b11010011, 0b00111011,0b00111010}; // 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F */ char const codeb_table[16]= {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; // 0,1,2,3,4,5,6,7,8,9 /* {0b11111001,0b11000000,0b10110011,0b11100011,0b11001010,0b01101011,0b01111011, 0b11100000,0b11111011,0b11101011,0b00000010,0b00111011,0b11011010,0b00011001, 0b10111010,0b00000000}; // 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F */ char const ascii_table[26]= {0x77,0x7c,0x39,0x5e,0x79,0x71,0x3d,0x74,0x04,0x0e,0x70,0x38,0x37, 0x54,0x5c,0x73,0x67,0x50,0x6d,0x78,0x1c,0x1c,0x1c,0x76,0x6e,0x5b}; // Message examples char const blank[4] = {0x00,0x00,0x00,0x00};// Blank display char const boot[4] = {0x7c,0x5c,0x5c,0b01111000}; // bOOt char const on[4] = {0x00,0x00,0x5c,0x54}; // On char const off[4] = {0x00,0x5c,0x71,0x71}; // OFF enum {blank_,boot_,on_,off_}; //-------------------------------------------------------------------------- // Sends number to four-digit led display via SAA1064 (0 to 9999) void send_saa1064_num(char addr,char control,int num) { char j; // Digit index char led_data[4]; // Ram array for segment data int temp16; // Get led segments for all four digits. Don't need to divide to get units. temp16 = num; j = 0; while (j <= 3) { if (j != 0) temp16 /= 10; led_data[j] = seg_table[temp16 %10]; j++; } // Do leading zero blanking if (num<1000) led_data[3] = 0x00; if (num<100) led_data[2] = 0x00; if (num<10) led_data[1] = 0x00; // Add decimal point if required //led_data[2] |= 0x80; // Send led segments I2CStart(); I2CSend(addr); // Send SAA1064 address I2CSend(0x00); // Send instruction byte. Zero is control reg. I2CSend(control); // Send control byte // Auto increment applies for digit data. Have to send out digits in reverse // because most significant digit is 1st digit. for (j=4;j>=1;j--) I2CSend(led_data[j-1] & 0xff); I2CStop(); } //--------------------------------------------------------------------------- //Sends message to led display via SAA1064 void send_saa1064_msg(char addr,char control,char msg) { char j; char led_data[4]; // Ram array for segments // Get segments for message. switch (msg) { case blank_: // blank_ for(j=0;j<=3;j++) led_data[j] = blank[j]; break; case boot_: //boot_ for(j=0;j<=3;j++) led_data[j] = boot[j]; break; case on_: //on_: for(j=0;j<=3;j++) led_data[j] = on[j]; break; case off_: //off_ for(j=0;j<=3;j++) led_data[j] = off[j]; break; default: for(j=0;j<=3;j++) led_data[j] = blank[j]; break; } // Send led segments I2CStart(); I2CSend(addr); // Send SAA1064 address I2CSend(0x00); // Send instruction byte. Zero is control reg. I2CSend(control); // Send control byte for (j=0;j<=3;j++) I2CSend(led_data[j]); I2CStop(); } //--------------------------------------------------------------------------- void send_saa1064_hex(char addr,char digit,char value) { I2CStart(); I2CSend(addr); // Send SAA1064 address I2CSend(digit+1); // Send instruction byte. Zero is control reg, so digit is 1+control I2CSend(seg_table[value]); // Send segment data I2CStop(); } void send_saa1064_codeb(char addr,char digit,char value) { I2CStart(); I2CSend(addr); // Send SAA1064 address I2CSend(digit+1); // Send instruction byte. Zero is control reg, so digit is 1+control I2CSend(codeb_table[value]); // Send segment data I2CStop(); } void send_saa1064_raw(char addr,char digit,char value) { I2CStart(); I2CSend(addr); // Send SAA1064 address I2CSend(digit+1); // Send instruction byte. Zero is control reg, so digit is 1+control I2CSend(value); // Send segment data I2CStop(); } //Sends scrolling string to led display via SAA1064 void send_saa1064_string(char addr,const char *message,char speed,const char *new_press) { for (i=0;i<(strlen(message)+6);i++) { if (*new_press != 0) return; I2CStart(); I2CSend(addr); I2CSend(1); for (j=0;j<4;j++) { if ((i+j<5)||(i+j>strlen(message)+4)) // blanks before and after message I2CSend(0x00); else if (message[i+j-5] == 0x20) // space I2CSend(0x00); else if (message[i+j-5] == '.' || message[i+j-5] == ',') // comma I2CSend(0x80); else if (message[i+j-5] >= '0' && message[i+j-5] <= '9') // number I2CSend(seg_table[message[i+j-5]-'0']); else I2CSend(ascii_table[message[i+j-5]-'a']); // (hopefully) letter } I2CStop(); delay_ms(speed); } }