/* lcd.c */ /* lcd - affiche des messages sur l'écran lcd. {{{ * * Copyright (C) 2006 Christophe Le Blanc * * Robot APB Team/Efrei 2006. * Web: http://assos.efrei.fr/robot/ * Email: robot AT efrei DOT fr * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * }}} */ #include "common.h" #include "modules/twi/twi.h" #include "modules/utils/utils.h" #include "modules/uart/uart.h" #include "modules/proto/proto.h" #include "io.h" #include void lcd_send_command (u8 cmd); char key_read (void); /* Envois une commande transit **/ void lcd_transit_command (u8 cmd) { lcd_send_command(cmd>>4); lcd_send_command(cmd); } /** Envois une commande. */ void lcd_send_command (u8 cmd) { PORTC = (PORTC & 0xf0) | (cmd & 0x0f); // Pas de RS car on n'écrit pas sur le lcd, c'est une commande ! PORTD = PORTD | 0x80; // puis E à 1 PORTD = PORTD & 0x7f; // utils_delay_us (40); } /* Envois un caractère. */ void lcd_send_character (u8 c) { PORTC = (PORTC & 0xf0) | (c>>4); // c'est ça ! PORTD = (PORTD | 0x40); // 1 à RS PORTD = PORTD | 0x80; // puis 1 à E PORTD = PORTD & 0x7f; // puis on remet 0 à E utils_delay_us (40); PORTC = (PORTC & 0xf0) | (c & 0xf); // c'est ça ! PORTD = PORTD | 0x80; // puis 1 à E PORTD = PORTD & 0x7f; // puis on remet 0 à E PORTD = (PORTD & 0xBF); // 0 à RS utils_delay_us (40); } /* Envois une chaîne de caractère. */ void lcd_send_string_n (const char *s, u8 i) { u8 cpt ; lcd_transit_command(0x01); // suffit d'envoyer les bits de gauche à droite : D7D6D5D4 en hexa utils_delay_ms(2); lcd_transit_command(0x02); utils_delay_ms(2); for (cpt = 0 ; cpt < i ; cpt++) { if (cpt == 16) { lcd_transit_command(0xc0); utils_delay_us(40); } lcd_send_character(s[cpt]); } } //lcd_send_line(const char *s,u8 i,u8 l) //{ // u8 cpt ; // lcd_transit_command(0x01); // suffit d'envoyer les bits de gauche à droite : D7D6D5D4 en hexa // utils_delay_ms(2); // if ( l == 0 ) // lcd_transit_command(0x02); // else // lcd_transit_command(0xc0); // utils_delay_ms(2); // for (cpt = 0 ; cpt < 16 && cpt < i ; cpt++) // { // lcd_send_character(s[cpt]); // } // //} /* Envois une chaîne de caractère. */ void lcd_send_string (const char *s) { lcd_send_string_n (s, strlen (s)); } /* Initialisation du lcd. */ void lcd_init (void) { DDRC = 0x0f; DDRD = 0xC0; // PD0 RX ( uart ) // PD1 TX ( uart ) // PD2 - PD5 clavier // PD6 RS ( lcd ) // PD7 E ( lcd ) PORTD = 0x3C; // pull up DDRB = 0x01; utils_delay_ms (15); // suffit d'envoyer les bits de gauche à droite : D7D6D5D4 en hexa lcd_transit_command (0x01); // efface ecran lcd_transit_command (0x01); lcd_transit_command (0x13); // force 8 bits utils_delay_ms (4.5); lcd_transit_command (0x33); utils_delay_ms (1); lcd_transit_command (0x22); // passage mode 4 bits // def afficheur lcd_transit_command (0x80); utils_delay_ms (2); // affichage fonction lcd_transit_command (0xc0); // déplacement curseur lcd_transit_command (0x60); // efface ecran lcd_transit_command (0x10); } void lcd_clear(void) { lcd_send_command (0x0); lcd_send_command (0x1); utils_delay_ms (20); } char key_get (char old_key) { char new_key = key_read (); if (old_key == 0) { old_key = new_key; if (old_key != 0) proto_send1b ('R', new_key); } else if (new_key == 0) { char i = 0; while ( key_read () == 0 && i < 3 ) { utils_delay_ms(100); if ( i == 2 ) old_key = 0; i++; } } else if ( old_key != new_key ) { proto_send1b ('R', new_key); old_key = new_key; } return old_key; } char key_read (void) { char key = 0; PORTC = (PORTC & 0xf0) | 0x0f; uint8_t i = 0; while ( key == 0 && i < 4 ) { switch (i) { case 0 : PORTC = (PORTC & 0xf0) | 0x0E; break; case 1 : PORTC = (PORTC & 0xf0) | 0x0D; break; case 2 : PORTC = (PORTC & 0xf0) | 0x0B; break; case 3 : PORTC = (PORTC & 0xf0) | 0x07; break; } uint8_t key_tmp = PIND; if ( ~(key_tmp & 0x3c) & 0x04 ) switch (i) { case 0 : key = '1'; break; case 1 : key = '2'; break; case 2 : key = '3'; break; case 3 : key = 'F'; break; } else if ( ~(key_tmp & 0x3c) & 0x08) switch (i) { case 0 : key = '4'; break; case 1 : key = '5'; break; case 2 : key = '6'; break; case 3 : key = 'E'; break; } else if ( ~(key_tmp & 0x3c) & 0x10) switch (i) { case 0 : key = '7'; break; case 1 : key = '8'; break; case 2 : key = '9'; break; case 3 : key = 'D'; break; } else if ( ~(key_tmp & 0x3c) & 0x20) switch (i) { case 0 : key = 'A'; break; case 1 : key = '0'; break; case 2 : key = 'B'; break; case 3 : key = 'C'; break; } i++; } PORTC = (PORTC & 0xf0); return key; } void proto_callback (uint8_t cmd, uint8_t size, uint8_t *args) { switch (cmd) { // reset case 'z': if (size != 0) { proto_send0 ('?'); return; } else { utils_reset (); } break; // affiche un message 32 caractère case 'p': lcd_send_string_n (args, size); break; // Efface l'écran case 'C': if (size != 0) { proto_send0 ('?'); return; } else { lcd_clear (); } break; // Lit une touche au clavier (bloquant) // revoit un caractère {1234567890ABCDEF} case 'R': proto_send1b ('R',key_read ()); break; default: /* This is to handle default commands, return an error. */ proto_send0 ('?'); return; } /* When no error acknoledge. */ proto_send (cmd, size, args); } /* Fonction principale */ int main (void) { char old_key = 0; uint8_t data_rcpt[TWI_SL_RCPT_SIZE]; sei (); uart0_init (); lcd_init (); twi_init(0x02); proto_send0 ('z'); lcd_send_string (" LCD initialise "); while (1) { if (uart0_poll ()) proto_accept (uart0_getc ()); utils_delay_ms(3); old_key = key_get (old_key); if (twi_sl_poll (data_rcpt, TWI_SL_RCPT_SIZE)) { lcd_send_string_n(data_rcpt,32); } twi_sl_update (&old_key, TWI_SL_SEND_SIZE); } return 0; }