Subversion Repositories HomeAutomation

Rev

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

  1. /**
  2.  * CanCarDisplay. HID for simple carsensor network
  3.  * For HD44780- and KS0073-based LCD displays
  4.  *
  5.  * Contains no intelligence. It just prints what it is told to.
  6.  *
  7.  * @date    2007-10-01
  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 <stdlib.h> //for itoa
  25.  
  26. #include <string.h> //for memcpy
  27.  
  28.  
  29. /* <SIZE> 8 bits 0xFFL */
  30. #define LCD_SIZE_ALL    0x00L
  31. #define LCD_SIZE_16x2   0x02L
  32. #define LCD_SIZE_20x4   0x10L
  33.  
  34.  
  35. //Borde ha en bŠttre plats.
  36. #define max(a,b) ((a>b)?a:b)
  37. #define min(a,b) ((a<b)?a:b)
  38.  
  39.  
  40. /*-----------------------------------------------------------------------------
  41.  * Defines
  42.  *---------------------------------------------------------------------------*/
  43. #define SIZE_X  20
  44. #define SIZE_Y  4
  45. #define SIZE_LCD LCD_SIZE_20x4
  46.  
  47. #define BUFFER_SIZE SIZE_X
  48. #define TRUE 1
  49. #define FALSE 0
  50.  
  51. #define LEFT    0x01
  52. #define RIGHT   0x02
  53. #define BUTTON_PUSH 0x03
  54. #define BUTTON_RELEASE 0x04
  55.  
  56. volatile Can_Message_t rxMsg;
  57.  
  58. char incoming_text[ BUFFER_SIZE ];
  59. uint8_t rxMsgFull;
  60.  
  61.  
  62. char buffer[ BUFFER_SIZE ];
  63.  
  64. void send_dimensions(void);
  65. void rotenc(void);
  66. void rotenc_action(uint8_t type);
  67.  
  68.  
  69. void updateDisplay(uint8_t screen, uint8_t transition);
  70.  
  71. #define SCR_LAMBDA      0x00
  72. #define SCR_BOOST       0x01
  73. #define SCR_MAXBOOST    0x02
  74. #define SCR_RPM         0x03
  75. #define SCR_VOLTAGE     0x04
  76. #define LAST_SCREEN     0x04
  77. void standardScreen(char* text, uint16_t value, uint16_t maxvalue);
  78.  
  79. uint8_t *io_s16toStr(int16_t value, uint8_t *str,uint8_t decimal,uint8_t options);
  80. uint8_t *io_u16toStr(uint16_t value, uint8_t *str,uint8_t decimal,uint8_t options);
  81.  
  82.  
  83.  
  84. /*******************************************************************************
  85.  * Sensor Values, Scale factors etc.                                           *
  86.  *******************************************************************************/
  87. int16_t sensor_Boost = 120; //Should be set automagically by incoming CAN
  88. int16_t sensor_Boost_Max = 200;
  89.  
  90. uint16_t sensor_RPM = 2573;
  91. uint8_t sensor_Lambda = 127;
  92. uint8_t sensor_Voltage = 143;
  93.  
  94. #define scale_Boost 809 //Read from eeprom later on?
  95. #define scale_BoostOffset 168 //Read from eeprom later on?
  96. #define scale_BoostMAX 200
  97. #define scale_RPMMAX 8000 //Can be set as in eeprom later perhaps?
  98. #define scale_Voltage 1024
  99. #define scale_VoltageMAX 150
  100.  
  101.  
  102. uint8_t currentScreen;
  103.  
  104. // CAN message reception callback
  105. // This function runs with interrupts disabled, keep it as short as possible
  106. void can_receive(Can_Message_t *msg){
  107.     if(!rxMsgFull){
  108.         memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
  109.         rxMsgFull = 1;
  110.     }
  111. }
  112.  
  113. ISR( PCINT2_vect ){
  114. // For ROTENC_A and ROTENC_B FIXME Šr inte riktigt rŠtt. Verkar vara bra tycker jag?
  115.     rotenc();
  116. }
  117.  
  118. ISR( PCINT0_vect ){
  119. // For ROTENC_BTN
  120.     rotenc();
  121. }
  122.  
  123. /*-----------------------------------------------------------------------------
  124.  * Main Program
  125.  *---------------------------------------------------------------------------*/
  126. int main(void) {
  127.     currentScreen = 0; //init display position
  128.    
  129. //  uint32_t act; not used anymoer
  130. //  uint8_t act_type, lcd_size; not used anymore
  131.     //uint8_t m, lcd_action;
  132.  
  133.     sei();
  134.  
  135.     /*
  136.      * Initialize rotaryencoders and buttons
  137.      */
  138.     // Set as input
  139.     DDRD &= ~(1<<DDD2);
  140.     DDRB &= ~((1<<DDB7)|(1<<DDB0));
  141.     // Enable pull-up
  142.     PORTD |= (1<<PD2);
  143.     PORTB |= (1<<PB7)|(1<<PB0);
  144.     // Enable IO-pin interrupt
  145.     PCICR |= (1<<PCIE2)|(1<<PCIE0);
  146.     // Unmask PB7, PB0 and PD2
  147.     PCMSK2 |= (1<<PCINT18);
  148.     PCMSK0 |= (1<<PCINT7)|(1<<PCINT0);
  149.  
  150.     // Contrast
  151.     TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
  152.     TCCR0B |= (1<<CS00);
  153.     OCR0B = 0x10;
  154.     DDRD |= (1<<DDD5);
  155.  
  156.     // Backlight
  157.     TCCR1A |= (1<<COM1A1)|(1<<WGM11);
  158.     TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
  159.     ICR1 = 0xFF; // Make it 8 bits
  160.     OCR1A = 0xFF;
  161.     DDRB |= (1<<DDB1);
  162.  
  163.  
  164.     Can_Message_t txMsg;
  165.     txMsg.ExtendedFlag=1;
  166.     txMsg.RemoteFlag=0;
  167. // FIXME skicka app startad
  168.     BIOS_CanCallback = &can_receive;
  169.  
  170.     lcd_init( LCD_DISP_ON );
  171.     lcd_clrscr();
  172.     lcd_puts("CarDisplay");
  173.  
  174.     send_dimensions();
  175.     lcd_gotoxy(0,1);
  176.     lcd_puts("CAN Connected!");
  177.  
  178.     /* main loop */
  179.     while(1){
  180.         /* check if any messages have been received */
  181.         if(rxMsgFull){
  182.             uint16_t act_type;
  183.             uint8_t lcdid;
  184.             if ( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_ACT){// FIXME ett jŠkla herk, stŠda upp
  185.                
  186.                
  187.                 act_type =(uint16_t)((rxMsg.Id & CAN_MASK_ACT_TYPE) >> CAN_SHIFT_ACT_TYPE);
  188.            
  189.                 lcdid = (uint8_t)((rxMsg.Id & CAN_MASK_ACT_ID) >> CAN_SHIFT_ACT_ID);               
  190.  
  191.  
  192.             }
  193.             rxMsgFull = 0;
  194.         }
  195.     }
  196. }
  197.  
  198. void send_dimensions(){
  199.     Can_Message_t txMsg;
  200.  
  201.     txMsg.ExtendedFlag=1;
  202.     txMsg.RemoteFlag=0;
  203.     txMsg.Id=0xA000001;
  204.     txMsg.Data.bytes[0] = SIZE_X;
  205.     txMsg.Data.bytes[1] = SIZE_Y;
  206.     txMsg.DataLength = 2;
  207.  
  208.     BIOS_CanSend(&txMsg);
  209. }
  210.  
  211. void rotenc_action(uint8_t type){
  212.     //Let's do something with something!
  213.     lcd_clrscr();
  214.     if (type == LEFT){ 
  215.         if (currentScreen == 0) currentScreen = LAST_SCREEN+1;
  216.         currentScreen--;
  217.         updateDisplay(currentScreen,1);
  218.     }
  219.     if (type == RIGHT){
  220.         currentScreen++;
  221.         if (currentScreen > LAST_SCREEN) currentScreen = 0;
  222.         updateDisplay(currentScreen,1);
  223.     }
  224.     if (type == BUTTON_PUSH){
  225.  
  226.     }
  227.     if (type == BUTTON_RELEASE){
  228.  
  229.     }
  230. }
  231.  
  232. void updateDisplay(uint8_t screen, uint8_t transition){
  233.     char buffer[10];   
  234.    
  235.     if (transition){
  236.         lcd_clrscr();
  237.     }
  238.     switch (screen){
  239.     case SCR_LAMBDA:
  240.         lcd_gotoxy(0,0);
  241.         lcd_puts("LEAN Lambda RICH");
  242.         lcd_gotoxy(0,1);
  243.         lcdProgressBar(sensor_Lambda, 255, 16); //TODO: vacker bargraph med bara en plupp i mitten
  244.     break;
  245.     case SCR_RPM:      
  246.         lcd_gotoxy(0,0);
  247.         itoa(sensor_RPM,buffer,10);
  248.         lcd_puts("RPM: ");
  249.         lcd_puts(buffer);
  250.         lcd_gotoxy(0,1);
  251.         lcdProgressBar(sensor_RPM, scale_RPMMAX, 16);
  252.     break;
  253.     case SCR_BOOST:
  254.            
  255.         lcd_gotoxy(0,0);
  256.         lcd_puts("Boost:");
  257.    
  258.         lcd_gotoxy(7,0);
  259.         lcd_puts(io_s16toStr(((int32_t)sensor_Boost*scale_Boost)>>10,buffer,2,1));
  260.    
  261.         lcd_gotoxy(13,0);
  262.         lcd_puts("bar");
  263.        
  264.         lcd_gotoxy(0,1);
  265.         lcdProgressBar(max(0,sensor_Boost), ((int32_t)scale_BoostMAX)>>10, 16);
  266.     break;
  267.     case SCR_MAXBOOST:
  268.         lcd_gotoxy(0,0);
  269.         lcd_puts("Max Boost: ");
  270.         lcd_gotoxy(11,0);
  271.         lcd_puts(io_s16toStr(((int32_t)sensor_Boost_Max*scale_Boost)>>10,buffer,2,1));     
  272.     break;
  273.     case SCR_VOLTAGE:
  274.  
  275.         lcd_gotoxy(0,0);
  276.         lcd_puts("Voltage:");
  277.        
  278.         lcd_gotoxy(9,0);
  279.         lcd_puts(io_u16toStr(((uint32_t)sensor_Voltage*scale_Voltage)>>10,buffer,1,0));
  280.        
  281.         lcd_gotoxy(16,0);
  282.         lcd_puts("V");     
  283.         lcd_puts("spanning!");
  284.        
  285.         lcd_gotoxy(0,1);
  286.         lcdProgressBar(sensor_Voltage, scale_VoltageMAX, 16);
  287.     break;
  288.     }
  289. }
  290.  
  291. void standardScreen(char* text, uint16_t value, uint16_t maxvalue){
  292.     lcd_gotoxy(0,0);
  293.     char buffer[5];
  294.     itoa(value,buffer,10);
  295.     lcd_puts(text);
  296.     lcd_puts(" ");
  297.     lcd_puts(buffer);
  298.     lcd_gotoxy(0,1);
  299.     lcdProgressBar(value, maxvalue, 16);
  300. }
  301.  
  302.  
  303.  
  304.  
  305.  
  306.  
  307.  
  308.  
  309.  
  310.  
  311.  
  312.  
  313.  
  314.  
  315.  
  316.  
  317. void rotenc(){
  318.     uint8_t rot_data = 0;
  319.     static uint8_t rot_lastdir = 0, rot_laststate = 0, btn_laststate = 0;
  320.  
  321.     Can_Message_t txMsg;
  322.     txMsg.ExtendedFlag=1;
  323.     txMsg.RemoteFlag=0;
  324.     //txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x01<<SNS_ID_BITS )| NODE_ID;//FIXME: borttaget
  325.     txMsg.DataLength=2;
  326.  
  327.     //Take care of button push
  328.     if ((PINB&(1<<PB7)) != btn_laststate){ //The buttonstate has changed! Let's send a message!
  329.         btn_laststate = (PINB&(1<<PB7));
  330.         txMsg.Data.bytes[0] = 5;
  331.         txMsg.Data.bytes[1] = (btn_laststate)?0:1;
  332.         txMsg.DataLength=2;
  333.         BIOS_CanSend(&txMsg);
  334.         rotenc_action((btn_laststate)?BUTTON_RELEASE:BUTTON_PUSH);
  335.     }
  336.    
  337.     //Take care of rotary encoder movement
  338.     if(PINB&(1<<PB0)){
  339.         rot_data |= 0x01;
  340.     }
  341.     if(PIND&(1<<PD2)){
  342.         rot_data |= 0x02;
  343.     }
  344.  
  345.     if( rot_data==0 || rot_data==3 ){ // Are both signals high or low?
  346.         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.
  347.             if( rot_lastdir&0x01 ){
  348.                 // Moving right
  349.                 txMsg.Data.bytes[0]=RIGHT;
  350.                 txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
  351.                 txMsg.DataLength=2;
  352.                 BIOS_CanSend(&txMsg);
  353.                 rotenc_action(RIGHT);
  354.             }else{
  355.                 // Moving left
  356.                 txMsg.Data.bytes[0]=LEFT;
  357.                 txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
  358.                 txMsg.DataLength=2;
  359.                 BIOS_CanSend(&txMsg);
  360.                 rotenc_action(LEFT);
  361.             }
  362.         }
  363.         rot_laststate = rot_data;
  364.     } else { // No, only one of the signals are high. We can use this to find out what direction we are moving.
  365.         rot_lastdir = rot_data;
  366.     }
  367. }
  368.  
  369.  
  370.  
  371.  
  372.  
  373.  
  374.  
  375.  
  376. //Supersnodd:
  377.  
  378.  
  379.  
  380. uint8_t _io_buf[10];
  381.  
  382. uint8_t *io_s16toStr(int16_t value,uint8_t *str,uint8_t decimal,uint8_t options) {
  383.     uint8_t i=0,j=0,w=0;
  384.     uint16_t tmp;
  385.    
  386.     if(value<0) {
  387.         str[i++]='-';
  388.         tmp=-value;
  389.     } else {
  390.         if(options&0x01) str[i++]=' ';
  391.         tmp=value;
  392.     }
  393.     while(tmp>0) {
  394.         _io_buf[j++]='0'+(tmp%10);
  395.         tmp=tmp/10;
  396.     }
  397.     if(j<=decimal) {
  398.         str[i++]='0';
  399.         if(decimal>0) str[i++]='.';
  400.         w=i;
  401.         while((i-w)<(decimal-j)) str[i++]='0';
  402.         while(j!=0) str[i++]=_io_buf[--j];
  403.     } else {
  404.         while(j!=0) {
  405.             str[i++]=_io_buf[--j];
  406.             if(j==decimal) str[i++]='.';
  407.         }
  408.     }
  409.     str[i++]=0;
  410.     return(str);
  411. }
  412.  
  413. uint8_t *io_u16toStr(uint16_t value,uint8_t *str,uint8_t decimal,uint8_t options) {
  414.     uint8_t i=0;
  415.     uint8_t j=0;
  416.     uint8_t w=0;
  417.    
  418.     while(value>0) {
  419.         _io_buf[j++]='0'+(value%10);
  420.         value=value/10;
  421.     }
  422.  
  423.     if(j<=decimal) {
  424.         str[i++]='0';
  425.         if(decimal>0) str[i++]='.';
  426.         w=i;
  427.         while((i-w)<(decimal-j)) str[i++]='0';
  428.         while(j!=0) str[i++]=_io_buf[--j];
  429.     } else {
  430.         while(j>0) {
  431.             str[i++]=_io_buf[--j];
  432.             if((decimal>0)&&(j==decimal)) str[i++]='.';
  433.         }
  434.     }
  435.     str[i++]=0;
  436.     return(str);
  437. }
  438.