Subversion Repositories HomeAutomation

Rev

Details | Last modification | View Log | SVN | RSS feed

Rev Author Line No. Line
919 zeed 1
#include <inttypes.h>
2
#include <avr/interrupt.h>
3
#include <stdio.h>
4
#include <string.h>
5
#include <config.h> // All configuration parameters
6
#include <bios.h>   // BIOS interface declarations, including CAN structure and ID defines.
7
#include <drivers/timer/timebase.h>
8
#include <drivers/ir/transceiver/irtransceiver.h>
9
#include <drivers/ir/protocols.h>
10
 
11
//Transmitter
12
#define APP_TYPE_TRANSMIT    CAN_APPTYPES_IRTRANSMITTER
13
#define APP_VERSION_TRANSMIT 0x0002
14
 
15
#define STATE_IDLE_TRANSMIT             0
16
#define STATE_START_TRANSMIT    1
17
#define STATE_TRANSMITTING      2
18
#define STATE_START_PAUSE_TRANSMIT      3
19
#define STATE_PAUSING_TRANSMIT          4
20
#define STATE_STOP_TRANSMIT             5
21
 
22
 
23
//Receiver
24
#define APP_TYPE_RECEIVE    CAN_APPTYPES_IRRECEIVER
25
#define APP_VERSION_RECEIVE 0x0004
26
 
27
#define STATE_IDLE_RECEIVE          0
28
#define STATE_IR_REPEAT_RECEIVE     1
29
#define STATE_START_RECEIVE 2
30
#define STATE_RECEIVING     3
31
#define STATE_START_PAUSE_RECEIVE   4
32
#define STATE_PAUSING_RECEIVE       5
33
#define STATE_START_IDLE_RECEIVE    6
34
 
35
#define IR_ID_DATA  0
36
#define IR_ID_RAW   1
37
#define IR_ID_DEBUG 10
38
 
39
 
40
// A simple message "queue", with space for one message only.
41
// These are declared volatile to tell the compiler not to optimize away accesses.
42
volatile Can_Message_t rxMsg; // Message storage
43
volatile uint8_t rxMsgFull;   // Synchronization flag
44
 
45
// CAN message reception callback.
46
// This function runs with interrupts disabled, keep it as short as possible.
47
void can_receive(Can_Message_t *msg) {
48
    if (!rxMsgFull) {
49
        memcpy((void*)&rxMsg, msg, sizeof(rxMsg));
50
        rxMsgFull = 1;
51
    }
52
}
53
 
54
#if (SEND_DEBUG)
55
void send_debug(uint16_t *buffer, uint8_t len) {
56
    Can_Message_t txMsg;
57
 
58
    /* the protocol is unknown so the raw ir-data is sent, makes it easier to develop a new protocol */
59
    txMsg.DataLength = 8;
60
    txMsg.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_IR << CAN_SHIFT_SNS_TYPE) | (IR_ID_RAW<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
61
    for (uint8_t i = 0; i < len>>2; i++) {
62
        uint8_t index = i<<2;
63
        txMsg.Data.bytes[0] = (buffer[index]>>8)&0xff;
64
        txMsg.Data.bytes[1] = (buffer[index]>>0)&0xff;
65
        txMsg.Data.bytes[2] = (buffer[index+1]>>8)&0xff;
66
        txMsg.Data.bytes[3] = (buffer[index+1]>>0)&0xff;
67
        txMsg.Data.bytes[4] = (buffer[index+2]>>8)&0xff;
68
        txMsg.Data.bytes[5] = (buffer[index+2]>>0)&0xff;
69
        txMsg.Data.bytes[6] = (buffer[index+3]>>8)&0xff;
70
        txMsg.Data.bytes[7] = (buffer[index+3]>>0)&0xff;
71
 
72
        /* buffers will be filled when sending more than 2-3 messages, so retry until sent */
73
        //while (BIOS_CanSend(&txMsg) != CAN_OK) {}
74
        BIOS_CanSend(&txMsg);
75
 
76
        uint16_t dummycnt = 1;
77
        while (dummycnt > 0) {
78
            dummycnt++;
79
            asm("nop");
80
            asm("nop");
81
        }
82
    }
83
 
84
    uint8_t lastpacketcnt = len&0x03;
85
    if (lastpacketcnt > 0) {
86
        txMsg.DataLength = lastpacketcnt<<1;
87
        for (uint8_t i = 0; i < lastpacketcnt; i++) {
88
            txMsg.Data.bytes[i<<1] = (buffer[(len&0xfc)|i]>>8)&0xff;
89
            txMsg.Data.bytes[(i<<1)+1] = (buffer[(len&0xfc)|i]>>0)&0xff;
90
        }
91
        /* buffers will be filled when sending more than 2-3 messages, so retry until sent */
92
        //while (BIOS_CanSend(&txMsg) != CAN_OK) {}
93
        BIOS_CanSend(&txMsg);
94
    }
95
 
96
}
97
#endif
98
 
99
int main(void)
100
{
101
    // Enable interrupts as early as possible
102
    sei();
103
 
104
    Timebase_Init();
105
    IrTransceiver_Init();
106
 
107
    Can_Message_t txMsg_receive;
108
    txMsg_receive.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) |
109
        (NODE_ID << CAN_SHIFT_NMT_SID);
110
    txMsg_receive.DataLength = 4;
111
    txMsg_receive.RemoteFlag = 0;
112
    txMsg_receive.ExtendedFlag = 1;
113
    txMsg_receive.Data.words[0] = APP_TYPE_RECEIVE;
114
    txMsg_receive.Data.words[1] = APP_VERSION_RECEIVE;
115
 
116
    // We will pretend to be two applications
117
    Can_Message_t txMsg_transmit;
118
    txMsg_transmit.Id = (CAN_NMT_APP_START << CAN_SHIFT_NMT_TYPE) |
119
        (NODE_ID << CAN_SHIFT_NMT_SID);
120
    txMsg_transmit.DataLength = 4;
121
    txMsg_transmit.RemoteFlag = 0;
122
    txMsg_transmit.ExtendedFlag = 1;
123
    txMsg_transmit.Data.words[0] = APP_TYPE_TRANSMIT;
124
    txMsg_transmit.Data.words[1] = APP_VERSION_TRANSMIT;
125
 
126
    // Set up callback for CAN reception, this is optional if only sending is required.
127
    BIOS_CanCallback = &can_receive;
128
    // Send CAN_NMT_APP_START for the receiver part, this is first since
129
    // we don't send commands to it
130
    BIOS_CanSend(&txMsg_receive);
131
 
132
    // Send CAN_NMT_APP_START for the transmitter part aswell
133
    BIOS_CanSend(&txMsg_transmit);
134
 
135
    uint32_t time = Timebase_CurrentTime();
136
    uint32_t timePauseStarted_transmit = 0;
137
    uint32_t timePauseStarted_receive = 0;
138
 
139
    // Transmitter
140
    uint8_t state_transmit=STATE_IDLE_TRANSMIT;
141
    uint8_t repeatcnt_transmit=0;
142
    uint8_t stop_transmit=0;
143
 
144
    Ir_Protocol_Data_t proto_transmit;
145
    proto_transmit.timeout=0;
146
    proto_transmit.data=0;
147
    proto_transmit.repeats=0;
148
    proto_transmit.protocol=0;
149
    proto_transmit.framecnt = 0;
150
 
151
    uint8_t len_transmit=0;
152
 
153
    uint16_t txbuffer[MAX_NR_TIMES];
154
 
155
    //Receiver
156
    uint8_t state_receive = STATE_IDLE_RECEIVE;
157
 
158
    Ir_Protocol_Data_t proto_receive;
159
    proto_receive.timeout=0;
160
    proto_receive.data=0;
161
    proto_receive.repeats=0;
162
    proto_receive.protocol=0;
163
 
164
    uint8_t len_receive=0;
165
 
166
    uint16_t rxbuffer[MAX_NR_TIMES];
167
 
168
    while (1) {
169
 
170
    //Transmitter
171
        if (state_transmit == STATE_IDLE_TRANSMIT) {
172
        }
173
        else if (state_transmit == STATE_START_TRANSMIT) {
174
            if (expandProtocol(txbuffer, &len_transmit, &proto_transmit) == IR_OK) {
175
                if (IrTransceiver_Transmit(txbuffer,
176
                    len_transmit, proto_transmit.modfreq) == IR_OK) {
177
                    state_transmit = STATE_TRANSMITTING;
178
                } else {
179
                    state_transmit = STATE_IDLE_TRANSMIT;
180
                }
181
            } else {
182
                state_transmit = STATE_IDLE_TRANSMIT;
183
            }
184
        } else if (state_transmit == STATE_TRANSMITTING) {
185
            //polla om den är klar, om klar gå till STATE_START_PAUSE
186
            if (IrTransceiver_Transmit_Poll() != IR_NOT_FINISHED) {
187
                state_transmit = STATE_START_PAUSE_TRANSMIT;
188
            }
189
        } else if (state_transmit == STATE_START_PAUSE_TRANSMIT) {
190
            if (repeatcnt_transmit<proto_transmit.repeats) {
191
                repeatcnt_transmit++;
192
            }
193
            timePauseStarted_transmit = Timebase_CurrentTime();
194
            if (proto_transmit.framecnt != 255) {
195
                proto_transmit.framecnt++;
196
            }
197
            state_transmit = STATE_PAUSING_TRANSMIT;
198
        } else if (state_transmit == STATE_PAUSING_TRANSMIT) {
199
            //när timeout har gått (timebase) så gå till STATE_START_TRANSMIT
200
            time = Timebase_CurrentTime();
201
            if (time - timePauseStarted_transmit >= proto_transmit.timeout) {
202
                state_transmit = STATE_START_TRANSMIT;
203
            }
204
            if (stop_transmit == 1 && repeatcnt_transmit >= proto_transmit.repeats) {
205
                state_transmit = STATE_STOP_TRANSMIT;
206
            }
207
        } else if (state_transmit == STATE_STOP_TRANSMIT) {
208
            stop_transmit = 0;
209
            proto_transmit.timeout = 0;
210
            proto_transmit.framecnt = 0;
211
            repeatcnt_transmit = 0;
212
            state_transmit = STATE_IDLE_TRANSMIT;
213
        }
214
 
215
        if (rxMsgFull) {
216
            if ( ((rxMsg.Id & CAN_MASK_CLASS)>>CAN_SHIFT_CLASS) == CAN_ACT) {
217
                uint16_t acttype =(uint16_t)((rxMsg.Id & CAN_MASK_ACT_TYPE) >> CAN_SHIFT_ACT_TYPE);
218
                uint8_t actid = (uint8_t)((rxMsg.Id & CAN_MASK_ACT_ID) >> CAN_SHIFT_ACT_ID);
219
 
220
                if (rxMsg.DataLength==6) {
221
                    if (acttype == ACT_TYPE_IR) {
222
                        if (state_transmit == STATE_IDLE_TRANSMIT && rxMsg.Data.bytes[0] == IR_BUTTON_DOWN) {
223
                            proto_transmit.protocol = rxMsg.Data.bytes[1];
224
                            proto_transmit.data = rxMsg.Data.bytes[5];
225
                            proto_transmit.data |= (rxMsg.Data.bytes[4]<<8);
226
                            proto_transmit.data |= ((uint32_t)rxMsg.Data.bytes[3]<<16);
227
                            proto_transmit.data |= ((uint32_t)rxMsg.Data.bytes[2]<<24);
228
 
229
                            state_transmit = STATE_START_TRANSMIT;
230
                        } else if (state_transmit != STATE_IDLE_TRANSMIT && rxMsg.Data.bytes[0] == IR_BUTTON_UP) {
231
                            stop_transmit = 1;
232
                        }
233
                    }
234
                }
235
            }
236
 
237
            // Flush the received message
238
            rxMsgFull = 0; //  
239
        }
240
 
241
        //Receiver          
242
        if (state_receive == STATE_IDLE_RECEIVE) {
243
            IrTransceiver_Receive_Start(rxbuffer);
244
            state_receive = STATE_START_RECEIVE;
245
        } else if (state_receive == STATE_START_RECEIVE) {
246
            state_receive = STATE_RECEIVING;
247
        } else if (state_receive == STATE_RECEIVING) {
248
            uint8_t res = IrTransceiver_Receive_Poll(&len_receive);
249
            if ((res == IR_OK) && (len_receive > 0)) {
250
                //låt protocols parsa och skicka på can
922 zeed 251
#if !(SEND_DEBUG)
919 zeed 252
                uint8_t res2 = parseProtocol(rxbuffer, len_receive, &proto_receive);
253
                if (res2 == IR_OK && proto_receive.protocol != IR_PROTO_UNKNOWN) {
254
                    txMsg_receive.Data.bytes[0] = IR_BUTTON_DOWN;
255
                    txMsg_receive.Data.bytes[1] = proto_receive.protocol;
256
                    txMsg_receive.Data.bytes[2] = (proto_receive.data>>24)&0xff;
257
                    txMsg_receive.Data.bytes[3] = (proto_receive.data>>16)&0xff;
258
                    txMsg_receive.Data.bytes[4] = (proto_receive.data>>8)&0xff;
259
                    txMsg_receive.Data.bytes[5] = proto_receive.data&0xff;
260
                    txMsg_receive.Id = ((CAN_SNS << CAN_SHIFT_CLASS) | (SNS_TYPE_IR << CAN_SHIFT_SNS_TYPE) | (IR_ID_DATA<<CAN_SHIFT_SNS_ID) | (NODE_ID << CAN_SHIFT_SNS_SID));
261
                    txMsg_receive.DataLength = 6;
262
                    BIOS_CanSend(&txMsg_receive);
263
                } else if (proto_receive.protocol == IR_PROTO_UNKNOWN) {
922 zeed 264
                }
265
#endif
919 zeed 266
#if (SEND_DEBUG)
922 zeed 267
                send_debug(rxbuffer, len_receive);
268
                proto_receive.timeout=300;
919 zeed 269
#endif
922 zeed 270
 
919 zeed 271
                state_receive = STATE_START_PAUSE_RECEIVE;
272
            }
273
        } else if (state_receive == STATE_START_PAUSE_RECEIVE) {
274
            IrTransceiver_Receive_Start(rxbuffer);
275
            timePauseStarted_receive = Timebase_CurrentTime();
276
            state_receive = STATE_PAUSING_RECEIVE;
277
        } else if (state_receive == STATE_PAUSING_RECEIVE) {
278
            //resetta timebase-var om ir finns
279
            uint8_t res = IrTransceiver_Receive_Poll(&len_receive);
280
            if (res == IR_NOT_FINISHED || res == IR_OK) {
281
                timePauseStarted_receive = Timebase_CurrentTime();
282
            }
283
            if (res == IR_OK) {
284
                /* start a new reception */
285
                IrTransceiver_Receive_Start(rxbuffer);
286
            }
287
 
288
            time = Timebase_CurrentTime();
289
            if (time - timePauseStarted_receive >= proto_receive.timeout) {
290
                state_receive = STATE_START_IDLE_RECEIVE;
291
            }
292
        } else if (state_receive == STATE_START_IDLE_RECEIVE) {
293
            if (proto_receive.protocol != IR_PROTO_UNKNOWN) {
294
                //skicka på can
295
                txMsg_receive.Data.bytes[0] = IR_BUTTON_UP;
296
                BIOS_CanSend(&txMsg_receive);
297
            }
298
            state_receive = STATE_IDLE_RECEIVE;
299
        }
300
    }
301
 
302
    return 0;
303
}
304