Subversion Repositories HomeAutomation

Rev

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

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