Subversion Repositories HomeAutomation

Rev

Rev 631 | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | SVN | RSS feed

Rev 631 Rev 636
1
/**
1
/**
2
 * CanEggWatch. Currenty only supports nodeCLCD, this will probably change since I want 7-segments in the long run.
2
 * CanEggWatch. Currenty only supports nodeCLCD, this will probably change since I want 7-segments in the long run.
3
 * Hardware: http://projekt.auml.se/homeautomation:hardware:avr:clcd
3
 * Hardware: http://projekt.auml.se/homeautomation:hardware:avr:clcd
4
 * TODO: Sending messages to report status, cleanup, graphical bar, nicer GUI, multiple timers
4
 * TODO: Sending messages to report status, cleanup, graphical bar, nicer GUI, multiple timers
5
 *
5
 *
6
 *
6
 *
7
 * @date    2007-09-09
7
 * @date    2007-09-09
8
 * @author  Martin Norden
8
 * @author  Martin Norden
9
 *
9
 *
10
 */
10
 */
11
 
11
 
12
/*-----------------------------------------------------------------------------
12
/*-----------------------------------------------------------------------------
13
 * Includes
13
 * Includes
14
 *---------------------------------------------------------------------------*/
14
 *---------------------------------------------------------------------------*/
15
/* system files */
15
/* system files */
16
#include <avr/io.h>
16
#include <avr/io.h>
17
#include <inttypes.h>
17
#include <inttypes.h>
18
#include <avr/interrupt.h>
18
#include <avr/interrupt.h>
19
#include <stdio.h>
19
#include <stdio.h>
20
/* lib files */
20
/* lib files */
21
#include <bios.h>
21
#include <bios.h>
22
#include <config.h>
22
#include <config.h>
23
#include <drivers/lcd/clcd/lcd_HD44780.h>
23
#include <drivers/lcd/clcd/lcd_HD44780.h>
24
#include <drivers/timer/timebase.h>
24
#include <drivers/timer/timebase.h>
25
 
25
 
26
 
26
 
27
#include <string.h> //for memcpy
27
#include <string.h> //for memcpy
28
#include <stdlib.h> //for itoa
28
#include <stdlib.h> //for itoa
29
 
29
 
30
 
30
 
31
/*-----------------------------------------------------------------------------
31
/*-----------------------------------------------------------------------------
32
 * Defines
32
 * Defines
33
 *---------------------------------------------------------------------------*/
33
 *---------------------------------------------------------------------------*/
34
#define SIZE_X  20
34
#define SIZE_X  20
35
#define SIZE_Y  4
35
#define SIZE_Y  4
36
#define SIZE_LCD LCD_SIZE_20x4
36
#define SIZE_LCD LCD_SIZE_20x4
37
 
37
 
38
#define BUFFER_SIZE SIZE_X
38
#define BUFFER_SIZE SIZE_X
39
#define TRUE 1
39
#define TRUE 1
40
#define FALSE 0
40
#define FALSE 0
41
 
41
 
42
#define LEFT    0x01
42
#define LEFT    0x01
43
#define RIGHT   0x02
43
#define RIGHT   0x02
44
#define BUTTON_PUSH 0x03
44
#define BUTTON_PUSH 0x03
45
#define BUTTON_RELEASE 0x04
45
#define BUTTON_RELEASE 0x04
46
 
46
 
47
volatile Can_Message_t rxMsg;
47
volatile Can_Message_t rxMsg;
48
 
48
 
49
char incoming_text[ BUFFER_SIZE ];
49
char incoming_text[ BUFFER_SIZE ];
50
uint8_t rxMsgFull;
50
uint8_t rxMsgFull;
51
 
51
 
52
 
52
 
53
char buffer[ BUFFER_SIZE ];
53
char buffer[ BUFFER_SIZE ];
54
 
54
 
55
void send_dimensions(void);
55
void send_dimensions(void);
56
void rotenc(void);
56
void rotenc(void);
57
void action(uint8_t type);
57
void action(uint8_t type);
58
void alarm(void);
58
void alarm(void);
-
 
59
void refreshDisplay(void);
59
 
60
 
60
uint32_t timeBase = 0;
61
uint32_t timeBase = 0;
61
uint16_t timerVar= 0;
-
 
62
uint8_t alarmTimer = 0;
-
 
63
 
62
 
64
char lcdBuffer[5];
63
char lcdBuffer[5];
-
 
64
 
-
 
65
//Struct for countdown
-
 
66
typedef struct
-
 
67
{
-
 
68
    uint16_t timerCnt;
-
 
69
    uint8_t alarmTimer;
-
 
70
    uint16_t timerMax;
-
 
71
} countDown;
-
 
72
 
-
 
73
countDown countTimer1;
-
 
74
 
65
 
75
 
66
// CAN message reception callback
76
// CAN message reception callback
67
// This function runs with interrupts disabled, keep it as short as possible
77
// This function runs with interrupts disabled, keep it as short as possible
68
void can_receive(Can_Message_t *msg){
78
void can_receive(Can_Message_t *msg){
69
    if(!rxMsgFull){
79
    if(!rxMsgFull){
70
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
80
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
71
        rxMsgFull = 1;
81
        rxMsgFull = 1;
72
    }
82
    }
73
}
83
}
74
 
84
 
75
ISR( PCINT2_vect ){
85
ISR( PCINT2_vect ){
76
// For ROTENC_A and ROTENC_B FIXME Šr inte riktigt rŠtt. Verkar vara bra tycker jag?
86
// For ROTENC_A and ROTENC_B FIXME Šr inte riktigt rŠtt. Verkar vara bra tycker jag?
77
    rotenc();
87
    rotenc();
78
}
88
}
79
 
89
 
80
ISR( PCINT0_vect ){
90
ISR( PCINT0_vect ){
81
// For ROTENC_BTN
91
// For ROTENC_BTN
82
    rotenc();
92
    rotenc();
83
}
93
}
84
 
94
 
85
/*-----------------------------------------------------------------------------
95
/*-----------------------------------------------------------------------------
86
 * Main Program
96
 * Main Program
87
 *---------------------------------------------------------------------------*/
97
 *---------------------------------------------------------------------------*/
88
int main(void) {
98
int main(void) {
89
//  uint32_t act; not used anymoer
99
//  uint32_t act; not used anymoer
90
//  uint8_t act_type, lcd_size; not used anymore
100
//  uint8_t act_type, lcd_size; not used anymore
91
//  uint8_t m, lcd_action; These are probably not needed now
101
//  uint8_t m, lcd_action; These are probably not needed now
92
 
102
 
93
    sei();
103
    sei();
94
   
104
   
95
    Timebase_Init();
105
    Timebase_Init();
96
 
106
 
97
    /*
107
    /*
98
     * Initialize rotaryencoders and buttons
108
     * Initialize rotaryencoders and buttons
99
     */
109
     */
100
    // Set as input
110
    // Set as input
101
    DDRD &= ~(1<<DDD2);
111
    DDRD &= ~(1<<DDD2);
102
    DDRB &= ~((1<<DDB7)|(1<<DDB0));
112
    DDRB &= ~((1<<DDB7)|(1<<DDB0));
103
    // Enable pull-up
113
    // Enable pull-up
104
    PORTD |= (1<<PD2);
114
    PORTD |= (1<<PD2);
105
    PORTB |= (1<<PB7)|(1<<PB0);
115
    PORTB |= (1<<PB7)|(1<<PB0);
106
    // Enable IO-pin interrupt
116
    // Enable IO-pin interrupt
107
    PCICR |= (1<<PCIE2)|(1<<PCIE0);
117
    PCICR |= (1<<PCIE2)|(1<<PCIE0);
108
    // Unmask PB7, PB0 and PD2
118
    // Unmask PB7, PB0 and PD2
109
    PCMSK2 |= (1<<PCINT18);
119
    PCMSK2 |= (1<<PCINT18);
110
    PCMSK0 |= (1<<PCINT7)|(1<<PCINT0);
120
    PCMSK0 |= (1<<PCINT7)|(1<<PCINT0);
111
 
121
 
112
    // Contrast
122
    // Contrast
113
    TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
123
    TCCR0A |= (1<<COM0B1)|(1<<WGM01)|(1<<WGM00);
114
    TCCR0B |= (1<<CS00);
124
    TCCR0B |= (1<<CS00);
115
    OCR0B = 0x10;
125
    OCR0B = 0x10;
116
    DDRD |= (1<<DDD5);
126
    DDRD |= (1<<DDD5);
117
 
127
 
118
    // Backlight
128
    // Backlight
119
    TCCR1A |= (1<<COM1A1)|(1<<WGM11);
129
    TCCR1A |= (1<<COM1A1)|(1<<WGM11);
120
    TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
130
    TCCR1B |= (1<<WGM13)|(1<<WGM12)|(1<<CS10);
121
    ICR1 = 0xFF; // Make it 8 bits
131
    ICR1 = 0xFF; // Make it 8 bits
122
    OCR1A = 0xFF;
132
    OCR1A = 0xFF;
123
    DDRB |= (1<<DDB1);
133
    DDRB |= (1<<DDB1);
124
 
134
 
125
 
135
 
126
    Can_Message_t txMsg;
136
    Can_Message_t txMsg;
127
    txMsg.ExtendedFlag=1;
137
    txMsg.ExtendedFlag=1;
128
    txMsg.RemoteFlag=0;
138
    txMsg.RemoteFlag=0;
129
// FIXME skicka app startad
139
// FIXME skicka app startad
130
    BIOS_CanCallback = &can_receive;
140
    BIOS_CanCallback = &can_receive;
131
 
141
 
132
    lcd_init( LCD_DISP_ON );
142
    lcd_init( LCD_DISP_ON );
133
    lcd_clrscr();
143
    lcd_clrscr();
134
    lcd_puts("EggWatch\n");
144
    lcd_puts("CanEggWatch\n");
135
 
145
 
136
    send_dimensions();
146
    send_dimensions();
137
    lcd_puts("CAN Connected!\n");
147
    lcd_puts("CAN Connected!\n");
-
 
148
   
-
 
149
    lcd_clrscr();
-
 
150
   
138
 
151
 
139
    /* main loop */
152
    /* main loop */
140
    while(1){
153
    while(1){
141
       
154
       
142
       
155
       
143
        if( Timebase_PassedTimeMillis(timeBase) >= 1000 ){
156
        if( Timebase_PassedTimeMillis(timeBase) >= 1000 ){
144
            if (timerVar != 0){
157
            if (countTimer1.timerCnt != 0){
145
                timerVar--;
158
                countTimer1.timerCnt--;
146
                lcd_clrscr();
159
                refreshDisplay();
147
                itoa(timerVar/60,lcdBuffer,10);
-
 
148
                lcd_puts(lcdBuffer);
-
 
149
                lcd_puts(":");
-
 
150
                itoa(timerVar%60,lcdBuffer,10);
-
 
151
                lcd_puts(lcdBuffer);
-
 
152
            } else {
160
            } else {
153
                if (alarmTimer != 0){
161
                if (countTimer1.alarmTimer != 0){
154
                    alarm();
162
                    alarm();
155
                    alarmTimer--;
163
                    countTimer1.alarmTimer--;
156
                }
164
                }
157
            }
165
            }
158
            timeBase =  Timebase_CurrentTime();
166
            timeBase =  Timebase_CurrentTime();
159
        }
167
        }
160
       
168
       
161
       
169
       
162
        /* check if any messages have been received */
170
        /* check if any messages have been received */
163
        if(rxMsgFull){
171
        if(rxMsgFull){
164
            //Throw it away. We don't use them yet. TODO: Support for time and remote setting.
172
            //Throw it away. We don't use them yet. TODO: Support for time and remote setting.
165
            rxMsgFull = 0;
173
            rxMsgFull = 0;
166
        }
174
        }
167
    }
175
    }
168
}
176
}
169
 
177
 
170
void send_dimensions(){
178
void send_dimensions(){
171
    Can_Message_t txMsg;
179
    Can_Message_t txMsg;
172
 
180
 
173
    txMsg.ExtendedFlag=1;
181
    txMsg.ExtendedFlag=1;
174
    txMsg.RemoteFlag=0;
182
    txMsg.RemoteFlag=0;
175
    txMsg.Id=0xA000001;
183
    txMsg.Id=0xA000001;
176
    txMsg.Data.bytes[0] = SIZE_X;
184
    txMsg.Data.bytes[0] = SIZE_X;
177
    txMsg.Data.bytes[1] = SIZE_Y;
185
    txMsg.Data.bytes[1] = SIZE_Y;
178
    txMsg.DataLength = 2;
186
    txMsg.DataLength = 2;
179
 
187
 
180
    BIOS_CanSend(&txMsg);
188
    BIOS_CanSend(&txMsg);
181
}
189
}
182
 
190
 
183
void rotenc(){
191
void rotenc(){
184
    uint8_t rot_data = 0;
192
    uint8_t rot_data = 0;
185
    static uint8_t rot_lastdir = 0, rot_laststate = 0, btn_laststate = 0;
193
    static uint8_t rot_lastdir = 0, rot_laststate = 0, btn_laststate = 0;
186
 
194
 
187
    Can_Message_t txMsg;
195
    Can_Message_t txMsg;
188
    txMsg.ExtendedFlag=1;
196
    txMsg.ExtendedFlag=1;
189
    txMsg.RemoteFlag=0;
197
    txMsg.RemoteFlag=0;
190
    //txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x01<<SNS_ID_BITS )| NODE_ID;//FIXME: borttaget
198
    //txMsg.Id = ( CLASS_SNS<<CLASS_MASK_BITS )|( SNS_ACT_BUTTON<<SNS_TYPE_BITS )|( 0x01<<SNS_ID_BITS )| NODE_ID;//FIXME: borttaget
191
    txMsg.DataLength=2;
199
    txMsg.DataLength=2;
192
 
200
 
193
    //Take care of button push
201
    //Take care of button push
194
    if ((PINB&(1<<PB7)) != btn_laststate){ //The buttonstate has changed! Let's send a message!
202
    if ((PINB&(1<<PB7)) != btn_laststate){ //The buttonstate has changed! Let's send a message!
195
        btn_laststate = (PINB&(1<<PB7));
203
        btn_laststate = (PINB&(1<<PB7));
196
        txMsg.Data.bytes[0] = 5;
204
        txMsg.Data.bytes[0] = 5;
197
        txMsg.Data.bytes[1] = (btn_laststate)?0:1;
205
        txMsg.Data.bytes[1] = (btn_laststate)?0:1;
198
        txMsg.DataLength=2;
206
        txMsg.DataLength=2;
199
        BIOS_CanSend(&txMsg);
207
        BIOS_CanSend(&txMsg);
200
        action((btn_laststate)?BUTTON_RELEASE:BUTTON_PUSH);
208
        action((btn_laststate)?BUTTON_RELEASE:BUTTON_PUSH);
201
    }
209
    }
202
   
210
   
203
    //Take care of rotary encoder movement
211
    //Take care of rotary encoder movement
204
    if(PINB&(1<<PB0)){
212
    if(PINB&(1<<PB0)){
205
        rot_data |= 0x01;
213
        rot_data |= 0x01;
206
    }
214
    }
207
    if(PIND&(1<<PD2)){
215
    if(PIND&(1<<PD2)){
208
        rot_data |= 0x02;
216
        rot_data |= 0x02;
209
    }
217
    }
210
 
218
 
211
    if( rot_data==0 || rot_data==3 ){ // Are both signals high or low?
219
    if( rot_data==0 || rot_data==3 ){ // Are both signals high or low?
212
        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. 
220
        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. 
213
            if( rot_lastdir&0x01 ){
221
            if( rot_lastdir&0x01 ){
214
                // Moving right
222
                // Moving right
215
                txMsg.Data.bytes[0]=RIGHT;
223
                txMsg.Data.bytes[0]=RIGHT;
216
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
224
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
217
                txMsg.DataLength=2;
225
                txMsg.DataLength=2;
218
                BIOS_CanSend(&txMsg);
226
                BIOS_CanSend(&txMsg);
219
                action(RIGHT);
227
                action(RIGHT);
220
            }else{
228
            }else{
221
                // Moving left
229
                // Moving left
222
                txMsg.Data.bytes[0]=LEFT;
230
                txMsg.Data.bytes[0]=LEFT;
223
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
231
                txMsg.Data.bytes[1] = (PINB&(1<<PB7))?0:1;
224
                txMsg.DataLength=2;
232
                txMsg.DataLength=2;
225
                BIOS_CanSend(&txMsg);
233
                BIOS_CanSend(&txMsg);
226
                action(LEFT);
234
                action(LEFT);
227
            }
235
            }
228
        }
236
        }
229
        rot_laststate = rot_data;
237
        rot_laststate = rot_data;
230
    } else { // No, only one of the signals are high. We can use this to find out what direction we are moving.
238
    } else { // No, only one of the signals are high. We can use this to find out what direction we are moving.
231
        rot_lastdir = rot_data;
239
        rot_lastdir = rot_data;
232
    }
240
    }
233
}
241
}
234
 
242
 
235
void action(uint8_t type){
243
void action(uint8_t type){
236
    //Let's do something with something!
244
    //Let's do something with something!
237
    lcd_clrscr();
245
    lcd_clrscr();
238
    if (type == LEFT){
246
    if (type == LEFT){
239
        timerVar--;
247
        countTimer1.timerCnt--;
240
        lcd_clrscr();
248
        refreshDisplay();
241
        itoa(timerVar/60,lcdBuffer,10);
-
 
242
        lcd_puts(lcdBuffer);
-
 
243
        lcd_puts(":");
-
 
244
        itoa(timerVar%60,lcdBuffer,10);
-
 
245
        lcd_puts(lcdBuffer);
-
 
246
    }
249
    }
247
    if (type == RIGHT){
250
    if (type == RIGHT){
248
        timerVar++;
251
        countTimer1.timerCnt++;
249
        lcd_clrscr();
-
 
250
        itoa(timerVar/60,lcdBuffer,10);
252
        if  (countTimer1.timerCnt > countTimer1.timerMax){
251
        lcd_puts(lcdBuffer);
253
            countTimer1.timerMax = countTimer1.timerCnt;
252
        lcd_puts(":");
254
        }
253
        itoa(timerVar%60,lcdBuffer,10);
-
 
254
        lcd_puts(lcdBuffer);
255
        refreshDisplay();
255
    }
256
    }
256
    if (type == BUTTON_PUSH){
257
    if (type == BUTTON_PUSH){
257
        lcd_puts("Init!");
258
        lcd_puts("Init!");
258
    }
259
    }
259
    if (type == BUTTON_RELEASE){
260
    if (type == BUTTON_RELEASE){
260
        timeBase = Timebase_CurrentTime();
261
        timeBase = Timebase_CurrentTime();
-
 
262
        countTimer1.timerCnt = 10;
261
        timerVar = 10;
263
        countTimer1.timerMax = 10;
262
        alarmTimer = 1;
264
        countTimer1.alarmTimer = 1;
-
 
265
        refreshDisplay();
263
    }
266
    }
264
}
267
}
265
 
268
 
266
void alarm(void){
269
void alarm(void){
267
    lcd_puts("Riing!");
270
    lcd_puts("Riing!");
-
 
271
}
-
 
272
 
-
 
273
void refreshDisplay(void){
-
 
274
    lcd_clrscr();
-
 
275
    itoa(countTimer1.timerCnt/60,lcdBuffer,10);
-
 
276
    lcd_puts(lcdBuffer);
-
 
277
    lcd_puts(":");
-
 
278
    itoa(countTimer1.timerCnt%60,lcdBuffer,10);
-
 
279
    lcd_puts(lcdBuffer);
-
 
280
   
-
 
281
    lcd_gotoxy(0,1);
-
 
282
    lcdProgressBar(countTimer1.timerCnt,countTimer1.timerMax,16);  
268
}
283
}
269
 
284