Subversion Repositories HomeAutomation

Rev

Rev 636 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

  1. /**
  2.  * CanEggWatch. Currenty only supports nodeCLCD, this will probably change since I want 7-segments in the long run.
  3.  * Hardware: http://projekt.auml.se/homeautomation:hardware:avr:clcd
  4.  * TODO: Sending messages to report status, cleanup, graphical bar, nicer GUI, multiple timers
  5.  *
  6.  *
  7.  * @date    2007-09-09
  8.  * @author  Martin Norden
  9.  *
  10.  */
  11.  
  12. /*-----------------------------------------------------------------------------
  13.  * Includes
  14.  *---------------------------------------------------------------------------*/
  15. /* system files */
  16. #include <avr/io.h>
  17. #include <inttypes.h>
  18. #include <avr/interrupt.h>
  19. #include <stdio.h>
  20. /* lib files */
  21. #include <bios.h>
  22. #include <config.h>
  23. #include <drivers/lcd/clcd/lcd_HD44780.h>
  24. #include <drivers/timer/timebase.h>
  25.  
  26.  
  27. #include <string.h> //for memcpy
  28. #include <stdlib.h> //for itoa
  29.  
  30.  
  31. /*-----------------------------------------------------------------------------
  32.  * Defines
  33.  *---------------------------------------------------------------------------*/
  34. #define SIZE_X  20
  35. #define SIZE_Y  4
  36. #define SIZE_LCD LCD_SIZE_20x4
  37.  
  38. #define BUFFER_SIZE SIZE_X
  39. #define TRUE 1
  40. #define FALSE 0
  41.  
  42. #define LEFT    0x01
  43. #define RIGHT   0x02
  44. #define BUTTON_PUSH 0x03
  45. #define BUTTON_RELEASE 0x04
  46.  
  47. volatile Can_Message_t rxMsg;
  48.  
  49. char incoming_text[ BUFFER_SIZE ];
  50. uint8_t rxMsgFull;
  51.  
  52.  
  53. char buffer[ BUFFER_SIZE ];
  54.  
  55. void send_dimensions(void);
  56. void rotenc(void);
  57. void action(uint8_t type);
  58. void alarm(void);
  59.  
  60. uint32_t timeBase = 0;
  61. uint16_t timerVar= 0;
  62. uint8_t alarmTimer = 0;
  63.  
  64. char lcdBuffer[5];
  65.  
  66. // CAN message reception callback
  67. // This function runs with interrupts disabled, keep it as short as possible
  68. void can_receive(Can_Message_t *msg){
  69.     if(!rxMsgFull){
  70.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  71.         rxMsgFull = 1;
  72.     }
  73. }
  74.  
  75. ISR( PCINT2_vect ){
  76. // For ROTENC_A and ROTENC_B FIXME Šr inte riktigt rŠtt. Verkar vara bra tycker jag?
  77.     rotenc();
  78. }
  79.  
  80. ISR( PCINT0_vect ){
  81. // For ROTENC_BTN
  82.     rotenc();
  83. }
  84.  
  85. /*-----------------------------------------------------------------------------
  86.  * Main Program
  87.  *---------------------------------------------------------------------------*/
  88. int main(void) {
  89. //  uint32_t act; not used anymoer
  90. //  uint8_t act_type, lcd_size; not used anymore
  91. //  uint8_t m, lcd_action; These are probably not needed now
  92.  
  93.     sei();
  94.    
  95.     Timebase_Init();
  96.  
  97.     /*
  98.      * Initialize rotaryencoders and buttons
  99.      */
  100.     // Set as input
  101.     DDRD &= ~(1<<DDD2);
  102.     DDRB &= ~((1<<DDB7)|(1<<DDB0));
  103.     // Enable pull-up
  104.     PORTD |= (1<<PD2);
  105.     PORTB |= (1<<PB7)|(1<<PB0);
  106.     // Enable IO-pin interrupt
  107.     PCICR |= (1<<PCIE2)|(1<<PCIE0);
  108.     // Unmask PB7, PB0 and PD2
  109.     PCMSK2 |= (1<<PCINT18);
  110.     PCMSK0 |= (1<<PCINT7)|(1<<PCINT0);
  111.  
  112.     // Contrast
  113.     TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
  114.     TCCR0B |= (1<<CS00);
  115.     OCR0B = 0x10;
  116.     DDRD |= (1<<DDD5);
  117.  
  118.     // Backlight
  119.     TCCR1A |= (1<<COM1A1)|(1<<WGM11);
  120.     TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
  121.     ICR1 = 0xFF; // Make it 8 bits
  122.     OCR1A = 0xFF;
  123.     DDRB |= (1<<DDB1);
  124.  
  125.  
  126.     Can_Message_t txMsg;
  127.     txMsg.ExtendedFlag=1;
  128.     txMsg.RemoteFlag=0;
  129. // FIXME skicka app startad
  130.     BIOS_CanCallback = &can_receive;
  131.  
  132.     lcd_init( LCD_DISP_ON );
  133.     lcd_clrscr();
  134.     lcd_puts("EggWatch\n");
  135.  
  136.     send_dimensions();
  137.     lcd_puts("CAN Connected!\n");
  138.  
  139.     /* main loop */
  140.     while(1){
  141.        
  142.        
  143.         if( Timebase_PassedTimeMillis(timeBase) >= 1000 ){
  144.             if (timerVar != 0){
  145.                 timerVar--;
  146.                 lcd_clrscr();
  147.                 itoa(timerVar/60,lcdBuffer,10);
  148.                 lcd_puts(lcdBuffer);
  149.                 lcd_puts(":");
  150.                 itoa(timerVar%60,lcdBuffer,10);
  151.                 lcd_puts(lcdBuffer);
  152.             } else {
  153.                 if (alarmTimer != 0){
  154.                     alarm();
  155.                     alarmTimer--;
  156.                 }
  157.             }
  158.             timeBase =  Timebase_CurrentTime();
  159.         }
  160.        
  161.        
  162.         /* check if any messages have been received */
  163.         if(rxMsgFull){
  164.             //Throw it away. We don't use them yet. TODO: Support for time and remote setting.
  165.             rxMsgFull = 0;
  166.         }
  167.     }
  168. }
  169.  
  170. void send_dimensions(){
  171.     Can_Message_t txMsg;
  172.  
  173.     txMsg.ExtendedFlag=1;
  174.     txMsg.RemoteFlag=0;
  175.     txMsg.Id=0xA000001;
  176.     txMsg.Data.bytes[0] = SIZE_X;
  177.     txMsg.Data.bytes[1] = SIZE_Y;
  178.     txMsg.DataLength = 2;
  179.  
  180.     BIOS_CanSend(&txMsg);
  181. }
  182.  
  183. void rotenc(){
  184.     uint8_t rot_data = 0;
  185.     static uint8_t rot_lastdir = 0, rot_laststate = 0, btn_laststate = 0;
  186.  
  187.     Can_Message_t txMsg;
  188.     txMsg.ExtendedFlag=1;
  189.     txMsg.RemoteFlag=0;
  190.     //txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x01<<SNS_ID_BITS )| NODE_ID;//FIXME: borttaget
  191.     txMsg.DataLength=2;
  192.  
  193.     //Take care of button push
  194.     if ((PINB&(1<<PB7)) != btn_laststate){ //The buttonstate has changed! Let's send a message!
  195.         btn_laststate = (PINB&(1<<PB7));
  196.         txMsg.Data.bytes[0] = 5;
  197.         txMsg.Data.bytes[1] = (btn_laststate)?0:1;
  198.         txMsg.DataLength=2;
  199.         BIOS_CanSend(&txMsg);
  200.         action((btn_laststate)?BUTTON_RELEASE:BUTTON_PUSH);
  201.     }
  202.    
  203.     //Take care of rotary encoder movement
  204.     if(PINB&(1<<PB0)){
  205.         rot_data |= 0x01;
  206.     }
  207.     if(PIND&(1<<PD2)){
  208.         rot_data |= 0x02;
  209.     }
  210.  
  211.     if( rot_data==0 || rot_data==3 ){ // Are both signals high or low?
  212.         if( rot_data==0 && rot_laststate!=rot_data ){ // Are both signals low? In that case we are finished with one turn and should print out the direction it went.
  213.             if( rot_lastdir&0x01 ){
  214.                 // Moving right
  215.                 txMsg.Data.bytes[0]=RIGHT;
  216.                 txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
  217.                 txMsg.DataLength=2;
  218.                 BIOS_CanSend(&txMsg);
  219.                 action(RIGHT);
  220.             }else{
  221.                 // Moving left
  222.                 txMsg.Data.bytes[0]=LEFT;
  223.                 txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
  224.                 txMsg.DataLength=2;
  225.                 BIOS_CanSend(&txMsg);
  226.                 action(LEFT);
  227.             }
  228.         }
  229.         rot_laststate = rot_data;
  230.     } else { // No, only one of the signals are high. We can use this to find out what direction we are moving.
  231.         rot_lastdir = rot_data;
  232.     }
  233. }
  234.  
  235. void action(uint8_t type){
  236.     //Let's do something with something!
  237.     lcd_clrscr();
  238.     if (type == LEFT){
  239.         timerVar--;
  240.         lcd_clrscr();
  241.         itoa(timerVar/60,lcdBuffer,10);
  242.         lcd_puts(lcdBuffer);
  243.         lcd_puts(":");
  244.         itoa(timerVar%60,lcdBuffer,10);
  245.         lcd_puts(lcdBuffer);
  246.     }
  247.     if (type == RIGHT){
  248.         timerVar++;
  249.         lcd_clrscr();
  250.         itoa(timerVar/60,lcdBuffer,10);
  251.         lcd_puts(lcdBuffer);
  252.         lcd_puts(":");
  253.         itoa(timerVar%60,lcdBuffer,10);
  254.         lcd_puts(lcdBuffer);
  255.     }
  256.     if (type == BUTTON_PUSH){
  257.         lcd_puts("Init!");
  258.     }
  259.     if (type == BUTTON_RELEASE){
  260.         timeBase = Timebase_CurrentTime();
  261.         timerVar = 10;
  262.         alarmTimer = 1;
  263.     }
  264. }
  265.  
  266. void alarm(void){
  267.     lcd_puts("Riing!");
  268. }
  269.