Subversion Repositories HomeAutomation

Rev

Rev 653 | Details | Compare with Previous | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
645 noddan 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
 *
647 noddan 10
 * TODO: put rotary encoder in external library, same with s16/u16tostr, cleanup, read external sensors... a lot basically.
11
 * Assume all sensor conversion done on the sensorcard, use canstandard here
645 noddan 12
 */
13
 
14
/*-----------------------------------------------------------------------------
15
 * Includes
16
 *---------------------------------------------------------------------------*/
17
/* system files */
18
#include <avr/io.h>
19
#include <inttypes.h>
20
#include <avr/interrupt.h>
21
#include <stdio.h>
22
/* lib files */
23
#include <bios.h>
24
#include <config.h>
25
#include <drivers/lcd/clcd/lcd_HD44780.h>
26
#include <stdlib.h> //for itoa
27
 
28
#include <string.h> //for memcpy
29
 
30
 
31
/* <SIZE> 8 bits 0xFFL */
32
#define LCD_SIZE_ALL    0x00L
33
#define LCD_SIZE_16x2   0x02L
34
#define LCD_SIZE_20x4   0x10L
35
 
36
 
37
//Borde ha en bŠttre plats.
38
#define max(a,b) ((a>b)?a:b)
39
#define min(a,b) ((a<b)?a:b)
40
 
41
 
42
/*-----------------------------------------------------------------------------
43
 * Defines
44
 *---------------------------------------------------------------------------*/
45
#define SIZE_X  20
46
#define SIZE_Y  4
47
#define SIZE_LCD LCD_SIZE_20x4
48
 
49
#define BUFFER_SIZE SIZE_X
50
#define TRUE 1
51
#define FALSE 0
52
 
53
#define LEFT    0x01
54
#define RIGHT   0x02
55
#define BUTTON_PUSH 0x03
56
#define BUTTON_RELEASE 0x04
57
 
58
volatile Can_Message_t rxMsg;
59
 
60
char incoming_text[ BUFFER_SIZE ];
61
uint8_t rxMsgFull;
62
 
63
 
64
char buffer[ BUFFER_SIZE ];
65
 
66
void send_dimensions(void);
67
void rotenc(void);
68
void rotenc_action(uint8_t type);
69
 
70
 
71
void updateDisplay(uint8_t screen, uint8_t transition);
72
 
653 noddan 73
#define SCR_BOOST       0x00
74
#define SCR_MAXBOOST    0x01
75
#define SCR_LAMBDA      0x02
645 noddan 76
#define SCR_RPM         0x03
77
#define SCR_VOLTAGE     0x04
653 noddan 78
#define SCR_VELOCITY    0x05
79
#define SCR_FUELCONS    0x06
80
//#define SCR_OILPRESS  0x07
81
//#define SCR_OILTEMP   0x08
82
#define LAST_SCREEN     0x06
645 noddan 83
 
647 noddan 84
void numtoascii( int16_t num, char **str );
653 noddan 85
void signedtoascii(int16_t num, uint8_t decimalplace, char *string, uint8_t numberofdecimals);
86
void unsignedtoascii(uint16_t num, uint8_t decimalplace, char *string, uint8_t numberofdecimals);
647 noddan 87
 
645 noddan 88
 
89
 
90
/*******************************************************************************
91
 * Sensor Values, Scale factors etc.                                           *
92
 *******************************************************************************/
653 noddan 93
int16_t     sensor_Boost        = 0.001*64;
94
int16_t     sensor_Boost_Max    = 0.92*64;  //highest boost so far
95
uint16_t    sensor_Lambda       = 32000;
96
uint16_t    sensor_RPM          = 3973*(2<<(SNS_DECPOINT_ROTSPEED-1));
97
uint16_t    sensor_Voltage      = 12.7*(2<<(SNS_DECPOINT_VOLTAGE-1));
98
uint16_t    sensor_Velocity     = 120*(2<<(SNS_DECPOINT_VELOCITY-1));
99
uint16_t    sensor_Fuelcons     = 0.78*(2<<(SNS_DECPOINT_FUELCONS-1));
645 noddan 100
 
653 noddan 101
#define SCALE_BOOSTMAX 1.2*64 //depending on memory usage later, maybe put these in eeprom?
102
#define SCALE_LAMBDAMAX 65535
103
#define SCALE_RPMMAX 8000*(2<<(SNS_DECPOINT_ROTSPEED-1))
104
#define SCALE_VOLTAGEMAX 15*(2<<(SNS_DECPOINT_VOLTAGE-1))
105
#define SCALE_VELOCITYMAX 150*(2<<(SNS_DECPOINT_VELOCITY-1))
106
#define SCALE_FUELCONSMAX 2*(2<<(SNS_DECPOINT_FUELCONS-1))
645 noddan 107
 
108
 
109
 
653 noddan 110
/*******************************************************************************
111
 * Something else..                                                            *
112
 *******************************************************************************/
645 noddan 113
 
653 noddan 114
uint8_t currentScreen; //current screen
115
 
645 noddan 116
// CAN message reception callback
117
// This function runs with interrupts disabled, keep it as short as possible
118
void can_receive(Can_Message_t *msg){
119
    if(!rxMsgFull){
120
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
121
        rxMsgFull = 1;
122
    }
123
}
124
 
125
ISR( PCINT2_vect ){
126
// For ROTENC_A and ROTENC_B FIXME Šr inte riktigt rŠtt. Verkar vara bra tycker jag?
127
    rotenc();
128
}
129
 
130
ISR( PCINT0_vect ){
131
// For ROTENC_BTN
132
    rotenc();
133
}
134
 
135
/*-----------------------------------------------------------------------------
136
 * Main Program
137
 *---------------------------------------------------------------------------*/
138
int main(void) {
139
    currentScreen = 0; //init display position
140
 
141
//  uint32_t act; not used anymoer
142
//  uint8_t act_type, lcd_size; not used anymore
143
    //uint8_t m, lcd_action;
144
 
145
    sei();
146
 
147
    /*
148
     * Initialize rotaryencoders and buttons
149
     */
150
    // Set as input
151
    DDRD &= ~(1<<DDD2);
152
    DDRB &= ~((1<<DDB7)|(1<<DDB0));
153
    // Enable pull-up
154
    PORTD |= (1<<PD2);
155
    PORTB |= (1<<PB7)|(1<<PB0);
156
    // Enable IO-pin interrupt
157
    PCICR |= (1<<PCIE2)|(1<<PCIE0);
158
    // Unmask PB7, PB0 and PD2
159
    PCMSK2 |= (1<<PCINT18);
160
    PCMSK0 |= (1<<PCINT7)|(1<<PCINT0);
161
 
162
    // Contrast
163
    TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
164
    TCCR0B |= (1<<CS00);
165
    OCR0B = 0x10;
166
    DDRD |= (1<<DDD5);
167
 
168
    // Backlight
169
    TCCR1A |= (1<<COM1A1)|(1<<WGM11);
170
    TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
171
    ICR1 = 0xFF; // Make it 8 bits
172
    OCR1A = 0xFF;
173
    DDRB |= (1<<DDB1);
174
 
175
 
176
    Can_Message_t txMsg;
177
    txMsg.ExtendedFlag=1;
178
    txMsg.RemoteFlag=0;
179
// FIXME skicka app startad
180
    BIOS_CanCallback = &can_receive;
181
 
182
    lcd_init( LCD_DISP_ON );
183
    lcd_clrscr();
184
    lcd_puts("CarDisplay");
185
 
186
    send_dimensions();
187
    lcd_gotoxy(0,1);
188
    lcd_puts("CAN Connected!");
189
 
190
    /* main loop */
191
    while(1){
192
        /* check if any messages have been received */
193
        if(rxMsgFull){
647 noddan 194
            uint16_t sns_type;
195
            uint8_t snsid;
196
            if ( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_SNS){// FIXME ett jŠkla herk, stŠda upp
197
 
198
                sns_type = (uint16_t)((rxMsg.Id & CAN_MASK_SNS_TYPE) >> CAN_SHIFT_SNS_TYPE);
199
                snsid = (uint8_t)((rxMsg.Id & CAN_MASK_SNS_ID) >> CAN_SHIFT_SNS_ID);
200
 
653 noddan 201
                switch(sns_type){
202
                case SNS_TYPE_PRESSURE:
647 noddan 203
                    sensor_Boost = rxMsg.Data.bytes[0]*256 + rxMsg.Data.bytes[1];
653 noddan 204
                    sensor_Boost_Max = max(sensor_Boost,sensor_Boost_Max);
205
                    if (currentScreen == SCR_BOOST) updateDisplay(SCR_BOOST,0);        
206
                break;
207
                case SNS_TYPE_ROTSPEED:
208
                    sensor_RPM = rxMsg.Data.bytes[0]*256 + rxMsg.Data.bytes[1];
209
                    if (currentScreen == SCR_RPM) updateDisplay(SCR_RPM,0);
210
                break;
211
                case SNS_TYPE_VOLTAGE:
212
                    sensor_Voltage = rxMsg.Data.bytes[0]*256 + rxMsg.Data.bytes[1];
213
                    if (currentScreen == SCR_VOLTAGE) updateDisplay(SCR_VOLTAGE,0);
647 noddan 214
                }
645 noddan 215
 
216
            }
217
            rxMsgFull = 0;
218
        }
219
    }
220
}
221
 
222
void send_dimensions(){
223
    Can_Message_t txMsg;
224
 
225
    txMsg.ExtendedFlag=1;
226
    txMsg.RemoteFlag=0;
227
    txMsg.Id=0xA000001;
228
    txMsg.Data.bytes[0] = SIZE_X;
229
    txMsg.Data.bytes[1] = SIZE_Y;
230
    txMsg.DataLength = 2;
231
 
232
    BIOS_CanSend(&txMsg);
233
}
234
 
235
void rotenc_action(uint8_t type){
236
    //Let's do something with something!
653 noddan 237
 
645 noddan 238
    if (type == LEFT){ 
239
        if (currentScreen == 0) currentScreen = LAST_SCREEN+1;
240
        currentScreen--;
241
        updateDisplay(currentScreen,1);
242
    }
243
    if (type == RIGHT){
244
        currentScreen++;
245
        if (currentScreen > LAST_SCREEN) currentScreen = 0;
246
        updateDisplay(currentScreen,1);
247
    }
248
    if (type == BUTTON_PUSH){
249
 
250
    }
251
    if (type == BUTTON_RELEASE){
252
 
253
    }
254
}
255
 
256
void updateDisplay(uint8_t screen, uint8_t transition){
647 noddan 257
    char buffer[20];   
645 noddan 258
 
259
    if (transition){
260
        lcd_clrscr();
653 noddan 261
        lcd_setanimation(1);
647 noddan 262
    } else {
263
        lcd_setanimation(0);
645 noddan 264
    }
265
    switch (screen){
266
    case SCR_LAMBDA:
267
        lcd_gotoxy(0,0);
653 noddan 268
        lcd_puts("LEAN   Lambda   RICH");
645 noddan 269
        lcd_gotoxy(0,1);
653 noddan 270
        lcdProgressBar(sensor_Lambda, SCALE_LAMBDAMAX, SIZE_X); //TODO: vacker bargraph med bara en plupp i mitten
645 noddan 271
    break;
272
    case SCR_RPM:      
273
        lcd_gotoxy(0,0);
274
        lcd_puts("RPM: ");
653 noddan 275
        unsignedtoascii(sensor_RPM,SNS_DECPOINT_ROTSPEED,buffer,0);
645 noddan 276
        lcd_puts(buffer);
277
        lcd_gotoxy(0,1);
653 noddan 278
        lcdProgressBar(sensor_RPM, SCALE_RPMMAX, SIZE_X);
645 noddan 279
    break;
653 noddan 280
    case SCR_BOOST:        
645 noddan 281
        lcd_gotoxy(0,0);
653 noddan 282
        lcd_puts("Boost: ");   
283
        signedtoascii(sensor_Boost,SNS_DECPOINT_PRESSURE,buffer,2);
647 noddan 284
        lcd_puts(buffer);
653 noddan 285
        lcd_puts(" bar    ");
645 noddan 286
 
287
        lcd_gotoxy(0,1);
653 noddan 288
        lcdProgressBar(max(0,sensor_Boost), SCALE_BOOSTMAX, SIZE_X);
645 noddan 289
    break;
647 noddan 290
    case SCR_MAXBOOST: //currently just a testscreen ffs omg
645 noddan 291
        lcd_gotoxy(0,0);
292
        lcd_puts("Max Boost: ");
653 noddan 293
        signedtoascii(sensor_Boost_Max ,SNS_DECPOINT_PRESSURE,buffer,2);
647 noddan 294
        lcd_puts(buffer);
653 noddan 295
        lcd_puts(" bar");
645 noddan 296
    break;
297
    case SCR_VOLTAGE:
298
        lcd_gotoxy(0,0);
653 noddan 299
        lcd_puts("Voltage: "); 
300
        unsignedtoascii(sensor_Voltage,SNS_DECPOINT_VOLTAGE,buffer,2);
301
        lcd_puts(buffer);
302
        lcd_puts(" V");    
645 noddan 303
        lcd_gotoxy(0,1);
653 noddan 304
        lcdProgressBar(max(0,sensor_Voltage), SCALE_VOLTAGEMAX, SIZE_X);
645 noddan 305
    break;
653 noddan 306
    case SCR_FUELCONS:
307
        lcd_gotoxy(0,0);
308
        lcd_puts("Fuel: ");
309
        unsignedtoascii(sensor_Fuelcons,SNS_DECPOINT_FUELCONS,buffer,2);
310
        lcd_puts(buffer);
311
        lcd_puts(" L/10km");       
312
        lcd_gotoxy(0,1);
313
        lcdProgressBar(max(0,sensor_Fuelcons), SCALE_FUELCONSMAX, SIZE_X);
314
    break;
315
    case SCR_VELOCITY:
316
        lcd_gotoxy(0,0);
317
        lcd_puts("Speed: ");   
318
        unsignedtoascii(sensor_Velocity,SNS_DECPOINT_VELOCITY,buffer,0);
319
        lcd_puts(buffer);
320
        lcd_puts(" km/h");     
321
        lcd_gotoxy(0,1);
322
        lcdProgressBar(max(0,sensor_Velocity), SCALE_VELOCITYMAX, SIZE_X);
323
    break;
645 noddan 324
    }
325
}
326
 
327
 
328
 
329
 
330
 
331
 
332
 
333
 
334
 
335
 
336
 
337
 
338
 
339
 
340
void rotenc(){
341
    uint8_t rot_data = 0;
342
    static uint8_t rot_lastdir = 0, rot_laststate = 0, btn_laststate = 0;
343
 
344
    Can_Message_t txMsg;
345
    txMsg.ExtendedFlag=1;
346
    txMsg.RemoteFlag=0;
347
    //txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x01<<SNS_ID_BITS )| NODE_ID;//FIXME: borttaget
348
    txMsg.DataLength=2;
349
 
350
    //Take care of button push
351
    if ((PINB&(1<<PB7)) != btn_laststate){ //The buttonstate has changed! Let's send a message!
352
        btn_laststate = (PINB&(1<<PB7));
353
        txMsg.Data.bytes[0] = 5;
354
        txMsg.Data.bytes[1] = (btn_laststate)?0:1;
355
        txMsg.DataLength=2;
356
        BIOS_CanSend(&txMsg);
357
        rotenc_action((btn_laststate)?BUTTON_RELEASE:BUTTON_PUSH);
358
    }
359
 
360
    //Take care of rotary encoder movement
361
    if(PINB&(1<<PB0)){
362
        rot_data |= 0x01;
363
    }
364
    if(PIND&(1<<PD2)){
365
        rot_data |= 0x02;
366
    }
367
 
368
    if( rot_data==0 || rot_data==3 ){ // Are both signals high or low?
369
        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. 
370
            if( rot_lastdir&0x01 ){
371
                // Moving right
372
                txMsg.Data.bytes[0]=RIGHT;
373
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
374
                txMsg.DataLength=2;
375
                BIOS_CanSend(&txMsg);
376
                rotenc_action(RIGHT);
377
            }else{
378
                // Moving left
379
                txMsg.Data.bytes[0]=LEFT;
380
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
381
                txMsg.DataLength=2;
382
                BIOS_CanSend(&txMsg);
383
                rotenc_action(LEFT);
384
            }
385
        }
386
        rot_laststate = rot_data;
387
    } else { // No, only one of the signals are high. We can use this to find out what direction we are moving.
388
        rot_lastdir = rot_data;
389
    }
390
}
391
 
392
 
393
 
653 noddan 394
//‡ la pengi. Skall libbifieras.
647 noddan 395
void numtoascii( int16_t num, char **str ) {
396
    if( num==0 ) return;
397
    numtoascii( num/10, str );
398
    **str = '0' + (num%10);
399
    (*str)++;
400
}
401
 
653 noddan 402
void signedtoascii(int16_t num, uint8_t decimalplace, char *string, uint8_t numberofdecimals){ //decimalplace is number of decimals
647 noddan 403
    uint8_t i;
653 noddan 404
 
647 noddan 405
    if( num<0 ) {
406
        *(string++) = '-';
407
        num = -num;
408
    }
409
    numtoascii(num>>decimalplace, &string );
653 noddan 410
    if(numberofdecimals!=0) *(string++) = '.';
411
    for(i=0;i<numberofdecimals;i++) {
647 noddan 412
        num %= 1<<decimalplace;
413
        num *= 10;
414
        *(string++) = '0' + (num>>decimalplace);
415
    }
416
    *(string++) = 0;
417
}
418
 
653 noddan 419
void unsignedtoascii(uint16_t num, uint8_t decimalplace, char *string, uint8_t numberofdecimals){ //decimalplace is number of decimals
420
    uint8_t i;
421
    numtoascii(num>>decimalplace, &string );
422
    if(numberofdecimals!=0) *(string++) = '.';
423
    for(i=0;i<numberofdecimals;i++) {
424
        num %= 1<<decimalplace;
425
        num *= 10;
426
        *(string++) = '0' + (num>>decimalplace);
645 noddan 427
    }
653 noddan 428
    *(string++) = 0;
645 noddan 429
}
430
 
431