Subversion Repositories HomeAutomation

Rev

Go to most recent revision | Details | 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
 *
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
}