Subversion Repositories HomeAutomation

Rev

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

  1. /**
  2.  * AntennaDisplay
  3.  * For controlling of the cAntenna bus using one
  4.  * HD44780 LCD display and buttons.
  5.  *
  6.  * @date    2007-12-10
  7.  * @author  Erik Larsson
  8.  *
  9.  */
  10.  
  11. /*-----------------------------------------------------------------------------
  12.  * Includes
  13.  *---------------------------------------------------------------------------*/
  14. /* system files */
  15. #include <avr/io.h>
  16. #include <inttypes.h>
  17. #include <avr/interrupt.h>
  18. #include <stdio.h>
  19. #include <stdlib.h>
  20.  
  21. /* lib files */
  22. #include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
  23. #include <config.h> // All configuration parameters
  24. #include <drivers/timer/timer.h>
  25. #include <drivers/lcd/clcd/lcd_HD44780.h>
  26.  
  27. #include <string.h> //for memcpy
  28.  
  29. /*-----------------------------------------------------------------------------
  30.  * Defines
  31.  *---------------------------------------------------------------------------*/
  32. #define APP_TYPE    0x1234
  33. #define APP_VERSION 0x0002
  34.  
  35. // LCD size
  36. #define SIZE_X  16
  37. #define SIZE_Y  2
  38.  
  39. #define BUFFER_SIZE SIZE_X
  40.  
  41. #define STOP 0
  42. #define AZIMUTH 1
  43. #define ELEVATION 2
  44. #define SCREEN_NORMAL 3
  45. #define SCREEN_CAL 4
  46.  
  47. // Display modes
  48. #define NORMAL_MODE 0x01
  49. #define CAL_MODE 0x02
  50.  
  51. // Actions
  52. #define AZIMUTH_PLUS 0x05
  53. #define AZIMUTH_MINUS 0x06
  54. #define ELEVATION_PLUS 0x07
  55. #define ELEVATION_MINUS 0x08
  56. #define AZIMUTH_STOP 0x09
  57. #define ELEVATION_STOP 0x0a
  58. #define GET_CAL 0x0b
  59. #define SET_CAL 0x0c
  60.  
  61. volatile Can_Message_t rxMsg;
  62.  
  63. uint8_t rxMsgFull=0;
  64.  
  65. // Buttons
  66. uint8_t azimuth_plus = 0, azimuth_minus = 0;
  67. uint8_t elevation_plus = 0, elevation_minus = 0;
  68. uint8_t calibration = 0;
  69.  
  70.  
  71. /*-----------------------------------------------------------------------------
  72.  * Declarations
  73.  *---------------------------------------------------------------------------*/
  74.  
  75. /**
  76.  * IO_init
  77.  * Enable button inputs
  78.  * Enable contrast and backlight for LCD
  79.  *
  80.  * @param void
  81.  * @return void
  82.  */
  83. void IO_init( void );
  84.  
  85. /**
  86.  * print_sceen
  87.  * Prints normal and calibration data to LCD
  88.  *
  89.  * @param screen type, normal or calibration
  90.  * @param data to print
  91.  * @return void
  92.  */
  93. void print_screen( uint8_t type, uint16_t data );
  94.  
  95. /**
  96.  * send_message
  97.  * Handles all messages to antenna nodes
  98.  *
  99.  * @param type of message
  100.  * @param data to send
  101.  * @return void
  102.  */
  103. void send_message( uint8_t type, uint16_t data );
  104.  
  105. /**
  106.  * calibrate
  107.  * Gets calibration data from node, adjusts it and returns
  108.  *
  109.  * @param void
  110.  * @return void
  111.  */
  112. void calibrate( void );
  113.  
  114. /**
  115.  * read_buttons
  116.  * Periodicly read buttons
  117.  *
  118.  * @param trigging timer
  119.  * @return void
  120.  */
  121. void read_buttons(uint8_t timer) {
  122.     // Read buttons
  123.     calibration = (PIND & (1<<PD2))?0:1;
  124.     azimuth_plus = (PINB & (1<<PB0))?0:1;
  125.     azimuth_minus = (PINB & (1<<PB7))?0:1;
  126.     elevation_plus = (PINC & (1<<PC1))?0:1;
  127.     elevation_minus = (PINC & (1<<PC0))?0:1;
  128. }
  129.  
  130. // CAN message reception callback
  131. // This function runs with interrupts disabled, keep it as short as possible
  132. void can_receive(Can_Message_t *msg){
  133.     if(!rxMsgFull){
  134.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  135.         rxMsgFull = 1;
  136.     }
  137. }
  138.  
  139. /*-----------------------------------------------------------------------------
  140.  * Main Program
  141.  *---------------------------------------------------------------------------*/
  142. int main( void ) {
  143.     // Flag for automatic sending stop message after released buttons
  144.     uint8_t autostop = 0;
  145.  
  146.     sei();
  147.    
  148.     // Enable timers
  149.     Timer_Init();
  150.  
  151.     // Enable buttons and display
  152.     IO_init();
  153.  
  154.     Can_Message_t txMsg;
  155.    
  156.     txMsg.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) | (NODE_ID << CAN_SHIFT_NMT_SID);
  157.     txMsg.ExtendedFlag=1;
  158.     txMsg.RemoteFlag=0;
  159.     txMsg.DataLength = 4;
  160.    
  161.     txMsg.Data.words[0] = APP_TYPE;
  162.     txMsg.Data.words[1] = APP_VERSION;
  163.    
  164.     // Send startup message
  165.     BIOS_CanSend(&txMsg);
  166.    
  167.     BIOS_CanCallback = &can_receive;
  168.    
  169.     // Timer for reading buttons and doing actions
  170.     Timer_SetTimeout(0, 50, TimerTypeFreeRunning, &read_buttons);
  171.     Timer_SetTimeout(1, 500, TimerTypeFreeRunning, 0);
  172.    
  173.     /* main loop */
  174.     while(1){
  175.        
  176.         /* check if any messages have been received */
  177.         if( rxMsgFull ){
  178.  
  179.             if( rxMsg.Id == 0x1f8f0100 ){
  180.                 // Received new azimuth data and print it
  181.                 print_screen( AZIMUTH, rxMsg.Data.words[0] );
  182.                
  183.             }else if( rxMsg.Id == 0x1f8f0200 ){
  184.                 // Received new elevation data and print it
  185.                 print_screen( ELEVATION, rxMsg.Data.words[0] );
  186.             }
  187.            
  188.             rxMsgFull = 0;
  189.         }
  190.        
  191.         // Periodicly take care of button actions
  192.         if (Timer_Expired(1)) {
  193.  
  194.             // Perhaps someone pressed a button
  195.             if( calibration || azimuth_plus || azimuth_minus || elevation_plus || elevation_minus ){
  196.                 if( calibration ){
  197.                     // Enters calibration mode
  198.                     // Send all stop
  199.                     send_message( AZIMUTH_STOP, 0);
  200.                     send_message( ELEVATION_STOP, 0);
  201.  
  202.                     // Start calibration
  203.                     calibrate();
  204.  
  205.                 }else{
  206.                     if( azimuth_plus ){
  207.                         // Send rotate aximuth plus
  208.                         send_message( AZIMUTH_PLUS, 0 );
  209.                        
  210.                     }else if( azimuth_minus ){
  211.                         // Send rotate azimuth minus
  212.                         send_message( AZIMUTH_MINUS, 0 );
  213.                        
  214.                     }else{
  215.                         // Send azimuth stop
  216.                         send_message( AZIMUTH_STOP, 0 );
  217.                     }
  218.    
  219.                     if( elevation_plus ){
  220.                         // Send elevate plus
  221.                         send_message( ELEVATION_PLUS, 0 );
  222.                        
  223.                     }else if( elevation_minus ){
  224.                         // Send elevate minus
  225.                         send_message( ELEVATION_MINUS, 0 );
  226.                        
  227.                     }else{
  228.                         // Send elevation stop
  229.                         send_message( ELEVATION_STOP, 0 );
  230.                     }
  231.  
  232.                     autostop = 1; // Stop all rotors when no button is pressed
  233.                 }
  234.  
  235.             }else if ( autostop ){
  236.                 // Send all stop
  237.                 // Only doing it once, no need to spam
  238.                 send_message( AZIMUTH_STOP, 0);
  239.                 send_message( ELEVATION_STOP, 0);
  240.  
  241.                 autostop = 0;
  242.             }
  243.         }
  244.     }
  245. }
  246.  
  247. /*-----------------------------------------------------------------------------
  248.  * Definitions
  249.  *---------------------------------------------------------------------------*/
  250.  
  251. void send_message( uint8_t type, uint16_t data ){
  252.     Can_Message_t txMsg;
  253.  
  254.     txMsg.ExtendedFlag=1;
  255.     txMsg.RemoteFlag=0;
  256.  
  257.     switch(type){
  258.    
  259.     case AZIMUTH_PLUS:
  260.         // Increase azimuth
  261.         txMsg.Id = 0x11100005UL;
  262.         txMsg.Data.bytes[0] = 0x01;
  263.         txMsg.DataLength = 1;
  264.         break;
  265.    
  266.     case AZIMUTH_MINUS:
  267.         // Decrease azimuth
  268.         txMsg.Id = 0x11100005UL;
  269.         txMsg.Data.bytes[0] = 0x02;
  270.         txMsg.DataLength = 1;
  271.         break;
  272.    
  273.     case AZIMUTH_STOP:
  274.         // Stop azimuth rotating
  275.         txMsg.Id = 0x11100005UL;
  276.         txMsg.Data.bytes[0] = 0x00;
  277.         txMsg.DataLength = 1;
  278.         break;
  279.    
  280.     case ELEVATION_PLUS:
  281.         // Increase elevation angle
  282.         txMsg.Id = 0x11100015UL;
  283.         txMsg.Data.bytes[0] = 0x01;
  284.         txMsg.DataLength = 1;
  285.         break;
  286.    
  287.     case ELEVATION_MINUS:
  288.         // Decrease elevation angle
  289.         txMsg.Id = 0x111000015UL;
  290.         txMsg.Data.bytes[0] = 0x02;
  291.         txMsg.DataLength = 1;
  292.         break;
  293.    
  294.     case ELEVATION_STOP:
  295.         // Stop elevation rotating
  296.         txMsg.Id = 0x11100015UL;
  297.         txMsg.Data.bytes[0] = 0x00;
  298.         txMsg.DataLength = 1;
  299.         break;
  300.        
  301.     case GET_CAL:
  302.         // Get calibration data from nodes
  303.         //FIXME add elevation
  304.         txMsg.Id = 0x11100002UL;
  305.         txMsg.DataLength = 0;
  306.         break;
  307.        
  308.     case SET_CAL:
  309.         // Set calibration data in nodes
  310.         //FIXME add elevation
  311.         txMsg.Id = 0x11100001UL;
  312.         txMsg.DataLength = 2;
  313.         txMsg.Data.words[0] = data;
  314.         break;
  315.        
  316.     default:
  317.         // Stop all rotating
  318.         txMsg.Id = 0x11100005UL;
  319.         txMsg.Data.bytes[0] = 0x00;
  320.         txMsg.DataLength = 1;
  321.         break;
  322.     }
  323.  
  324.     BIOS_CanSend(&txMsg);
  325. }
  326.  
  327. /**
  328.  * print_screen, 2x16 characters
  329.  *
  330.  * Normal screen (for rotating):
  331.  * ##################
  332.  * #Azimuth     183*#
  333.  * #Elevation    45*#
  334.  * ##################  
  335.  *
  336.  * Calibration screen:
  337.  * ##################
  338.  * #Cal Azimuth  20*#
  339.  * #Cal Elevat.  12*#
  340.  * ##################
  341.  */
  342.  
  343. void print_screen(uint8_t type, uint16_t data){
  344.     char buffer[ BUFFER_SIZE ];
  345.  
  346.     if( SCREEN_NORMAL == type){
  347.         // Normal screen for rotating
  348.         lcd_clrscr();
  349.         lcd_puts("Azimuth     ???*\n");
  350.         lcd_puts("Elevation   ???*\n");
  351.  
  352.     }else if( SCREEN_CAL == type){
  353.         // Screen for calibration
  354.         lcd_clrscr();
  355.         lcd_puts("Cal Azimuth ???*\n");
  356.         lcd_puts("Cal Elevat. ???*\n");
  357.  
  358.     }else if( AZIMUTH == type ){
  359.         // Prints azimuth position or calibration data
  360.         lcd_gotoxy(12,0);
  361.         lcd_puts("   *");
  362.         lcd_gotoxy(12,0);
  363.  
  364.         snprintf(buffer, BUFFER_SIZE, "%i", data);
  365.         lcd_puts(buffer);
  366.  
  367.     }else if( ELEVATION == type ){
  368.         // Prints elevation position or calibration data
  369.         lcd_gotoxy(12,1);
  370.         lcd_puts("   *");
  371.         lcd_gotoxy(12,1);
  372.  
  373.         snprintf(buffer, BUFFER_SIZE, "%i", data);
  374.         lcd_puts(buffer);
  375.     }
  376. }
  377.  
  378. /**
  379.  * Enable buttons and display light
  380.  *
  381.  * PB0: Azimuth plus
  382.  * PB7: Azimuth minus
  383.  * PC0: Elevation plus
  384.  * PC1: Elevation minus
  385.  * PD2: Calibration
  386.  */
  387. void IO_init( void )
  388. {
  389.     // Set as inputs
  390.     DDRD |= ( 1<<DDD2 ); // Calibration
  391.     DDRB |= ( 1<<DDB0 )|( 1<<DDB7 ); // Azimuth
  392.     DDRC |= ( 1<<DDC0 )|( 1<<DDC1 ); // Elevation
  393.  
  394.     // Enable pull up
  395.     PORTD |= ( 1<<PD2 );
  396.     PORTB |= ( 1<<PB0 )|( 1<<PB7 );
  397.     PORTC |= ( 1<<PC0 )|( 1<<PC1 );
  398.  
  399.     // Contrast
  400.     TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
  401.     TCCR0B |= (1<<CS00);
  402.     OCR0B = 0x02;
  403.     DDRD |= (1<<DDD5);
  404.  
  405.     // Backlight
  406.     TCCR1A |= (1<<COM1A1)|(1<<WGM11);
  407.     TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
  408.     ICR1 = 0xFF; // Make it 8 bits
  409.     OCR1A = 0xC0;
  410.     DDRB |= (1<<DDB1);
  411.    
  412.     // Startup LCD
  413.     lcd_init( LCD_DISP_ON );
  414.  
  415.     // Prints first characters to display
  416.     print_screen( SCREEN_NORMAL, 0 );
  417. }
  418.  
  419.  
  420. void calibrate( void ){
  421.     int16_t calib_value_az = 0, calib_value_elv = 0;
  422.    
  423.     // Flags
  424.     uint8_t received_cal = 0, calibration_mode = 0;
  425.    
  426.     // Show calibration display
  427.     print_screen( SCREEN_CAL, 0 );
  428.    
  429.     // Aquire old calibration data from node
  430.     send_message( GET_CAL, 0 );
  431.    
  432.     while ( 1 ) {
  433.    
  434.         /* check if any messages have been received */
  435.         if( rxMsgFull ){
  436.             if( 0x111000f2 == rxMsg.Id && 2 == rxMsg.DataLength ){ // MSG_CAL_RET
  437.                 calib_value_az = rxMsg.Data.words[0];
  438.                
  439.                 received_cal = 1;
  440.                
  441.                 // Print old calibration data
  442.                 print_screen( AZIMUTH, calib_value_az );
  443.             } //FIXME elevation
  444.                
  445.             rxMsgFull = 0;
  446.         }
  447.    
  448.         /* When we got the old calibration data and we want to adjust it */
  449.         if ( Timer_Expired(1) && received_cal ) {
  450.             if ( !calibration ){// wait for released calibration button
  451.                 calibration_mode = 1;
  452.                
  453.                 if(azimuth_plus){
  454.                     // Increase value
  455.                     calib_value_az++;
  456.                     print_screen( AZIMUTH, calib_value_az );               
  457.  
  458.                 }else if(azimuth_minus){
  459.                     // Decrease value
  460.                     calib_value_az--;
  461.                     print_screen( AZIMUTH, calib_value_az );
  462.                 }
  463.  
  464.                 // FIXME elevation 
  465.                 if(elevation_plus){
  466.                     // Increase value
  467.                     calib_value_elv++;
  468.                
  469.                 }else if(elevation_minus){
  470.                     // Decrease value
  471.                     calib_value_elv--;
  472.                 }  
  473.  
  474.             }else if( calibration && calibration_mode ){
  475.                 // Send new calibration value to antenna node
  476.                 send_message( SET_CAL, calib_value_az );
  477.                 //FIXME elevation
  478.  
  479.                 // Return to normal screen
  480.                 print_screen( SCREEN_NORMAL, 0 );
  481.                
  482.                 return;
  483.             }
  484.         }
  485.     }
  486. }
  487.