Subversion Repositories HomeAutomation

Rev

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