Subversion Repositories HomeAutomation

Rev

Rev 1334 | Blame | Compare with Previous | Last modification | View Log | SVN | RSS feed

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