oPossum 1,083 Posted March 31, 2012 Share Posted March 31, 2012 This uses code from Software RTC, Using the internal temperature sensor and Nokia 5110 template class. The code has been modified and refined a bit for this project. main.cpp #include #include #include #include #include "nokia7110tl.h" using namespace nokia7110; static const unsigned char ti[] = { 48, 48 / 8, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00,0x00,0xF0, 0xF0,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFC,0xFC,0x3C,0x80,0xFC,0xFD, 0xFD,0xFD,0x3D,0x81,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0x00, 0x00,0x1C,0x7C,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xF7,0xF0,0xF0,0x00,0xF0,0xFF,0xFF,0xFF, 0xFF,0x0F,0xF0,0xF0,0xF0,0xF0,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xF8,0xF0,0x00,0x00, 0x00,0x00,0x00,0x00,0x01,0x03,0x07,0x3F,0x7F,0xFF, 0xFF,0xFF,0xFF,0xFF,0x7F,0x3F,0x3F,0x7F,0xFF,0xFF, 0xFF,0xFF,0xFF,0x1F,0x00,0x1E,0x1F,0x1F,0x1F,0x1F, 0x01,0x1E,0x1F,0xDF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0x7F,0x7F,0x3F,0x3F,0x3F,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x03, 0x0F,0x3F,0xFF,0xFE,0xFE,0xFE,0xFC,0xFC,0xFC,0xFC, 0xFC,0xFC,0xFC,0x7F,0x1F,0x07,0x03,0x03,0x01,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x01,0x07,0x0F,0x0F,0x1F,0x1F,0x3F, 0x3F,0x3F,0x3F,0x1C,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; /* P1.0 Reset P1.3 Temp Sensor (Not used) P2.0 Serial Data P2.1 Backlight P2.2 Chip Select P2.3 Data/Command P2.4 Serial Clock P2.5 Pushbutton */ // P1 static const unsigned LCD_RESET = BIT0; static const unsigned RXD = BIT2; static const unsigned SWITCH = BIT3; // P2 static const unsigned LCD_DATA = BIT0; static const unsigned LCD_BACKLIGHT = BIT1; static const unsigned LCD_CE = BIT2; static const unsigned LCD_DC = BIT3; static const unsigned LCD_CLK = BIT4; static const unsigned LCD_BTN = BIT5; Nokia7110 lcd; void show_time(const struct tm *t) // Show time on LCD { static const char *dow[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; int x, w; const char *s; div_t d; if(t->tm_hour < 10) { x = -2; lcd.fill(0, 0, 9, 2, 0); d.rem = t->tm_hour; } else { x = 3; lcd.fill(0, 0, 3, 2, 0); d = div(t->tm_hour, 10); lcd.pd12(d.quot, x, 0); } lcd.pd12(d.rem, x + 11, 0); lcd.pd12(11, x + 22, 0); d = div(t->tm_min, 10); lcd.pd12(d.quot, x + 27, 0); lcd.pd12(d.rem, x + 38, 0); lcd.pd12(11, x + 49, 0); d = div(t->tm_sec, 10); lcd.pd12(d.quot, x + 54, 0); lcd.pd12(d.rem, x + 65, 0); lcd.fill(x + 76, 0, 7 - x, 2, 0); if(t->tm_mon < 9) { x = -5; lcd.fill(0, 2, 6, 2, 0); d.rem = t->tm_mon + 1; } else { x = 0; d = div(t->tm_mon + 1, 10); lcd.pd12(d.quot, x, 2); } lcd.pd12(d.rem, x + 11, 2); lcd.pd12(13, x + 22, 2); d = div(t->tm_mday, 10); lcd.pd12(d.quot, x + 30, 2); lcd.pd12(d.rem, x + 41, 2); lcd.pd12(13, x + 52, 2); d = div(t->tm_year % 100, 10); lcd.pd12(d.quot, x + 60, 2); lcd.pd12(d.rem, x + 71, 2); if(x) lcd.fill(x + 82, 2, 1 - x, 2, 0); s = dow[t->tm_wday]; w = strlen(s) * 6; x = (83 - w) >> 1; lcd.fill(0, 4, x, 1, 0); lcd.print((unsigned char)x, (unsigned char)4, s); x += w; lcd.fill(x, 4, 83 - x, 1, 0); } // Print integer from -999 to 9999 using 12 x 16 font void print_int(int i, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; unsigned x = 48; do { d = div(d.quot, 10); lcd.pd12(d.rem, x -= 12, y); } while(d.quot); if(neg) lcd.pd12(14, x -= 12, y); while(x) lcd.pd12(10, x -= 12, y); } // Print integer from -999 to 9999 using 6 x 8 font void print_int(int i, unsigned x, const unsigned y) { if(i < -999 || i > 9999) return; const unsigned e = x; x += 24; const unsigned neg = i < 0; if(neg) i = -i; div_t d; d.quot = i; do { d = div(d.quot, 10); lcd.print(x -= 6, y, '0' + d.rem); } while(d.quot); if(neg) lcd.print(x -= 6, y, '-'); while(x > e) lcd.print(x -= 6, y, ' '); } void draw_bargraph(int f) { int x, y, bg; char c; unsigned char bgc[9] = { 0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0 }; char *bgl[8] = { "90", "80", "70", "60", "50", "40", "30", "20" }; x = 20; // bg = (f - (x - 5)) * 4 / 5; // for(y = 7; y >= 0; --y) { // lcd.pos(83, y); // if(bg < 0) { c = bgc[8]; } else if (bg > 7) { c = bgc[7]; } else { c = bgc[bg]; } lcd.write((unsigned char *)&c, 1, lcd_data); lcd.print(bgl[y], c); bg -= 8; } // } time_t tt; // Time in seconds since epoch unsigned adc; // ADC value #pragma vector = WDT_VECTOR // - Watchdog timer interrupt vector __interrupt void wdt_isr(void) // This interrupt will occur once per second { // ++tt; // Increment time_t __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // // #pragma vector = ADC10_VECTOR // ADC conversion complete interrupt __interrupt void ADC10_ISR(void) // { // adc = ADC10MEM; // Read ADC __bic_SR_register_on_exit(LPM0_bits); // Wakeup main code } // int main(void) { int x, y; char c; struct tm ts; int dc, dk, df; // Temperature in degrees C, K, and F WDTCTL = WDTPW | WDTHOLD; P1REN = RXD | SWITCH; P1DIR = LCD_RESET; P1OUT = RXD | SWITCH | LCD_RESET; P2DIR = LCD_DC | LCD_CE | LCD_CLK | LCD_BACKLIGHT | LCD_DATA; P2REN = LCD_BTN; P2OUT = LCD_CLK | LCD_DC | LCD_CE | LCD_BACKLIGHT | LCD_BTN; ADC10CTL0 = 0; // Configure ADC ADC10CTL1 = INCH_10 | ADC10DIV_3; // ADC10CTL0 = SREF_1 | ADC10SHT_3 | REFON | ADC10ON | ADC10IE; ADC10CTL0 |= ADC10IE; // Enable ADC conversion complete interrupt // // 32 kHz xtal loading //BCSCTL3 = XCAP_1; // 6 pF (default) BCSCTL3 = XCAP_2; // 10 pF //BCSCTL3 = XCAP_3; // 12.5 pF // WDTCTL = WDTPW | WDTTMSEL | WDTCNTCL | WDTSSEL; // Use WDT as interval timer IE1 |= WDTIE; // Enable WDT interrupt _EINT(); // Enable interrupts // // Set initial time - there is no UI for this ts.tm_hour = 13; // Hour ts.tm_min = 37; // Minute ts.tm_sec = 42; // Second ts.tm_mon = 3; // Month (0 based!) ts.tm_mday = 20; // Day of Month ts.tm_year = 2012 - 1900; // Year ts.tm_wday = 5; // Day of Week - Not used by mktime() ts.tm_yday = 0; // Not used by mktime() ts.tm_isdst = 0; // DST flag - Not used by rtc_tick() // tt = mktime(&ts); // Convert tm struct to time_t // lcd.reset(); lcd.init(); lcd.clear(); lcd.print(30, 6, "MSP430"); lcd.print(18, 7, "Nokia 7110"); for(x = -47; x < 24; ++x) { lcd.bitmap(ti, x, 0); __delay_cycles(20000); } __delay_cycles(2000000); for(; x < 96; ++x) { lcd.bitmap(ti, x, 0); __delay_cycles(20000); } lcd.clear(); lcd.print(9, 7, "Character Set"); x = y = 0; lcd.pos(x, y); for(c = 32; c < 128; ++c) { lcd.print(c); if(++x >= 16) x = 0, lcd.pos(x, ++y); } __delay_cycles(3000000); lcd.clear(); ts.tm_hour = ts.tm_min = ts.tm_sec = 88; ts.tm_mon = 87; ts.tm_mday = ts.tm_year = 88; ts.tm_wday = 5; show_time(&ts); lcd.pd12(15, 48, 5); lcd.pd12(17, 59, 5); lcd.print(24, 7, "\x7F""C"); lcd.print(66, 7, "\x7F""K"); print_int(8888, 5); print_int(8888, 0, 7); print_int(8888, 42, 7); for(x = 15; x < 96; ++x) draw_bargraph(x); __delay_cycles(3000000); lcd.clear(); // lcd.pd12(15, 48, 5); // Degrees lcd.pd12(17, 59, 5); // F lcd.print(24, 7, "\x7F""C"); // C lcd.print(66, 7, "\x7F""K"); // K // for(; { // for-ever show_time(localtime(&tt)); // Convert time_t to tm struct and show on LCD __bis_SR_register(LPM0_bits + GIE); // Sleep until WDT interrupt ADC10CTL0 |= (ENC | ADC10SC); // Begin ADC conversion __bis_SR_register(LPM0_bits + GIE); // Sleep until conversion complete // // Convert to temperature dc = ((27069L * adc) - 18169625L) >> 16; // Vref = 1.5V dk = ((27069L * adc) - 268467L) >> 16; // Vref = 1.5V df = ((48724L * adc) - 30634388L) >> 16; // Vref = 1.5V // // Display on LCD print_int(df, 5); // Degrees F print_int(dc, 0, 7); // Degrees C print_int(dk, 42, 7); // Degrees K draw_bargraph(df); // Deg F Bargraph } // return 0; } nokia7110tl.h - C++ template class for Nokia 7110 (SED1565) namespace nokia7110 { unsigned char PNONE; typedef enum { lcd_command = 0, // Array of one or more commands lcd_data = 1, // Array of one or more bytes of data lcd_data_repeat = 2 // One byte of data repeated } lcd_cmd_type; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> struct Nokia7110 { void write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type = lcd_data); void reset(void); void init(void); void home(void); void pos(unsigned char x, unsigned char y); void clear(unsigned char x = 0); void fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z); void bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h); inline void bitmap(const unsigned char *bmp, signed char x, signed char y) { bitmap(bmp + 2, x, y, bmp[0], bmp[1]); }; void print(char c); inline void print(unsigned char x, unsigned char y, char c) { pos(x, y); print(c); }; void print(const char *s); inline void print(unsigned char x, unsigned char y, const char *s) { pos(x, y); print(s); }; void print(const char *s, unsigned char m); void printv(unsigned char x, unsigned char y, char *s); void pd12(unsigned n, unsigned x, unsigned y); }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::write(const unsigned char *cmd, unsigned len, const lcd_cmd_type type) { register unsigned mask; if(&_EP != &PNONE) _EP &= ~_CE; do { mask = 0x0080; do { if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; mask >>= 1; } while(!(mask & 1)); if(&_CP == &PNONE) { __delay_cycles(_DC); } else { if(!type) _CP &= ~_DC; } if(*cmd & mask) { _SP |= _DATA; _SP &= ~_CLK; } else { _SP &= ~(_CLK | _DATA); } _SP |= _CLK; if(&_CP != &PNONE) _CP |= _DC; if(!(type & 2)) ++cmd; } while(--len); if(&_EP != &PNONE) _EP |= _CE; } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::reset(void) { if(&_RP == &PNONE) { // --- Set initial state of CLK, DC and CE as needed // * = output used for reset if(&_CP == &PNONE) { if(&_EP != &PNONE) { // CLK*, DATA, CE _EP |= _CE; } // else // CLK*, DATA } else { if(&_EP != &PNONE) { // CLK, DATA, DC*, CE if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { // CLK, DATA, DC* _SP |= _CLK; } } // --- Reset pulse on CLK or DC as needed if(&_CP == &PNONE) { // No DC port, use CLK to reset _SP &= ~_CLK; __delay_cycles(_RD); _SP |= _CLK; } else { // Use DC to reset _CP &= ~_DC; __delay_cycles(_RD); _CP |= _DC; } } else { _RP &= ~_RST; if(&_EP != &PNONE) { if(&_SP == &_EP) { _SP |= (_CLK | _CE); } else { _SP |= _CLK; _EP |= _CE; } } else { _SP |= _CLK; } __delay_cycles(_RD); _RP |= _RST; } __delay_cycles(_RD); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::init(void) { static const unsigned char init[] = { 0xA6, //Display: Normal 0xA3, //LCD Bias Settings: 1/7 0xA1, //ADC Selection: Reverse 0xC0, //Common Output: Normal Direction //0xC8, //Common Output: Upside Down 0x22, //Set the V5 output Voltage 0x81, //Set Electronic Volume Register 0x2E, //Power Controller Set // Booster circuit: ON // Voltage regulator circuit: ON // Voltage follower circuit: OFF 0x2F, //Power Controller Set // Voltage follower circuit: ON 0xE3, //Non-OPeration Command 0x40, //Set the start line 0xAF, //LCD On //0xA5, //Display All Points: ON 0xA4, //Display All Points: NORMAL }; write(init, sizeof(init), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::home(void) { static const unsigned char home[] = { 0xB0, 0x11, 0x02 }; write(home, sizeof(home), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pos(unsigned char x, unsigned char y) { unsigned char c[3]; x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; write(c, sizeof(c), lcd_command); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::clear(unsigned char x) { for(unsigned y = 0; y < 9; ++y) { pos(0, y); write(&x, 96, lcd_data_repeat); } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::fill(unsigned x, unsigned y, unsigned w, unsigned h, unsigned char z) { unsigned yy = y + h; unsigned char c[3]; x += 18; c[1] = 0x10 | (x >> 4); c[2] = (x & 0x0F); for(;y < yy; ++y) { c[0] = 0xB0 | y; write(c, sizeof(c), lcd_command); write(&z, w, lcd_data_repeat); } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::bitmap(const unsigned char *bmp, signed char x, signed char y, unsigned char w, unsigned char h) { unsigned char c[3]; unsigned char ww; if(x < 0) { ww = w + x; bmp -= x; x = 0; } else if(x + w >= 96) { ww = (96 - x); } else { ww = w; } x += 18; c[0] = 0xB0 | y; c[1] = 0x10 | (x >> 4); c[2] = x & 0x0F; while(h--) { write(c, sizeof(c), lcd_command); write(bmp, ww); bmp += w; ++c[0]; } } static const unsigned char font[96][5] = { 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00, 0x00, 0x5F, 0x00, 0x00, // ! 0x00, 0x07, 0x00, 0x07, 0x00, // " 0x14, 0x7F, 0x14, 0x7F, 0x14, // # 0x24, 0x2A, 0x7F, 0x2A, 0x12, // $ 0x23, 0x13, 0x08, 0x64, 0x62, // % 0x36, 0x49, 0x56, 0x20, 0x50, // & 0x00, 0x08, 0x07, 0x03, 0x00, // ' 0x00, 0x1C, 0x22, 0x41, 0x00, // ( 0x00, 0x41, 0x22, 0x1C, 0x00, // ) 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, // * 0x08, 0x08, 0x3E, 0x08, 0x08, // + 0x00, 0x40, 0x38, 0x18, 0x00, // , 0x08, 0x08, 0x08, 0x08, 0x08, // - 0x00, 0x00, 0x60, 0x60, 0x00, // . 0x20, 0x10, 0x08, 0x04, 0x02, // / 0x3E, 0x51, 0x49, 0x45, 0x3E, // 0 0x00, 0x42, 0x7F, 0x40, 0x00, // 1 0x42, 0x61, 0x51, 0x49, 0x46, // 2 0x21, 0x41, 0x49, 0x4D, 0x33, // 3 0x18, 0x14, 0x12, 0x7F, 0x10, // 4 0x27, 0x45, 0x45, 0x45, 0x39, // 5 0x3C, 0x4A, 0x49, 0x49, 0x30, // 6 0x41, 0x21, 0x11, 0x09, 0x07, // 7 0x36, 0x49, 0x49, 0x49, 0x36, // 8 0x06, 0x49, 0x49, 0x29, 0x1E, // 9 0x00, 0x00, 0x14, 0x00, 0x00, // : 0x00, 0x00, 0x40, 0x34, 0x00, // ; 0x00, 0x08, 0x14, 0x22, 0x41, // < 0x14, 0x14, 0x14, 0x14, 0x14, // = 0x00, 0x41, 0x22, 0x14, 0x08, // > 0x02, 0x01, 0x51, 0x09, 0x06, // ? 0x3E, 0x41, 0x5D, 0x59, 0x4E, // @ 0x7C, 0x12, 0x11, 0x12, 0x7C, // A 0x7F, 0x49, 0x49, 0x49, 0x36, // B 0x3E, 0x41, 0x41, 0x41, 0x22, // C 0x7F, 0x41, 0x41, 0x41, 0x3E, // D 0x7F, 0x49, 0x49, 0x49, 0x41, // E 0x7F, 0x09, 0x09, 0x09, 0x01, // F 0x3E, 0x41, 0x49, 0x49, 0x7A, // G 0x7F, 0x08, 0x08, 0x08, 0x7F, // H 0x00, 0x41, 0x7F, 0x41, 0x00, // I 0x20, 0x40, 0x41, 0x3F, 0x01, // J 0x7F, 0x08, 0x14, 0x22, 0x41, // K 0x7F, 0x40, 0x40, 0x40, 0x40, // L 0x7F, 0x02, 0x1C, 0x02, 0x7F, // M 0x7F, 0x04, 0x08, 0x10, 0x7F, // N 0x3E, 0x41, 0x41, 0x41, 0x3E, // O 0x7F, 0x09, 0x09, 0x09, 0x06, // P 0x3E, 0x41, 0x51, 0x21, 0x5E, // Q 0x7F, 0x09, 0x19, 0x29, 0x46, // R 0x26, 0x49, 0x49, 0x49, 0x32, // S 0x01, 0x01, 0x7F, 0x01, 0x01, // T 0x3F, 0x40, 0x40, 0x40, 0x3F, // U 0x1F, 0x20, 0x40, 0x20, 0x1F, // V 0x3F, 0x40, 0x38, 0x40, 0x3F, // W 0x63, 0x14, 0x08, 0x14, 0x63, // X 0x03, 0x04, 0x78, 0x04, 0x03, // Y 0x61, 0x51, 0x49, 0x45, 0x43, // Z 0x00, 0x7F, 0x41, 0x41, 0x41, // [ 0x02, 0x04, 0x08, 0x10, 0x20, // '\' 0x00, 0x41, 0x41, 0x41, 0x7F, // ] 0x04, 0x02, 0x01, 0x02, 0x04, // ^ 0x80, 0x80, 0x80, 0x80, 0x80, // _ 0x00, 0x03, 0x07, 0x08, 0x00, // ' 0x20, 0x54, 0x54, 0x54, 0x78, // a 0x7F, 0x28, 0x44, 0x44, 0x38, // b 0x38, 0x44, 0x44, 0x44, 0x28, // c 0x38, 0x44, 0x44, 0x28, 0x7F, // d 0x38, 0x54, 0x54, 0x54, 0x18, // e 0x00, 0x08, 0x7E, 0x09, 0x02, // f 0x18, 0xA4, 0xA4, 0xA4, 0x7C, // g 0x7F, 0x08, 0x04, 0x04, 0x78, // h 0x00, 0x44, 0x7D, 0x40, 0x00, // i 0x00, 0x20, 0x40, 0x40, 0x3D, // j 0x00, 0x7F, 0x10, 0x28, 0x44, // k 0x00, 0x41, 0x7F, 0x40, 0x00, // l 0x7C, 0x04, 0x78, 0x04, 0x78, // m 0x7C, 0x08, 0x04, 0x04, 0x78, // n 0x38, 0x44, 0x44, 0x44, 0x38, // o 0xFC, 0x18, 0x24, 0x24, 0x18, // p 0x18, 0x24, 0x24, 0x18, 0xFC, // q 0x7C, 0x08, 0x04, 0x04, 0x08, // r 0x48, 0x54, 0x54, 0x54, 0x24, // s 0x04, 0x04, 0x3F, 0x44, 0x24, // t 0x3C, 0x40, 0x40, 0x20, 0x7C, // u 0x1C, 0x20, 0x40, 0x20, 0x1C, // v 0x3C, 0x40, 0x30, 0x40, 0x3C, // w 0x44, 0x28, 0x10, 0x28, 0x44, // x 0x4C, 0x90, 0x90, 0x90, 0x7C, // y 0x44, 0x64, 0x54, 0x4C, 0x44, // z 0x00, 0x08, 0x36, 0x41, 0x00, // { 0x00, 0x00, 0x77, 0x00, 0x00, // | 0x00, 0x41, 0x36, 0x08, 0x00, // } 0x02, 0x01, 0x02, 0x04, 0x02, // ~ 0x00, 0x06, 0x09, 0x09, 0x06, // degrees }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(char c) { write(&font[c - 32][0], 5); write(&font[0][0], 1); } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s) { while(*s) { write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::print(const char *s, unsigned char m) { unsigned char c; while(*s) { c = font[*s - 32][0] ^ m; write(&c, 1); c = font[*s - 32][1] ^ m; write(&c, 1); c = font[*s - 32][2] ^ m; write(&c, 1); c = font[*s - 32][3] ^ m; write(&c, 1); c = font[*s - 32][4] ^ m; write(&c, 1); write(&m, 1); ++s; } } template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::printv(unsigned char x, unsigned char y, char *s) { while(*s) { pos(x, y); ++y; write(&font[*s - 32][0], 5); write(&font[0][0], 1); ++s; } } static const unsigned char num11x16[19][11 * 2] = { 0x00,0xF0,0xFC,0xFE,0x06,0x02,0x06,0xFE,0xFC,0xF0,0x00, // 0 0x00,0x07,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x07,0x00, 0x00,0x00,0x08,0x0C,0xFC,0xFE,0xFE,0x00,0x00,0x00,0x00, // 1 0x00,0x20,0x20,0x20,0x3F,0x3F,0x3F,0x20,0x20,0x20,0x00, 0x00,0x0C,0x0E,0x06,0x02,0x02,0x86,0xFE,0x7C,0x38,0x00, // 2 0x00,0x30,0x38,0x3C,0x36,0x33,0x31,0x30,0x30,0x38,0x00, 0x00,0x0C,0x0E,0x86,0x82,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 3 0x00,0x18,0x38,0x30,0x20,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x00,0xC0,0x20,0x18,0x04,0xFE,0xFE,0xFE,0x00,0x00, // 4 0x00,0x03,0x02,0x02,0x02,0x22,0x3F,0x3F,0x3F,0x22,0x02, 0x00,0x00,0x7E,0x7E,0x46,0x46,0xC6,0xC6,0x86,0x00,0x00, // 5 0x00,0x18,0x38,0x30,0x20,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0xC0,0xF0,0xF8,0xFC,0x4C,0xC6,0xC2,0x82,0x00,0x00, // 6 0x00,0x0F,0x1F,0x3F,0x30,0x20,0x30,0x3F,0x1F,0x0F,0x00, 0x00,0x06,0x06,0x06,0x06,0x06,0xC6,0xF6,0x3E,0x0E,0x00, // 7 0x00,0x00,0x00,0x30,0x3C,0x0F,0x03,0x00,0x00,0x00,0x00, 0x00,0x38,0x7C,0xFE,0xC6,0x82,0xC6,0xFE,0x7C,0x38,0x00, // 8 0x00,0x0E,0x1F,0x3F,0x31,0x20,0x31,0x3F,0x1F,0x0E,0x00, 0x00,0x78,0xFC,0xFE,0x86,0x02,0x86,0xFE,0xFC,0xF8,0x00, // 9 0x00,0x00,0x00,0x21,0x21,0x31,0x1D,0x1F,0x0F,0x03,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x70,0x70,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // : 0x00,0x0E,0x0E,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, // . 0x00,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0xC0,0x30,0x0C,0x00,0x00,0x00,0x00, // / 0x00,0x30,0x0C,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x80, // - 0x00,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x00,0x18,0x3C,0x66,0x66,0x3C,0x18,0x00,0x00,0x00,0x00, // 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xF0,0xF8,0x0C,0x06,0x02,0x02,0x02,0x02,0x0E,0x0C,0x00, // C 0x03,0x07,0x0C,0x18,0x10,0x10,0x10,0x10,0x1C,0x0C,0x00, 0xFE,0xFE,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,0x00, // F 0x1F,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0xFE,0xFE,0x40,0xE0,0xB0,0x18,0x0C,0x06,0x02,0x00,0x00, // K 0x1F,0x1F,0x00,0x00,0x01,0x03,0x06,0x0C,0x18,0x10,0x00 }; template volatile unsigned char &_EP, unsigned char _CE, volatile unsigned char &_RP, unsigned char _RST, unsigned _RD> void Nokia7110<_SP, _CLK, _DATA, _CP, _DC, _EP, _CE, _RP, _RST, _RD>::pd12(unsigned n, unsigned x, unsigned y) { pos(x, y); write(num11x16[n], 11, lcd_data); pos(x, ++y); write(num11x16[n] + 11, 11, lcd_data); } } // namespace kff2, randal23, tom_launch_bav and 11 others 14 Quote Link to post Share on other sites
bluehash 1,581 Posted March 31, 2012 Share Posted March 31, 2012 My LP will finally have a use on my desk once SA's LCDs ship. Thanks oPossum. Quote Link to post Share on other sites
username 198 Posted April 1, 2012 Share Posted April 1, 2012 Awesome project oPossum! Thanks for sharing! Quote Link to post Share on other sites
timotet 44 Posted April 1, 2012 Share Posted April 1, 2012 Very cool! Thanks for doing all the work. Between you and RobG we can all just plug and play. Sweet! Quote Link to post Share on other sites
SugarAddict 227 Posted April 2, 2012 Share Posted April 2, 2012 Very cool!Thanks for doing all the work. Between you and RobG we can all just plug and play. Sweet! That was the goal :twisted: Quote Link to post Share on other sites
greeeg 460 Posted April 10, 2012 Share Posted April 10, 2012 Nice work. In the video that temperature seemed to jump around quite a bit, thought of adding a SW filter to smooth it out? Or maybe slow the update rate of the temperature? Quote Link to post Share on other sites
K5HJ 0 Posted April 19, 2012 Share Posted April 19, 2012 Very nice. Thanks for the code. I just got my SugarAddict board and dropped this code in. Works right out of the box. I did find an issue with the 7110 init code. The array init[] has a missing value for the contrast setting. After the 0x81 line, I added an 0x33 for optimum contrast on my display. static const unsigned char init[] = { 0xA6, //Display: Normal 0xA3, //LCD Bias Settings: 1/7 0xA1, //ADC Selection: Reverse 0xC0, //Common Output: Normal Direction //0xC8, //Common Output: Upside Down 0x22, //Set the V5 output Voltage 0x81, //Set Electronic Volume Register 0x33, //Contrast setting <-- ADD THIS 0x2E, //Power Controller Set // Booster circuit: ON // Voltage regulator circuit: ON // Voltage follower circuit: OFF 0x2F, //Power Controller Set // Voltage follower circuit: ON 0xE3, //Non-OPeration Command 0x40, //Set the start line 0xAF, //LCD On //0xA5, //Display All Points: ON 0xA4, //Display All Points: NORMAL }; Randy Quote Link to post Share on other sites
K5HJ 0 Posted April 19, 2012 Share Posted April 19, 2012 Looks like I jumped the gun. :oops: I thought the 0x2E value was "Power control set", like the comments say. It is not, it is the contrast setting. As it turns out, that setting is too low on my hardware. So, don't add the extra line. Very nice. Thanks for the code. I just got my SugarAddict board and dropped this code in. Works right out of the box. I did find an issue with the 7110 init code. The array init[] has a missing value for the contrast setting. After the 0x81 line, I added an 0x33 for optimum contrast on my display. static const unsigned char init[] = { 0xA6, //Display: Normal 0xA3, //LCD Bias Settings: 1/7 0xA1, //ADC Selection: Reverse 0xC0, //Common Output: Normal Direction //0xC8, //Common Output: Upside Down 0x22, //Set the V5 output Voltage 0x81, //Set Electronic Volume Register 0x33, //Contrast setting <-- ADD THIS 0x2E, //Power Controller Set // Booster circuit: ON // Voltage regulator circuit: ON // Voltage follower circuit: OFF 0x2F, //Power Controller Set // Voltage follower circuit: ON 0xE3, //Non-OPeration Command 0x40, //Set the start line 0xAF, //LCD On //0xA5, //Display All Points: ON 0xA4, //Display All Points: NORMAL }; Randy Quote Link to post Share on other sites
kff2 22 Posted April 24, 2012 Share Posted April 24, 2012 __delay_cycles(_DC) in nokia7110tl.h should be __delay_cycles(_RD), no? Many thanks for sharing this code! Quote Link to post Share on other sites
kff2 22 Posted April 24, 2012 Share Posted April 24, 2012 Some notes on compiling this with msp430-gcc. 1) To handle C++ templates in nokia7110tl.h, you need to a version of msp430-gcc with C++ support. If building from sources, configure with --enable_languages=c,c++. The packaged msp430-gcc in recent versions of Ubuntu should already be C++ enabled. To compile C++ code, use msp430-g++ instead of msp430-gcc. You will likely get the error ld: cannot find -lstdc++ This is because msp430-g++ links against the C++ standard library by default, which is not included with msp430-gcc. To work around, run msp430-g++ as follows: msp430-g++ -mmcu=msp430g2452 -o time.elf main.cpp -nodefaultlibs -fno-rtti -fno-exceptions -lc -lgcc This tells msp430-g++ not to use default libraries. You then need to explicitly list the default libraries that you need (-lc and -lgcc). -fno-rtti -fno-exceptions eliminates some C++ bloat and reduces code size. 2) time.h is not included with msp430-gcc. I used this version which I found somewhere on the internet: typedef long time_t; /* for representing times in seconds */ struct tm { int tm_sec; int tm_min; int tm_hour; int tm_mday; int tm_mon; int tm_year; int tm_wday; int tm_yday; int tm_isdst; }; const unsigned char moninit[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; static unsigned dylen(unsigned yr) { if(yr%4 || (yr % 100) == 0 && ((yr+300)%400) != 0) return(365); return(366); } struct tm * gmtime(time_t * tp) { time_t t; static struct tm tim; t = *tp; tim.tm_sec = t % 60L; t /= 60L; tim.tm_min = t % 60L; t /= 60L; tim.tm_hour = t % 24L; tim.tm_mday = t / 24L; tim.tm_wday = (tim.tm_mday + 4) % 7; tim.tm_year = 70; while(tim.tm_mday >= dylen(tim.tm_year)) { tim.tm_mday -= dylen(tim.tm_year); tim.tm_year++; } tim.tm_yday = tim.tm_mday; if(tim.tm_mday >= 59 && dylen(tim.tm_year) == 366) tim.tm_mday--; tim.tm_mon = 0; while(tim.tm_mday >= moninit[tim.tm_mon]) { tim.tm_mday -= moninit[tim.tm_mon]; tim.tm_mon++; } tim.tm_mday++; return &tim; } struct tm * localtime(time_t * tp) { time_t t; t = *tp - 7 * 3600L; return gmtime(&t); } Notice that there is no mktime function here. Instead, in main.cpp, I set tt to the current unix timestamp (obtained with "date +%s" in Linux). Also, the localtime function here hardcodes my timezone. Change accordingly. 3) This original code causes the LCD to go berserk when compiled under msp430-gcc: for(c = 32; c < 128; ++c) { lcd.print(c); if(++x >= 16) x = 0, lcd.pos(x, ++y); } That's because c is a signed byte value, and the compiler treats 128 as -1, causing an infinite loop. What you want instead is for(c = 32; c < 128U; ++c) { lcd.print(c); if(++x >= 16) x = 0, lcd.pos(x, ++y); } Hope this will be useful to somebody. gordon, oPossum and flying4fun 3 Quote Link to post Share on other sites
CptanPanic 5 Posted May 19, 2012 Share Posted May 19, 2012 I tried to build this for CCS5, but doesn't seem like it knows about C++. Is there a way to enable c++, to get this to build in CCS5? Quote Link to post Share on other sites
timotet 44 Posted May 19, 2012 Share Posted May 19, 2012 Did you name the main with .cpp when you created your project? Thats how I compiled it with CCSV5. hope this helps Quote Link to post Share on other sites
CptanPanic 5 Posted May 20, 2012 Share Posted May 20, 2012 Did you name the main with .cpp when you created your project?Thats how I compiled it with CCSV5. hope this helps Thanks that worked. I missed that one. Quote Link to post Share on other sites
Rei Vilo 695 Posted May 26, 2012 Share Posted May 26, 2012 I ported the sketch to Energia, the Arduino 1.0-based IDE for the LaunchPad. Learn more at this thread :arrow: Thermometer with Nokia 7110 LCD on Energia. The code is available at the :arrow: Energia repository, under Energia / examples / 7.Display / Nokia7110_430. Feel free to participate! Quote Link to post Share on other sites
kff2 22 Posted May 26, 2012 Share Posted May 26, 2012 I may be missing something, but it looks like you copied oPossum's code verbatim and then added the following header to his code: // Project Nokia7110_430b // Created by Rei VILO on 26/05/12 // Copyright © 2012 http://embeddedcomputing.weebly.com https://github.com/energia/Energia/blob ... _library.h Please give proper attribution to oPossum in all source files that use his code. Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.