/** Define a glyph */ void lcd_glyph_P(const uint8_t index, const uint8_t* array) { lcd_addr_cg(index * 8); for (uint8_t i = 0; i < 8; ++i) { lcd_write(pgm_read_byte(&array[i])); } // restore previous position lcd_xy(_pos.x, _pos.y); _addrtype = TEXT; }
// display an icon at position x,y void d_icon(int x,int y) //display first bit of 8x8 icon at x,y position { char i,j; if (p_x%16 <8) //if x position is on upper byte of 16 bit { for (j=0;j<8;j++) //repeat for 8 vertical line { lcd_xy(p_x/16,(p_y+j)%64); //go to the location and y is re-adjust after adding j ( > 64 after adding j ) send_char(0); //send upperbyte with shifting according to the x position send_char(0); //send lowerbyte with shifting according to the x position } } else { for (j=0;j<8;j++) { lcd_xy(p_x/16,(p_y+j)%64); //go to the location and y is re-adjust after adding j ( > 64 after adding j ) send_char (0); //send dummy data to the upperbyte send_char(0); //send lowerbyte data with shifting according to the x position if(p_x/16 == 7) lcd_xy(0,p_y+j); send_char(0); //send upperbyte of the next 'x' with shifting according to the x position } } if (x%16 <8) //if x position is on upper byte of 16 bit { for (j=0;j<8;j++) //repeat for 8 vertical line { lcd_xy(x/16,(y+j)%64); //go to the location and y is re-adjust after adding j ( > 64 after adding j ) send_char(icon[j]>> x%8); //send upperbyte with shifting according to the x position send_char(icon[j]<< (8-x%8)); //send lowerbyte with shifting according to the x position } } else { for (j=0;j<8;j++)
int main( void ) { uint32_t val = 0; char s[sizeof("4294967295")]; // ASCII space for 32 bit number char textbuf [ 16 + 1 ]; //_delay_ms ( 5000 ); lcd_init(); #if 1 char *p; if ( 1 ) { char *source = "68u65gujl"; unsigned int i; for ( i = 0; i < strlen ( source ); i++ ) { textbuf [ i ] = source [ i ]; } textbuf [ i ] = '\0'; lcd_xy( 0, 0 ); lcd_puts( textbuf ); // display number right adjusted } #endif #if 0 for(;;){ ultoa( val, s, 10 ); lcd_xy( 0, 1 ); lcd_blank( 10 - strlen( s )); // insert spaces until number lcd_puts( s ); // display number right adjusted val++; } #endif return ( 0 ); }
/** Write a data byte */ void lcd_write(uint8_t bb) { if (_addrtype == TEXT) { if (bb == '\r') { // CR _pos.x = 0; lcd_xy(_pos.x, _pos.y); return; } if (bb == '\n') { // LF _pos.y++; lcd_xy(_pos.x, _pos.y); return; } _pos.x++; } _lcd_wait_bf(); pin_high(LCD_RS); // select data register _lcd_write_byte(bb); // send data byte }
void lcd_puts_xy(uint8_t x, uint8_t y, const char *str) { for (lcd_xy(x, y); x < LCD_STRIDE && *str; ++x, ++str) { lcd_putc(*str); } }
char _key_string(char __mode) { unsigned char __chr = 0, __i = 0; uint8_t __key = 0; if(__mode==0) { CURSOR_SHOW; while(1) { __key = _key_scan(_PAD_SINGLE); if(__key==_KEY_NULL || __key==_KEY_TIKET || __key==_KEY_MENU || __key==_KEY_SHIFT); else if(__key==_KEY_CANCEL) { __chr_count = 0; CURSOR_HIDE; _SHIFT_OFF;// return 1; } else if(__key==_KEY_ENTER) { __chr_count = 0; CURSOR_HIDE; _SHIFT_OFF;// return 0; } else if(__key==_KEY_CLEAR) { if(__chr_count>0) { _LCD_LEFT; _lcd(0x10); _LCD_LEFT; __buf_string[__chr_count-1] = '\0'; __chr_count--; } } else { if(__chr_count<__max_string) { _lcd(_table_alphanum(0, __key, 0)); __buf_string[__chr_count] = _table_alphanum(0, __key, 0); __buf_string[__chr_count + 1] = '\0'; __chr_count++; } } } } if(__mode==_STRING_ALPHANUM) { while(1) { CURSOR_SHOW; __key = _key_scan(_PAD_MULTI); if(__key == _KEY_NULL || __key == _KEY_TIKET || __key == _KEY_MENU); else if(__key == _KEY_CANCEL) { CURSOR_HIDE; _SHIFT_OFF; return 1; } else if(__key == _KEY_ENTER) { CURSOR_HIDE; _SHIFT_OFF; return 0; } else if(__key == _KEY_SHIFT) { __caps_lock = __caps_lock ^ 1; } else if(__key == _KEY_CLEAR) { if(__chr_count > 0) { if(!__key_shift) { _LCD_LEFT; _lcd(0x10); _LCD_LEFT; __buf_string[__chr_count - 1] = '\0'; __chr_count--; if(__chr_count == 19) { lcd_put(2, 20, 0x10); lcd_xy(2, 20); } _SHIFT_OFF; CURSOR_SHOW; //_SHIFT_FREE; } } } else { if(__chr_count < __max_string) { if(__key != __buf_anum) { __buf_anum = __key; __hit_count = 0; if(__key_shift == 1 && __buf_anum != 0) { _LCD_RIGHT; __chr_count++; if(__chr_count == 20) lcd_xy(3, 1); } } else { __hit_count++; } __chr = _table_alphanum(__caps_lock, __key, __hit_count); if(__chr == '\0') { __hit_count = 0; __chr = _table_alphanum(__caps_lock, __key, __hit_count); } if(__chr_count < __max_string) { _lcd(__chr); _LCD_LEFT; __buf_string[__chr_count] = __chr; __buf_string[__chr_count + 1] = '\0'; } } CURSOR_SHOW; //else _SHIFT_LOCK; } } } if(__mode==_STRING_PASSWORD) { CURSOR_SHOW; while(1) { __key = _key_scan(_PAD_SINGLE); if(__key==_KEY_NULL || __key==_KEY_TIKET || __key==_KEY_MENU || __key==_KEY_SHIFT); else if(__key==_KEY_CANCEL) { __chr_count = 0; CURSOR_HIDE; return 1; } else if(__key==_KEY_ENTER) { __chr_count = 0; CURSOR_HIDE; return 0; } else if(__key==_KEY_CLEAR) { if(__chr_count>0) { _LCD_LEFT; _lcd(0x10); _LCD_LEFT; __buf_string[__chr_count-1] = '\0'; __chr_count--; } } else { if(__chr_count<__max_string) { _lcd(0x2a); __buf_string[__chr_count] = _table_alphanum(0, __key, 0); __buf_string[__chr_count + 1] = '\0'; __chr_count++; } } } } if(__mode==_STRING_VALUE) { for(__i=0; __i<__max_string; __i++) _lcd('0'); while(1) { __key = _key_scan(_PAD_SINGLE); if(__key==_KEY_NULL || __key==_KEY_TIKET || __key==_KEY_MENU || __key==_KEY_SHIFT || __key==_KEY_CLEAR); else if(__key==_KEY_CANCEL) { __chr_count = 0; CURSOR_HIDE; return 1; } else if(__key==_KEY_ENTER) { __chr_count = 0; CURSOR_HIDE; return 0; } else { for(__i=0; __i<__max_string - 1; __i++) __buf_string[__i] = __buf_string[__i + 1]; __buf_string[__max_string - 1] = _table_alphanum(0, __key, 0); __buf_string[__max_string] = '\0'; for(__i=0; __i<__max_string; __i++) _LCD_LEFT; for(__i=0; __i<__max_string; __i++) _lcd(__buf_string[__i]); } } } return 0; }
int main( void ) { uint32_t val = 0; char textbuf [ (2*16) + 1 ]; // lcd /* setup */ // LCD lcd_init(); // Timer: enable a timer so we can measure passage of time // // Given: 20MHz clock // --> if we want resolution of ms (1/1000th second) .. actually, we want us (1/10th of a ms) so we can measure partial ms // --> and we have 1/20000000 clock resolution // -----> 2000 ticks will get us there (20,000 will get us ms) // // Goal: Use CTC interupt mode (CTC -> Clear on Timer Compare) // So a compare matches, it clears to zero and triggers interupt TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode OCR1A = 2000; // number to compare against TIMSK1 |= (1 << OCIE1A); // Enable CTC interrupt TCCR1B |= (1 << CS10); // Set up timer , with no prescaler (works at full MHz of clock) // Receiver setup - set up pin change interupt #if 1 EICRA &= ~ ( (1 << ISC01) | (1 << ISC01) ); // clear ISC01+ISC00 EICRA |= ( (1 << ISC00) ); // 00 set and 01 unset means any edge will make event PCMSK0 |= ( (1 << PCINT0) | (1 << PCINT1) ); // Pins to monitor: PA0 and PA1 PCICR |= (1 << PCIE0); // PA is monitored #endif // Serial - setup (for motor controller) mc_setup(); // TWI - set up unsigned char twibuf [ TWI_BUFFER_SIZE ]; unsigned char TWI_slaveAddress; TWI_slaveAddress = 0x10; // our TWI address TWI_Slave_Initialise( (unsigned char)((TWI_slaveAddress<<TWI_ADR_BITS) | (TRUE<<TWI_GEN_BIT) )); // Initialise TWI module as slave; include addr+general unsigned char twi_heartbeat_counter = 0; // setup done - kick up interupts sei(); // lets burn the first couple of seconds, so the receiver can get some signal // before we start blasting stuff into the motor controllers { unsigned int start_sec = g_time_s; while ( g_time_s - start_sec < 3 ) { nop(); } } // Start the TWI transceiver to enable reseption of the first command from the TWI Master. TWI_Start_Transceiver(); #if 1 // timer test .. show per-second counter update on lcd if ( 1 ) { unsigned int last_sec = g_time_s; unsigned int last_us = _g_time_us_tick; unsigned char sent_l = 0, sent_r = 0; char message [ 17 ]; while(1) { unsigned int ch1 = g_ch1_duration; unsigned int ch2 = g_ch2_duration; // 100ms has past? if ( _g_time_us_tick - last_us > 1000 ) { if ( g_control_twi ) { // we're on TWI control, but if nothing comes in.. revert back to RC if ( g_time_s - g_control_last_s > 2 ) { g_control_twi = 0; } } else { mc_set_by_receiver ( ch1, ch2, &sent_l, &sent_r, message ); } last_us = _g_time_us_tick; } // .1sec tick // one second has past? update lcd if ( g_time_s != last_sec ) { //sprintf ( textbuf, "recv %2d %2d ", g_ch1_duration, g_ch2_duration ); sprintf ( textbuf, "m %2d %2d th %2d %2d #", sent_l, sent_r, ch1, ch2 ); lcd_xy ( 0, 0 ); lcd_puts( textbuf ); // display number right adjusted //sprintf ( textbuf, "t%2d #", g_time_s ); sprintf ( textbuf, "t%2d # %s", g_time_s, message ); lcd_xy ( 0, 1 ); lcd_puts( textbuf ); // display number right adjusted last_sec = g_time_s; } // 1 sec tick // TWI/I2C stuff, talk to r-pi // // Check if the TWI Transceiver has completed an operation. if ( ! TWI_Transceiver_Busy() ) { // Check if the last operation was successful if ( TWI_statusReg.lastTransOK ) { // Check if the last operation was a reception if ( TWI_statusReg.RxDataInBuf ) { TWI_Get_Data_From_Transceiver ( twibuf, 3 ); // Check if the last operation was a reception as General Call if ( TWI_statusReg.genAddressCall ) { // don't care } else { // Ends up here if the last operation was a reception as Slave Address Match // Example of how to interpret a command and respond. #if 0 // TWI_CMD_MASTER_WRITE stores the data to PORTB if (twibuf[0] == TWI_CMD_MASTER_WRITE) { PORTB = twibuf[1]; } #endif // TWI_CMD_MASTER_READ prepares the data from PINB in the transceiver buffer for the TWI master to fetch. if ( twibuf[0] == tc_heartbeat ) { twibuf [ 0 ] = 1; twibuf [ 1 ] = twi_heartbeat_counter++; TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } else if ( twibuf[0] == tc_gethello ) { sprintf ( twibuf + 1, "hello" ); twibuf [ 0 ] = strlen ( twibuf + 1 ); // len TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } else if ( twibuf[0] == tc_setmotors ) { g_control_last_s = g_time_s; mc_speed ( mcm_left, twibuf [ 1 ] ); mc_speed ( mcm_right, twibuf [ 2 ] ); } else if ( twibuf[0] == tc_takeover ) { g_control_last_s = g_time_s; g_control_twi = 1; } else if ( twibuf[0] == tc_release ) { g_control_twi = 0; } else { twibuf [ 0 ] = 1; twibuf [ 1 ] = 0xde; twibuf [ 2 ] = 0xad; twibuf [ 3 ] = 0xbe; twibuf [ 4 ] = 0xef; TWI_Start_Transceiver_With_Data ( twibuf, TWI_BUFFER_SIZE ); } } } else { // Ends up here if the last operation was a transmission // don't care } // Check if the TWI Transceiver has already been started. // If not then restart it to prepare it for new receptions. if ( ! TWI_Transceiver_Busy() ) { TWI_Start_Transceiver(); } } else { // Ends up here if the last operation completed unsuccessfully TWI_Act_On_Failure_In_Last_Transmission ( TWI_Get_State_Info() ); } // success/fail } // TWI busy? // spin _delay_ms ( 20 ); } // while forever } // if 1 #endif /* churn forever */ while(1); return ( 0 ); }
void menu_update() { // czas pobrany z RTC time_t time; unsigned char n; // czyœæ ekran przed aktualizacj¹ menu if ( menu_updated ) { lcd_clear(); } // rysuj g³ówne menu lcd_xy(0,0); lcd_char(lcd_larrow); lcd_xy(15,0); lcd_char(lcd_rarrow); lcd_xy(2,0); // ogranicz if (menu_pos == 0xff) { menu_pos = MENU_POS_COUNT - 1; } else if(menu_pos >= MENU_POS_COUNT) { menu_pos = 0; } // wybierz g³ówne menu switch(menu_pos) { // czas i trzy temperatury // case 0: // pobierz czas ... ds1306_time_get(&time); // ... i poka¿ lcd_xy(1,0); lcd_int2(time.tm_hour); lcd_char(uptime%2 ? ':' : ' '); lcd_int2(time.tm_min); lcd_char(' ');//lcd_text_P(PSTR(" 20")); lcd_int2(time.tm_year);lcd_char('/');lcd_int2(time.tm_mon);lcd_char('/');lcd_int2(time.tm_mday); // ogranicz podmenu do liczby czujników if (menu_sub_pos == 0xff) { menu_sub_pos = 0; } else if ( (menu_sub_pos > ds_devices_count-3) && (ds_devices_count > 3) ) { menu_sub_pos = ds_devices_count-3; } // poka¿ temperatury lcd_xy(1,1); for (n=0; n<ds_devices_count && n<3; n++) { lcd_int2(abs(ds_temp[menu_sub_pos + n])/10); lcd_char('.'); lcd_char('0' + (abs(ds_temp[menu_sub_pos + n])%10)); lcd_char(' '); } // strza³ki lcd_xy(0,1); lcd_char( (menu_sub_pos > 0) ? lcd_larrow : ' '); lcd_xy(15,1); lcd_char( (menu_sub_pos < ds_devices_count-3) ? lcd_rarrow : ' '); break; // temperatury // case 1: // poka¿ temperatury lcd_xy(1,0); for (n=0; n<ds_devices_count && n<3; n++) { lcd_int2(abs(ds_temp[n])/10); lcd_char('.'); lcd_char('0' + (abs(ds_temp[n])%10)); lcd_char(n<2 ? ' ' : lcd_rarrow); } lcd_xy(1,1); for (n=3; n<ds_devices_count && n<6; n++) { lcd_int2(abs(ds_temp[n])/10); lcd_char('.'); lcd_char('0' + (abs(ds_temp[n])%10)); lcd_char(' '); } break; // sieæ (IP, brama, DHCP, pakiety) // case 2: lcd_text_P(PSTR("Sie\x09/")); // sieæ // ogranicz podmenu if (menu_sub_pos == 0xff) { menu_sub_pos = 6; } else if (menu_sub_pos > 6) { menu_sub_pos = 0; } lcd_xy(7,0); switch (menu_sub_pos) { case 0: lcd_text_P(PSTR("IP")); lcd_xy(2,1); for (n=0; n<4; n++) { lcd_int(my_net_config.my_ip[n]); lcd_char(n<3 ? '.' : ' '); } break; case 1: lcd_text_P(PSTR("brama")); lcd_xy(2,1); for (n=0; n<4; n++) { lcd_int(my_net_config.gate_ip[n]); lcd_char(n<3 ? '.' : ' '); } break; case 2: lcd_text_P(PSTR("DHCP")); lcd_xy(2,1); // DHCP if (my_net_config.using_dhcp) { lcd_text_P(PSTR("u\x0fywane")); } else { lcd_text_P(PSTR("nie")); } break; case 3: lcd_text_P(PSTR("\x0b\x08")); lcd_text_P(PSTR("cze")); lcd_xy(2,1); // stan ³¹cza if ( enc28_is_link_up() ) { lcd_text_P(PSTR("tak")); } else { lcd_text_P(PSTR("brak")); } break; case 4: lcd_text_P(PSTR("pakiety")); lcd_xy(2,1); lcd_text_P(PSTR("Tx: ")); lcd_int(net_ip_packet_id); break; case 5: lcd_text_P(PSTR("pakiety")); lcd_xy(2,1); lcd_text_P(PSTR("Rx: ")); lcd_int(my_net_config.pktcnt); break; case 6: lcd_text_P(PSTR("MAC")); lcd_xy(2,1); for (n=0; n<6; n++) { lcd_hex(my_net_config.my_mac[n]); } break; } // strza³ki lcd_xy(0,1); lcd_char(lcd_larrow); lcd_xy(15,1); lcd_char(lcd_rarrow); break; // PID (wysterowania, nastawy, PV, SP) // /* case 3: lcd_text_P(PSTR("PID")); // PID break; */ // PWM (wype³nienia) // case 3: lcd_text_P(PSTR("PWM")); // ogranicz podmenu do liczby kana³ów PWM if (menu_sub_pos == 0xff) { menu_sub_pos = 0; } else if (menu_sub_pos > PWM_CHANNELS-3) { menu_sub_pos = PWM_CHANNELS-3; } // nr pokazywanych kana³ów lcd_xy(11,0); lcd_char('1' + menu_sub_pos); lcd_char('-'); lcd_char('3' + menu_sub_pos); // poka¿ wype³nienia lcd_xy(2,1); for (n=0; n<PWM_CHANNELS && n<3; n++) { lcd_char('0' + pwm_get_fill(menu_sub_pos + n)/100);lcd_int2(pwm_get_fill(menu_sub_pos + n)); lcd_char(' '); } // strza³ki lcd_xy(0,1); lcd_char( (menu_sub_pos > 0) ? lcd_larrow : ' '); lcd_xy(15,1); lcd_char( (menu_sub_pos < PWM_CHANNELS-3) ? lcd_rarrow : ' '); break; // informacje (wersja, ENC28J60, karta pamiêci, EEPROM) // case 4: lcd_text_P(PSTR("Informacje")); // sieæ // ogranicz podmenu if (menu_sub_pos == 0xff) { menu_sub_pos = 6; } else if (menu_sub_pos > 6) { menu_sub_pos = 0; } lcd_xy(2,1); switch (menu_sub_pos) { case 0: lcd_text_P(PSTR(__DATE__)); break; case 1: lcd_text_P(PSTR("GCC " __AVR_LIBC_VERSION_STRING__)); break; case 2: //lcd_text_P(PSTR("Up ")); // dni lcd_int((uptime/3600/24)); lcd_char('d'); // godziny lcd_int2((uptime/3600)%24); lcd_char(':'); // minuty lcd_int2((uptime/60)%60); lcd_char(':'); // sekundy lcd_int2((uptime%60)); break; case 3: lcd_text_P(PSTR("ENC28 rev.B")); lcd_char('0' + enc28_read_rev_id()); break; case 4: lcd_text_P(PSTR("Czujnik\x0dw: ")); lcd_int(ds_devices_count); break; case 5: lcd_text_P(PSTR("EEPROM ")); lcd_int(eeprom_get_size() >> 10); lcd_char('k');lcd_char('B'); break; case 6: if (sd_get_state() != SD_FAILED) { lcd_text_P(sd_get_state() == SD_IS_SD ? PSTR("SD") : PSTR("MMC")); lcd_char(' '); lcd_int(sd_size >> 10); // kB lcd_char('k');lcd_char('b'); } else { lcd_text_P(PSTR("SD/MMC: b\x0b\x08d")); } break; }