Subversion Repositories HomeAutomation

Rev

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

  1.  
  2. #include "chn_lcd_control.h"
  3.  
  4.  
  5. #include "../chn_ChnMaster/chn_ChnMaster.h"
  6.  
  7. #define CHANNEL_FLAG_WRITABLE  0x01
  8. #define CHANNEL_FLAG_ENABLED   0x02
  9. #define CHANNEL_FLAG_UNKNOWN   0x04
  10. #define CHANNEL_FLAG_REDRAW    0x80
  11.  
  12. struct chn_lcd_control_channel_t {
  13.     uint16_t id;
  14.     char     name[6];
  15.     char     type[3];
  16.     uint16_t value;
  17.     uint16_t low;
  18.     uint16_t range;
  19.     uint16_t low_disp;
  20.     uint16_t range_disp;
  21.     int8_t   dot;
  22.     uint8_t  flags;
  23. };
  24.  
  25.  
  26. void rotary_pcint_callback(uint8_t id, uint8_t status);
  27. void chn_lcd_control_drawChannel( uint8_t channel );
  28. void chn_lcd_control_chn_update( uint16_t channel_id, uint16_t value );
  29. void chn_lcd_control_timeout( uint8_t timer );
  30.  
  31. extern uint8_t lcd_framebuffer[256]; /* FIXME: a lib or something here... */
  32.  
  33.  
  34.  
  35. uint8_t controller_editmode = 1;
  36. volatile int8_t rotaryEncoder_Position = 0;
  37. uint8_t rotaryEncoder_Button_Position = 0;
  38. uint8_t rotaryEncoder_Button_Position_old = 0;
  39.  
  40. uint8_t channels_count         = 8;
  41. uint8_t channel_sel            = 0;
  42. uint8_t channel_border_visible = 0;
  43.  
  44. struct chn_lcd_control_channel_t channels[8] = {
  45.     {0, "Ceil", "%",  0,     0, 65535, 0, 100, -1, CHANNEL_FLAG_UNKNOWN | CHANNEL_FLAG_WRITABLE | CHANNEL_FLAG_ENABLED },
  46.     {1, "Win",  "%",  0,     0, 65535, 0, 100, -1, CHANNEL_FLAG_UNKNOWN | CHANNEL_FLAG_WRITABLE | CHANNEL_FLAG_ENABLED },
  47.     {3, "Test", "%",  0,     0, 65535, 0, 100, -1, CHANNEL_FLAG_UNKNOWN | CHANNEL_FLAG_WRITABLE | CHANNEL_FLAG_ENABLED },
  48.     {4, "",     "",   0,     0, 65535, 0, 100, -1, 0},
  49.     {5, "",     "",   0,     0, 65535, 0, 100, -1, 0},
  50.     {6, "",     "",   0,     0, 65535, 0, 100, -1, 0},
  51.     {7, "",     "",   0,     0, 65535, 0, 100, -1, 0},
  52.     {2, "Out",  "C ", 0, 25600,  7680, 0, 300,  3, CHANNEL_FLAG_UNKNOWN |                         CHANNEL_FLAG_ENABLED }
  53. };
  54.  
  55. void chn_lcd_control_timeout( uint8_t timer ) {
  56.     controller_editmode    = 0;
  57.     channel_border_visible = 0;
  58.     channels[ channel_sel ].flags |= CHANNEL_FLAG_REDRAW;
  59. }
  60.  
  61. void chn_lcd_control_enable( void ) {
  62.     channel_border_visible = 1;
  63.     channels[ channel_sel ].flags |= CHANNEL_FLAG_REDRAW;
  64.     Timer_SetTimeout(chn_contr_rot_TIMER, 3000, TimerTypeOneShot, &chn_lcd_control_timeout);
  65. }
  66.  
  67.  
  68. void rotary_pcint_callback(uint8_t id, uint8_t status) {
  69.     uint8_t rot_data = 0;
  70.     static uint8_t rot_lastdir = 0, rot_laststate = 0;
  71.  
  72.     //Take care of rotary encoder movement
  73.     if(gpio_get_state(ROTARY_CH1)){
  74.         rot_data |= 0x01;
  75.     }
  76.     if(gpio_get_state(ROTARY_CH2)){
  77.         rot_data |= 0x02;
  78.     }
  79.  
  80.     if( rot_data==0 || rot_data==3 ){ // Are both signals high or low?
  81.         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.
  82.             if( rot_lastdir&0x01 ){
  83.             #if ROTARY_CHx_INVERT_DIRECTION==1
  84.                 rotaryEncoder_Position--;    // Moving clockwise
  85.             #else
  86.                 rotaryEncoder_Position++;    // Moving counter clockwise
  87.             #endif
  88.             }else{
  89.             #if ROTARY_CHx_INVERT_DIRECTION==1
  90.                 rotaryEncoder_Position++;    // Moving counter clockwise
  91.             #else
  92.                 rotaryEncoder_Position--;    // Moving clockwise
  93.             #endif
  94.             }
  95.         }
  96.         rot_laststate = rot_data;
  97.     } else { // No, only one of the signals are high. We can use this to find out what direction we are moving.
  98.         rot_lastdir = rot_data;
  99.     }
  100. }
  101.  
  102.  
  103. void chn_lcd_control_chn_update( uint16_t channel_id, uint16_t value ) {
  104.     uint8_t i;
  105.     for( i = 0; i < channels_count; i++ ) {
  106.         if( channels[i].id == channel_id ) {
  107.             channels[i].value = value;
  108.             channels[i].flags &= ~CHANNEL_FLAG_UNKNOWN;
  109.             channels[i].flags |= CHANNEL_FLAG_REDRAW;
  110.         }
  111.     }
  112. }
  113.  
  114. void chn_lcd_control_drawChannel( uint8_t channel ) {
  115.     uint8_t *fb = lcd_framebuffer + channel*4;
  116.     uint8_t i;
  117.     int32_t value;
  118.     int8_t normvalue = 23;
  119.     int8_t tilevalue;
  120.     struct chn_lcd_control_channel_t *chn = &channels[ channel ];
  121.  
  122.     if( !( chn->flags & CHANNEL_FLAG_ENABLED ) )
  123.         return;
  124.  
  125.     /* Draw frame */
  126.     if( channel_border_visible && channel == channel_sel ) {
  127.         fb[0] = 157; fb[1] = 158; fb[2] = 158; fb[3] = 159;
  128.         if( controller_editmode ) {
  129.             for( i=1; i<8; i++ ) {
  130.                 fb[i*32] = 189; fb[i*32+3] = 191;
  131.             }
  132.         } else {
  133.             for( i=1; i<8; i++ ) {
  134.                 fb[i*32] = 0; fb[i*32+3] = 0;
  135.             }
  136.         }
  137.         fb[224] = 221; fb[225] = 222; fb[226] = 222; fb[227] = 223;
  138.     } else {
  139.         fb[0] = 0; fb[1] = 0; fb[2] = 0; fb[3] = 0;
  140.         for( i=1; i<8; i++ ) {
  141.             fb[i*32] = 0; fb[i*32+3] = 0;
  142.         }
  143.         fb[224] = 0; fb[225] = 0; fb[226] = 0; fb[227] = 0;
  144.     }
  145.  
  146.     /* Draw name */
  147.     for( i=0; chn->name[i]; i++ ) {
  148.         fb[(i+1)*32] = chn->name[i];
  149.     }
  150.  
  151.     if( !( chn->flags & CHANNEL_FLAG_UNKNOWN ) ) {
  152.         /* Draw value */
  153.         value  = chn->value;
  154.         value -= chn->low;
  155.         value *= chn->range_disp;
  156.         value /= chn->range;
  157.         value += chn->low_disp;
  158.  
  159.         i = 0;
  160.         while( chn->type[i] ) {
  161.             fb[ 195 - 32*i ] = chn->type[i];
  162.             i++;
  163.         }
  164.         do {
  165.             if( chn->dot == i ) {
  166.                 fb[ 195 - 32*i ] = '.';
  167.             } else {
  168.                 fb[ 195 - 32*i ] = '0' + (value%10);
  169.                 value /= 10;
  170.             }
  171.             i++;
  172.         } while( value > 0 );
  173.         if( i<=6 ) {
  174.             fb[ 195 - 32*i ]  = 0;
  175.         }
  176.  
  177.  
  178.         /* Scale value */
  179.         value = chn->value - chn->low;
  180.         if( value < 0 ) value = 0;
  181.         if( value > chn->range ) value = chn->range;
  182.  
  183.         value = value * 44 / chn->range;
  184.  
  185.         normvalue = value + 2; /* Base of meter isn't at bottom of tile */
  186.  
  187.     }
  188.  
  189.     /* Draw meter */
  190.  
  191.  
  192.     if( chn->flags & CHANNEL_FLAG_UNKNOWN ) {
  193.         tilevalue = 9;
  194.     } else {
  195.         if( normvalue < 0 ) normvalue = 0;
  196.         tilevalue = normvalue;
  197.         if( tilevalue > 8 ) tilevalue = 8;
  198.         normvalue -= 8;
  199.     }
  200.     tilevalue *= 2;
  201.  
  202.     fb[32*6 + 1] = 192+tilevalue; fb[32*6 + 2] = 193+tilevalue;
  203.     for( i=5; i>=2; i-- ) {
  204.         if( !( chn->flags & CHANNEL_FLAG_UNKNOWN ) ) {
  205.             if( normvalue < 0 ) normvalue = 0;
  206.             tilevalue = normvalue;
  207.             if( tilevalue > 8 ) tilevalue = 8;
  208.             normvalue -= 8;
  209.             tilevalue *= 2;
  210.         }
  211.  
  212.         fb[32*i + 1] = 160+tilevalue; fb[32*i + 2] = 161+tilevalue;
  213.     }
  214.     if( !( chn->flags & CHANNEL_FLAG_UNKNOWN ) ) {
  215.         if( normvalue < 0 ) normvalue = 0;
  216.         tilevalue = normvalue;
  217.         if( tilevalue > 8 ) tilevalue = 8;
  218.         normvalue -= 8;
  219.         tilevalue *= 2;
  220.     }
  221.  
  222.     fb[32*1 + 1] = 128+tilevalue; fb[32*1 + 2] = 129+tilevalue;
  223.  
  224. }
  225.  
  226. void chn_lcd_control_Init(void)
  227. {
  228.     uint8_t i;
  229.     ///TODO: Initialize hardware etc here
  230.  
  231.     // to use PCINt lib, call this function: (the callback function look as a timer callback function)
  232.     // Pcint_SetCallbackPin(chn_lcd_control_PCINT, EXP_C , &chn_lcd_control_pcint_callback);
  233.  
  234.     for( i = 0; i < channels_count; i++ ) {
  235.         chn_lcd_control_drawChannel( i );
  236.         chn_ChnMaster_RegisterListener( channels[i].id, chn_lcd_control_chn_update );
  237.     }
  238.  
  239.     /*
  240.      * Initialize rotaryencoders and buttons
  241.      */
  242.     gpio_set_in(ROTARY_CH1);    // Set to input
  243.     gpio_set_pullup(ROTARY_CH1);    // Enable pull-up
  244.     gpio_set_in(ROTARY_CH2);    // Set to input
  245.     gpio_set_pullup(ROTARY_CH2);    // Enable pull-up
  246.     gpio_set_in(ROTARY_BTN);    // Set to input
  247.     gpio_set_pullup(ROTARY_BTN);    // Enable pull-up
  248.  
  249.     // Enable IO-pin interrupt
  250.     Pcint_SetCallbackPin(chn_contr_rot_PCINT_CH1, ROTARY_CH1, &rotary_pcint_callback);
  251.     Pcint_SetCallbackPin(chn_contr_rot_PCINT_CH2, ROTARY_CH2, &rotary_pcint_callback);
  252. //    Pcint_SetCallbackPin(chn_contr_rot_PCINT_BTN, ROTARY_BTN, &rotary_pcint_callback);
  253.  
  254. }
  255.  
  256. void chn_lcd_control_Process(void)
  257. {
  258.     int8_t rotary_pos = rotaryEncoder_Position;
  259.     int32_t value;
  260.     uint8_t old_channel,i;
  261.  
  262.     rotaryEncoder_Position = 0;
  263.  
  264.     if( rotary_pos != 0 ) {
  265.         chn_lcd_control_enable();
  266.     }
  267.  
  268.     if( controller_editmode ) {
  269.         if( channel_sel < channels_count && rotary_pos != 0 ) {
  270.             value = channels[ channel_sel ].value;
  271.             value += 2048L * (int32_t)rotary_pos;
  272.             if( value < 0 ) value = 0;
  273.             if( value > 65535 ) value = 65535;
  274.             channels[ channel_sel ].value = value;
  275.  
  276.             chn_ChnMaster_UpdateChannel( channels[ channel_sel ].id, value );
  277.  
  278.             channels[ channel_sel ].flags &= ~CHANNEL_FLAG_UNKNOWN;
  279.             channels[ channel_sel ].flags |= CHANNEL_FLAG_REDRAW;
  280.         }
  281.     } else {
  282.         old_channel = channel_sel;
  283.         while( rotary_pos > 0 ) {
  284.             do {
  285.                 channel_sel = (channel_sel+1)%channels_count;
  286.             } while( !( channels[ channel_sel ].flags & CHANNEL_FLAG_WRITABLE ) );
  287.             rotary_pos--;
  288.         }
  289.         while( rotary_pos < 0 ) {
  290.             do {
  291.                 channel_sel = (channel_sel+channels_count-1)%channels_count;
  292.             } while( !( channels[ channel_sel ].flags & CHANNEL_FLAG_WRITABLE ) );
  293.             rotary_pos++;
  294.         }
  295.         if( old_channel != channel_sel ) {
  296.             channels[ old_channel ].flags |= CHANNEL_FLAG_REDRAW;
  297.             channels[ channel_sel ].flags |= CHANNEL_FLAG_REDRAW;
  298.         }
  299.     }
  300.  
  301.  
  302.     //Take care of button push
  303.     rotaryEncoder_Button_Position = gpio_get_state(ROTARY_BTN);
  304.     if( rotaryEncoder_Button_Position && !rotaryEncoder_Button_Position_old ) {
  305.         chn_lcd_control_enable();
  306.         controller_editmode = !controller_editmode;
  307.         channels[ channel_sel ].flags |= CHANNEL_FLAG_REDRAW;
  308.     }
  309.     rotaryEncoder_Button_Position_old = rotaryEncoder_Button_Position;
  310.  
  311.     for( i=0; i<channels_count; i++ ) {
  312.         if( channels[ i ].flags & CHANNEL_FLAG_REDRAW ) {
  313.             channels[ i ].flags &= ~CHANNEL_FLAG_REDRAW;
  314.             chn_lcd_control_drawChannel( i );
  315.         }
  316.     }
  317.  
  318. }
  319.  
  320. void chn_lcd_control_HandleMessage(StdCan_Msg_t *rxMsg)
  321. {
  322. }
  323.  
  324. void chn_lcd_control_List(uint8_t ModuleSequenceNumber)
  325. {
  326.     StdCan_Msg_t txMsg;
  327.    
  328.     StdCan_Set_class(txMsg.Header, CAN_MODULE_CLASS_CHN);
  329.     StdCan_Set_direction(txMsg.Header, DIRECTIONFLAG_FROM_OWNER);
  330.     txMsg.Header.ModuleType = CAN_MODULE_TYPE_CHN_CHNCONTROLLER;
  331.     txMsg.Header.ModuleId = chn_lcd_control_ID;
  332.     txMsg.Header.Command = CAN_MODULE_CMD_GLOBAL_LIST;
  333.     txMsg.Length = 6;
  334.  
  335.     txMsg.Data[0] = NODE_HW_ID_BYTE0;
  336.     txMsg.Data[1] = NODE_HW_ID_BYTE1;
  337.     txMsg.Data[2] = NODE_HW_ID_BYTE2;
  338.     txMsg.Data[3] = NODE_HW_ID_BYTE3;
  339.    
  340.     txMsg.Data[4] = NUMBER_OF_MODULES;
  341.     txMsg.Data[5] = ModuleSequenceNumber;
  342.    
  343.     while (StdCan_Put(&txMsg) != StdCan_Ret_OK);
  344. }
  345.