Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
179 eqlazer 1
/**
349 eqlazer 2
 * CanSimpleCLCD. Simple version.
179 eqlazer 3
 * For HD44780- and KS0073-based LCD displays
4
 *
349 eqlazer 5
 * Contains no intelligence. It just prints what it is told to.
6
 *
179 eqlazer 7
 * @date    2006-12-11
8
 * @author  Erik Larsson
627 noddan 9
 * @author  Martin Norden
179 eqlazer 10
 *
11
 */
12
 
13
/*-----------------------------------------------------------------------------
14
 * Includes
15
 *---------------------------------------------------------------------------*/
16
/* system files */
17
#include <avr/io.h>
481 eqlazer 18
#include <inttypes.h>
179 eqlazer 19
#include <avr/interrupt.h>
20
#include <stdio.h>
21
/* lib files */
332 eqlazer 22
#include <bios.h>
481 eqlazer 23
#include <config.h>
605 noddan 24
#include <drivers/lcd/clcd/lcd_HD44780.h>
25
 
26
#include <string.h> //for memcpy
27
 
28
 
196 eqlazer 29
/* funcdefs */
605 noddan 30
//#include <funcdefs/funcdefs.h>
31
 
32
 
33
//a lot of crap from previous funcdefs
34
/* ACT LCD 12 bits <ACTION><SIZE> 0xFFFL
35
 *
36
 * <ACTION>, 4 bits = Type och action.
37
 * <SIZE>, 8 bits = Size of display.
38
 */
39
#define LCD_ACTION_MASK 0xF00L /* bit[12..8] */
40
#define LCD_SIZE_MASK 0x0FFL /* bit[7..0] */
41
 
42
#define LCD_ACTION_BITS 8
43
#define LCD_SIZE_BITS 0
44
 
45
 
46
/* <ACTION> 4 bits 0xFL */
47
 
48
#define LCD_ACTION_CLR          0x0L
49
#define LCD_ACTION_CURS         0x1L
50
#define LCD_ACTION_TEXT         0x2L
51
#define LCD_ACTION_GET_SIZE     0x3L
52
#define LCD_ACTION_SET_CONT     0x4L
53
#define LCD_ACTION_SET_BLIGHT   0x5L
54
#define LCD_ACTION_GET_CONT     0x6L
55
#define LCD_ACTION_GET_BLIGHT   0x7L
56
 
57
#define LCD_ACTION_SEND_CONT    0x8L
58
#define LCD_ACTION_SEND_BLIGHT  0x9L
59
 
60
 
61
 
62
/* <SIZE> 8 bits 0xFFL */
63
#define LCD_SIZE_ALL    0x00L
64
#define LCD_SIZE_16x2   0x02L
65
#define LCD_SIZE_20x4   0x10L
66
 
179 eqlazer 67
 
605 noddan 68
 
349 eqlazer 69
/*-----------------------------------------------------------------------------
70
 * Defines
71
 *---------------------------------------------------------------------------*/
344 eqlazer 72
#define SIZE_X  20
73
#define SIZE_Y  4
348 eqlazer 74
#define SIZE_LCD LCD_SIZE_20x4
344 eqlazer 75
 
348 eqlazer 76
#define BUFFER_SIZE SIZE_X
332 eqlazer 77
#define TRUE 1
78
#define FALSE 0
179 eqlazer 79
 
344 eqlazer 80
#define LEFT    0x01
81
#define RIGHT   0x02
82
 
481 eqlazer 83
volatile Can_Message_t rxMsg;
256 eqlazer 84
 
348 eqlazer 85
char incoming_text[ BUFFER_SIZE ];
481 eqlazer 86
uint8_t rxMsgFull;
335 eqlazer 87
 
88
 
349 eqlazer 89
char buffer[ BUFFER_SIZE ];
344 eqlazer 90
 
605 noddan 91
void send_dimensions(void);
92
void rotenc(void);
348 eqlazer 93
 
481 eqlazer 94
// CAN message reception callback
95
// This function runs with interrupts disabled, keep it as short as possible
344 eqlazer 96
void can_receive(Can_Message_t *msg){
481 eqlazer 97
    if(!rxMsgFull){
98
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
99
        rxMsgFull = 1;
348 eqlazer 100
    }
344 eqlazer 101
}
102
 
481 eqlazer 103
ISR( PCINT2_vect ){
627 noddan 104
// For ROTENC_A and ROTENC_B FIXME Šr inte riktigt rŠtt. Verkar vara bra tycker jag?
463 eqlazer 105
    rotenc();
106
}
107
 
481 eqlazer 108
ISR( PCINT0_vect ){
109
// For ROTENC_BTN
627 noddan 110
    rotenc();
463 eqlazer 111
}
112
 
179 eqlazer 113
/*-----------------------------------------------------------------------------
114
 * Main Program
115
 *---------------------------------------------------------------------------*/
116
int main(void) {
607 noddan 117
//  uint32_t act; not used anymoer
118
//  uint8_t act_type, lcd_size; not used anymore
119
    uint8_t m, lcd_action;
179 eqlazer 120
 
481 eqlazer 121
    sei();
122
 
335 eqlazer 123
    /*
124
     * Initialize rotaryencoders and buttons
125
     */
481 eqlazer 126
    // Set as input
344 eqlazer 127
    DDRD &= ~(1<<DDD2);
128
    DDRB &= ~((1<<DDB7)|(1<<DDB0));
481 eqlazer 129
    // Enable pull-up
344 eqlazer 130
    PORTD |= (1<<PD2);
131
    PORTB |= (1<<PB7)|(1<<PB0);
481 eqlazer 132
    // Enable IO-pin interrupt
344 eqlazer 133
    PCICR |= (1<<PCIE2)|(1<<PCIE0);
481 eqlazer 134
    // Unmask PB7, PB0 and PD2
344 eqlazer 135
    PCMSK2 |= (1<<PCINT18);
136
    PCMSK0 |= (1<<PCINT7)|(1<<PCINT0);
179 eqlazer 137
 
481 eqlazer 138
    // Contrast
348 eqlazer 139
    TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
140
    TCCR0B |= (1<<CS00);
481 eqlazer 141
    OCR0B = 0x10;
348 eqlazer 142
    DDRD |= (1<<DDD5);
143
 
481 eqlazer 144
    // Backlight
348 eqlazer 145
    TCCR1A |= (1<<COM1A1)|(1<<WGM11);
146
    TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
147
    ICR1 = 0xFF; // Make it 8 bits
607 noddan 148
    OCR1A = 0xFF;
348 eqlazer 149
    DDRB |= (1<<DDB1);
607 noddan 150
 
348 eqlazer 151
 
463 eqlazer 152
    Can_Message_t txMsg;
344 eqlazer 153
    txMsg.ExtendedFlag=1;
154
    txMsg.RemoteFlag=0;
481 eqlazer 155
// FIXME skicka app startad
463 eqlazer 156
    BIOS_CanCallback = &can_receive;
256 eqlazer 157
 
332 eqlazer 158
    lcd_init( LCD_DISP_ON );
159
    lcd_clrscr();
348 eqlazer 160
    lcd_puts("HomeAutomation\n");
179 eqlazer 161
 
344 eqlazer 162
    send_dimensions();
627 noddan 163
    lcd_puts("CAN Connected!\n");
179 eqlazer 164
 
165
    /* main loop */
332 eqlazer 166
    while(1){
167
        /* check if any messages have been received */
607 noddan 168
        if(rxMsgFull){
169
            uint16_t act_type;
170
            uint8_t lcdid;
627 noddan 171
            if ( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_ACT){// FIXME ett jŠkla herk, stŠda upp
607 noddan 172
 
173
 
174
                act_type =(uint16_t)((rxMsg.Id & CAN_MASK_ACT_TYPE) >> CAN_SHIFT_ACT_TYPE);
175
 
176
                lcdid = (uint8_t)((rxMsg.Id & CAN_MASK_ACT_ID) >> CAN_SHIFT_ACT_ID);
177
 
481 eqlazer 178
 
607 noddan 179
                if( act_type == ACT_TYPE_LCD ){ //FIXME add id to check here
180
                    lcd_action =  rxMsg.Data.bytes[0];
481 eqlazer 181
                    switch( lcd_action ){
182
                    case LCD_ACTION_CLR:
183
                        // Clear LCD
184
                        lcd_clrscr();
185
                    break;
186
                    case LCD_ACTION_CURS:
187
                        // Move cursor
607 noddan 188
                        lcd_gotoxy( rxMsg.Data.bytes[1],rxMsg.Data.bytes[2] );
481 eqlazer 189
                    break;
190
                    case LCD_ACTION_GET_SIZE:
191
                        // Request LCD dimension
192
                        send_dimensions();
193
                    break;
194
                    case LCD_ACTION_TEXT:
195
                        // Print text to LCD
607 noddan 196
                        for(m=1;m<rxMsg.DataLength;m++){
481 eqlazer 197
                            lcd_putc( (char)rxMsg.Data.bytes[m] );
198
                        }
199
                    break;
200
                    case LCD_ACTION_SET_CONT:
201
                        // Set contrast
202
                        if(rxMsg.DataLength == 1){
607 noddan 203
                            OCR0B = rxMsg.Data.bytes[1];
481 eqlazer 204
                        }
205
                    break;
206
                    case LCD_ACTION_SET_BLIGHT:
207
                        // Set backlight
607 noddan 208
                        if(rxMsg.DataLength == 2){
209
                            OCR1AL = rxMsg.Data.bytes[1];
481 eqlazer 210
                        }
211
                    break;
212
                    case LCD_ACTION_GET_CONT:
213
                        // Get contrast
214
                        txMsg.DataLength = 1;
607 noddan 215
                        //txMsg.Id = ( CLASS_ACT<<CLASS_MASK_BITS )|( ACT_TYPE_LCD<<ACT_TYPE_BITS )|( LCD_ACTION_SEND_CONT<<LCD_ACTION_BITS )|NODE_ID; FIXME
216
                        txMsg.Data.bytes[1] = OCR0B;
481 eqlazer 217
                        BIOS_CanSend(&txMsg);
218
                    break;
219
                    case LCD_ACTION_GET_BLIGHT:
220
                        // Get backlight
221
                        txMsg.DataLength = 1;
607 noddan 222
                        //txMsg.Id = ( CLASS_ACT<<CLASS_MASK_BITS )|( ACT_TYPE_LCD<<ACT_TYPE_BITS )|( LCD_ACTION_SEND_BLIGHT<<LCD_ACTION_BITS )|NODE_ID; FIXME
223
                        txMsg.Data.bytes[1] = OCR1AL;
481 eqlazer 224
                        BIOS_CanSend(&txMsg);
225
                    break;
226
                    default:
227
                    // Take over the world
228
                    break;
229
                    }
230
                }
231
            }
232
            rxMsgFull = 0;
607 noddan 233
        }
332 eqlazer 234
    }
179 eqlazer 235
}
344 eqlazer 236
 
237
void send_dimensions(){
463 eqlazer 238
    Can_Message_t txMsg;
481 eqlazer 239
 
463 eqlazer 240
    txMsg.ExtendedFlag=1;
241
    txMsg.RemoteFlag=0;
344 eqlazer 242
    txMsg.Id=0xA000001;
243
    txMsg.Data.bytes[0] = SIZE_X;
244
    txMsg.Data.bytes[1] = SIZE_Y;
245
    txMsg.DataLength = 2;
481 eqlazer 246
 
463 eqlazer 247
    BIOS_CanSend(&txMsg);
344 eqlazer 248
}
481 eqlazer 249
 
250
void rotenc(){
251
    uint8_t rot_data = 0;
627 noddan 252
    static uint8_t rot_lastdir = 0, rot_laststate = 0, btn_laststate = 0;
481 eqlazer 253
 
254
    Can_Message_t txMsg;
255
    txMsg.ExtendedFlag=1;
256
    txMsg.RemoteFlag=0;
605 noddan 257
    //txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x01<<SNS_ID_BITS )| NODE_ID;//FIXME: borttaget
481 eqlazer 258
    txMsg.DataLength=2;
259
 
627 noddan 260
    //Take care of button push
261
    if ((PINB&(1<<PB7)) != btn_laststate){ //The buttonstate has changed! Let's send a message!
262
        btn_laststate = (PINB&(1<<PB7));
263
        txMsg.Data.bytes[0] = 5;
264
        txMsg.Data.bytes[1] = (btn_laststate)?0:1;
265
        txMsg.DataLength=2;
266
        BIOS_CanSend(&txMsg);
267
    }
268
 
269
    //Take care of rotary encoder movement
481 eqlazer 270
    if(PINB&(1<<PB0)){
271
        rot_data |= 0x01;
272
    }
273
    if(PIND&(1<<PD2)){
274
        rot_data |= 0x02;
275
    }
276
 
627 noddan 277
    if( rot_data==0 || rot_data==3 ){ // Are both signals high or low?
278
        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. 
481 eqlazer 279
            if( rot_lastdir&0x01 ){
280
                // Moving right
281
                txMsg.Data.bytes[0]=RIGHT;
282
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
283
                txMsg.DataLength=2;
284
                BIOS_CanSend(&txMsg);
285
            }else{
286
                // Moving left
287
                txMsg.Data.bytes[0]=LEFT;
288
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
289
                txMsg.DataLength=2;
290
                BIOS_CanSend(&txMsg);
291
            }
292
        }
293
        rot_laststate = rot_data;
627 noddan 294
    } else { // No, only one of the signals are high. We can use this to find out what direction we are moving.
481 eqlazer 295
        rot_lastdir = rot_data;
296
    }
297
}
298