Subversion Repositories HomeAutomation

Rev

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

Rev Author Line No. Line
610 arune 1
/**
2
 * IR receiver and transmitter protocols.
3
 *
4
 * @date    2006-12-10
5
 *
733 noddan 6
 * @author  Anders Runeson, Andreas Fritiofson, Martin NordŽn
610 arune 7
 *  
8
 */
9
 
608 arune 10
#include "protocols.h"
610 arune 11
 
608 arune 12
int8_t parseProtocol(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
610 arune 13
    proto->protocol=IR_PROTO_UNKNOWN;
14
    proto->data=0;
15
    proto->timeout=100;
608 arune 16
    /* Try all protocols in order. */
17
#if (IR_PROTOCOLS_USE_SIRC)
610 arune 18
    if (parseSIRC(buf, len, proto)==IR_OK) return IR_OK;
608 arune 19
#endif
20
#if (IR_PROTOCOLS_USE_RC5)
610 arune 21
    if (parseRC5(buf, len, proto)==IR_OK) return IR_OK;
608 arune 22
#endif
23
#if (IR_PROTOCOLS_USE_SHARP)
610 arune 24
    if (parseSharp(buf, len, proto)==IR_OK) return IR_OK;
608 arune 25
#endif
26
#if (IR_PROTOCOLS_USE_NEC)
610 arune 27
    if (parseNEC(buf, len, proto)==IR_OK) return IR_OK;
608 arune 28
#endif
29
#if (IR_PROTOCOLS_USE_SAMSUNG)
610 arune 30
    if (parseSamsung(buf, len, proto)==IR_OK) return IR_OK;
608 arune 31
#endif
732 noddan 32
#if (IR_PROTOCOLS_USE_MARANTZ)
33
    if (parseMarantz(buf, len, proto)==IR_OK) return IR_OK;
34
#endif
608 arune 35
    /* No protocol matched. */
610 arune 36
    proto->protocol = IR_PROTO_UNKNOWN;
608 arune 37
    return IR_NOT_CORRECT_DATA;
38
}
39
 
40
int8_t parseHash(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
41
    //TODO: Transform the buffer in some clever way to a 32 bit word. */
42
    proto->protocol = IR_PROTO_HASH;
610 arune 43
    proto->timeout = 200;
608 arune 44
    proto->data = 0;
45
 
46
    return 0;
47
}
48
 
49
int8_t expandProtocol(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
50
    /* Call the expand function for the specified protocol. */
51
    switch (proto->protocol) {
52
    case IR_PROTO_SIRC:
53
        return expandSIRC(buf, len, proto);
54
    case IR_PROTO_RC5:
55
        return expandRC5(buf, len, proto);
56
    case IR_PROTO_SHARP:
57
        return expandSharp(buf, len, proto);
58
    case IR_PROTO_NEC:
59
        return expandNEC(buf, len, proto);
60
    case IR_PROTO_SAMS:
61
        return expandSamsung(buf, len, proto);
732 noddan 62
    case IR_PROTO_MARANTZ:
63
        return expandMarantz(buf, len, proto);
608 arune 64
    }
65
    /* Invalid protocol specified. */
66
    return IR_NOT_CORRECT_DATA;
67
}
68
 
69
#if (IR_PROTOCOLS_USE_SIRC)
70
/**
71
 * Test data on SIRC protocol, 12-bit version
72
 * http://www.sbprojects.com/knowledge/ir/sirc.htm
73
 *
610 arune 74
 * @param buf
75
 *      Pointer to buffer to where to data to parse is stored
76
 * @param len
77
 *      Length of the data
78
 * @param proto
79
 *      Pointer to protocol information
608 arune 80
 * @return
81
 *      IR_OK if data parsed successfully, one of several errormessages if not
82
 */
83
int8_t parseSIRC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
84
    /* parse buf[], max is len */
85
 
86
    /* check if we have correct amount of data */
87
    if (len != 25) {
88
        return IR_NOT_CORRECT_DATA;
89
    }
90
 
91
    /* check startbit */
92
    if (buf[0] > IR_SIRC_ST_BIT + IR_SIRC_ST_BIT/IR_SIRC_TOL_DIV || buf[0] < IR_SIRC_ST_BIT - IR_SIRC_ST_BIT/IR_SIRC_TOL_DIV) {
93
        return IR_NOT_CORRECT_DATA;
94
    }
95
 
96
    uint16_t rawbits=0;
97
 
98
    for (uint8_t i = 1; i < len; i++) {
99
        if ((i&1) == 1) {       /* if odd, ir-pause */
100
            /* check length of pause between bits */
101
            if (buf[i] > IR_SIRC_LOW + IR_SIRC_LOW/IR_SIRC_TOL_DIV || buf[i] < IR_SIRC_LOW - IR_SIRC_LOW/IR_SIRC_TOL_DIV) {
102
                return IR_NOT_CORRECT_DATA;
103
            }
104
        } else {            /* if even, ir-bit */
105
            if (buf[i] > IR_SIRC_HIGH_ONE - IR_SIRC_HIGH_ONE/IR_SIRC_TOL_DIV && buf[i] < IR_SIRC_HIGH_ONE + IR_SIRC_HIGH_ONE/IR_SIRC_TOL_DIV) {
106
                /* write a one */
107
                rawbits |= 1<<((i-2)>>1);
108
            } else if (buf[i] > IR_SIRC_HIGH_ZERO - IR_SIRC_HIGH_ZERO/IR_SIRC_TOL_DIV && buf[i] < IR_SIRC_HIGH_ZERO + IR_SIRC_HIGH_ZERO/IR_SIRC_TOL_DIV) {
109
                /* do nothing, a zero is already in rawbits */
110
            } else {
111
                return IR_NOT_CORRECT_DATA;
112
            }
113
        }
114
    }
115
 
116
    proto->protocol = IR_PROTO_SIRC;
117
    proto->timeout = IR_SIRC_TIMEOUT;
610 arune 118
    proto->data = rawbits;
608 arune 119
 
120
    return IR_OK;
121
}
122
#endif
123
 
610 arune 124
/**
125
 * Expand data from SIRC protocol
126
 * http://www.sbprojects.com/knowledge/ir/sirc.htm
127
 *
128
 * @param buf
129
 *      Pointer to buffer to store the expanded data
130
 * @param len
131
 *      Pointer to length of the data
132
 * @param proto
133
 *      Pointer to protocol information
134
 * @return
135
 *      IR_OK if data expanded successfully, one of several errormessages if not
136
 */
608 arune 137
int8_t expandSIRC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
138
    //TODO: Implement this function.
734 noddan 139
    buf[0] = IR_SIRC_ST_BIT;
140
    buf[1] = IR_SIRC_LOW;//start pulse finished
141
 
142
 
143
 
608 arune 144
    return IR_NOT_CORRECT_DATA;
145
}
146
 
610 arune 147
 
608 arune 148
#if (IR_PROTOCOLS_USE_RC5)
149
/**
150
 * Test data on RC5 protocol
151
 * http://www.sbprojects.com/knowledge/ir/rc5.htm
152
 *
610 arune 153
 * @param buf
154
 *      Pointer to buffer to where to data to parse is stored
155
 * @param len
156
 *      Length of the data
157
 * @param proto
158
 *      Pointer to protocol information
608 arune 159
 * @return
160
 *      IR_OK if data parsed successfully, one of several errormessages if not
161
 */
162
int8_t parseRC5(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
163
    uint8_t halfbitscnt = 1;
164
    uint16_t rawbits = 0;
165
 
166
    for (uint8_t i = 0; i<len; i++) {
167
        //halfbitscnt&1==1 in the middle of bits
168
        //i&1==0 positive flank
169
 
170
        if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
171
            rawbits |= (1<<(13-(halfbitscnt>>1)));
172
        }
173
 
174
        if (buf[i] > IR_RC5_HALF_BIT - IR_RC5_HALF_BIT/IR_RC5_TOL_DIV && buf[i] < IR_RC5_HALF_BIT + IR_RC5_HALF_BIT/IR_RC5_TOL_DIV) {
175
            halfbitscnt += 1;
176
        } else if (buf[i] > IR_RC5_BIT - IR_RC5_BIT/IR_RC5_TOL_DIV && buf[i] < IR_RC5_BIT + IR_RC5_BIT/IR_RC5_TOL_DIV) {
177
            halfbitscnt += 2;
178
        } else {
179
            return IR_NOT_CORRECT_DATA;
180
        }
181
 
182
    }
183
 
184
    proto->protocol=IR_PROTO_RC5;
185
    proto->timeout=IR_RC5_TIMEOUT;
186
    //support RC5-extended keeping second startbit 
187
    //remove togglebit
732 noddan 188
    proto->data = rawbits&0x37ff; //This seems to be wrong? Does not invert second start bit and keeps first start bit
189
    //proto->data = (rawbits&0x07ff) | ((~rawbits)&0x0100);
608 arune 190
 
191
 
192
    return IR_OK;
193
}
194
#endif
195
 
610 arune 196
/**
197
 * Expand data from RC5 protocol
198
 * http://www.sbprojects.com/knowledge/ir/rc5.htm
199
 *
200
 * @param buf
201
 *      Pointer to buffer to store the expanded data
202
 * @param len
203
 *      Pointer to length of the data
204
 * @param proto
205
 *      Pointer to protocol information
206
 * @return
207
 *      IR_OK if data expanded successfully, one of several errormessages if not
208
 */
608 arune 209
int8_t expandRC5(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
727 noddan 210
    uint8_t tempadress;
211
    uint8_t tempcommand;
212
    uint8_t previousBit;
732 noddan 213
    uint16_t tempdata;
727 noddan 214
 
215
    /* Set up startbit */
216
    buf[0] = 0; // no start-one
217
    buf[1] = IR_RC5_HALF_BIT;
218
    buf[2] = IR_RC5_HALF_BIT;//first start bit
219
    buf[3] = IR_RC5_HALF_BIT;
220
    buf[4] = IR_RC5_HALF_BIT;//second start bit
221
 
222
#define Toggle 0 //TODO: Fix toggle in some proper way
223
    if (Toggle==0){
224
        buf[5] = IR_RC5_HALF_BIT;
225
        buf[6] = IR_RC5_HALF_BIT; //toggle bit (yes i know it should not be hardcoded)
226
        *len = 7;
732 noddan 227
        previousBit = 1;
727 noddan 228
    } else {
229
        buf[4] = IR_RC5_BIT;
230
        buf[5] = IR_RC5_HALF_BIT;
231
        *len = 6;
732 noddan 232
        previousBit = 0;
727 noddan 233
    }
732 noddan 234
 
727 noddan 235
    //let's start with the adress bits..
732 noddan 236
    tempcommand = proto->data&(0b00111111);
727 noddan 237
    tempadress = (proto->data>>8)&(0b00011111);
733 noddan 238
    //TODO: This requires massive cleanup
727 noddan 239
 
732 noddan 240
    //tempdata = ((((uint16_t)(proto->data)&(0x3F)) + ((uint16_t)((proto->data>>8)&(0x1F))<<6)))<<5;
241
 
242
    tempdata = (uint16_t)tempcommand + ((uint16_t)tempadress<<6);
243
    tempdata = tempdata<<5;
244
 
245
    /*
246
    for(uint8_t ijag t = 0; i < 11; i++) {
247
        tempdata = tempdata<<1;
248
        //temptemp = tempadress&0xA0;
249
        if (((tempdata&(0xA000))>>15)==1){
250
            if (previousBit == 1){//11
251
                buf[*len] = IR_RC5_HALF_BIT;
252
                buf[*len+1] = IR_RC5_HALF_BIT;
253
                *len = *len + 2;
254
            } else {//01
255
                buf[*len-1] = IR_RC5_BIT;
256
                buf[*len] = IR_RC5_HALF_BIT;
257
                *len = *len + 1;
258
            }
259
            previousBit = 1;
260
        } else {//10
261
            if (previousBit == 1){
262
                buf[*len-1] = IR_RC5_BIT;
263
                buf[*len] = IR_RC5_HALF_BIT;
264
                *len = *len + 1;
265
            } else {//00
266
                buf[*len] = IR_RC5_HALF_BIT;
267
                buf[*len+1] = IR_RC5_HALF_BIT;
268
                *len = *len + 2;
269
            }
270
            previousBit = 0;
271
        }
272
    }
273
    */
274
 
727 noddan 275
    tempadress = tempadress<<2;
276
 
277
    for(uint8_t i = 0; i < 5; i++) {
278
        tempadress = tempadress<<1;
279
        //temptemp = tempadress&0xA0;
280
        if (((tempadress&(0xA0))>>7)==1){
281
            if (previousBit == 1){//11
282
                buf[*len] = IR_RC5_HALF_BIT;
283
                buf[*len+1] = IR_RC5_HALF_BIT;
284
                *len = *len + 2;
285
            } else {//01
286
                buf[*len-1] = IR_RC5_BIT;
287
                buf[*len] = IR_RC5_HALF_BIT;
288
                *len = *len + 1;
289
            }
290
            previousBit = 1;
291
        } else {//10
292
            if (previousBit == 1){
293
                buf[*len-1] = IR_RC5_BIT;
294
                buf[*len] = IR_RC5_HALF_BIT;
295
                *len = *len + 1;
296
            } else {//00
297
                buf[*len] = IR_RC5_HALF_BIT;
298
                buf[*len+1] = IR_RC5_HALF_BIT;
299
                *len = *len + 2;
300
            }
301
            previousBit = 0;
302
        }
303
    }
304
 
305
 
306
    tempcommand = tempcommand << 1;
307
 
308
    for(uint8_t i = 0; i < 6; i++) {
309
        tempcommand = tempcommand<<1;
310
        //temptemp = tempadress&0xA0;
311
        if (((tempcommand&(0xA0))>>7)==1){
312
            if (previousBit == 1){//11
313
                buf[*len] = IR_RC5_HALF_BIT;
314
                buf[*len+1] = IR_RC5_HALF_BIT;
315
                *len = *len + 2;
316
            } else {//01
317
                buf[*len-1] = IR_RC5_BIT;
318
                buf[*len] = IR_RC5_HALF_BIT;
319
                *len = *len + 1;
320
            }
321
            previousBit = 1;
322
        } else {//10
323
            if (previousBit == 1){
324
                buf[*len-1] = IR_RC5_BIT;
325
                buf[*len] = IR_RC5_HALF_BIT;
326
                *len = *len + 1;
327
            } else {//00
328
                buf[*len] = IR_RC5_HALF_BIT;
329
                buf[*len+1] = IR_RC5_HALF_BIT;
330
                *len = *len + 2;
331
            }
332
            previousBit = 0;
333
        }
334
    }
335
 
336
    proto->modfreq=(((F_CPU/2000)/IR_RC5_F_MOD) -1);
337
    proto->timeout=IR_RC5_TIMEOUT;
338
    proto->repeats=IR_RC5_REPS;
339
    return IR_OK;
608 arune 340
}
341
 
610 arune 342
 
608 arune 343
#if (IR_PROTOCOLS_USE_SHARP)
344
/**
345
 * Test data on SHARP protocol
346
 * http://www.sbprojects.com/knowledge/ir/sharp.htm
347
 *
610 arune 348
 * @param buf
349
 *      Pointer to buffer to where to data to parse is stored
350
 * @param len
351
 *      Length of the data
352
 * @param proto
353
 *      Pointer to protocol information
608 arune 354
 * @return
355
 *      IR_OK if data parsed successfully, one of several errormessages if not
356
 */
357
int8_t parseSharp(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
358
    /* parse buf[], max is len */
359
 
360
    /* check if we have correct amount of data */
361
    if (len != 31) {
362
        return IR_NOT_CORRECT_DATA;
363
    }
364
 
365
    uint16_t rawbits=0;
366
 
367
    for (uint8_t i = 1; i < len; i++) {
368
        if ((i&1) == 1) {       /* if odd, ir-pause */
369
            /* check length of pause between bits */
370
            if (buf[i] > IR_SHARP_LOW_ONE - IR_SHARP_LOW_ONE/IR_SHARP_TOL_DIV && buf[i] < IR_SHARP_LOW_ONE + IR_SHARP_LOW_ONE/IR_SHARP_TOL_DIV) {
371
                /* write a one */
372
                rawbits |= 1<<((i-1)>>1);
373
            } else if (buf[i] > IR_SHARP_LOW_ZERO - IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV && buf[i] < IR_SHARP_LOW_ZERO + IR_SHARP_LOW_ZERO/IR_SHARP_TOL_DIV) {
374
                /* do nothing, a zero is already in rawbits */
375
            } else {
376
                return IR_NOT_CORRECT_DATA;
377
            }
378
        } else {            /* if even, ir-bit */
379
            if (buf[i] > IR_SHARP_HIGH + IR_SHARP_HIGH/IR_SHARP_TOL_DIV || buf[i] < IR_SHARP_HIGH - IR_SHARP_HIGH/IR_SHARP_TOL_DIV) {
380
                return IR_NOT_CORRECT_DATA;
381
            }
382
        }
383
    }
384
 
385
    proto->protocol=IR_PROTO_SHARP;
386
    proto->timeout=IR_SHARP_TIMEOUT;
387
    proto->data=rawbits;
388
    return IR_OK;
389
}
390
#endif
391
 
610 arune 392
/**
393
 * Expand data from Sharp protocol
394
 * http://www.sbprojects.com/knowledge/ir/sharp.htm
395
 *
396
 * @param buf
397
 *      Pointer to buffer to store the expanded data
398
 * @param len
399
 *      Pointer to length of the data
400
 * @param proto
401
 *      Pointer to protocol information
402
 * @return
403
 *      IR_OK if data expanded successfully, one of several errormessages if not
404
 */
608 arune 405
int8_t expandSharp(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
406
    //TODO: Implement this function.
407
    return IR_NOT_CORRECT_DATA;
408
}
409
 
610 arune 410
 
608 arune 411
#if (IR_PROTOCOLS_USE_NEC)
412
/**
413
 * Test data on NEC protocol
414
 * http://www.sbprojects.com/knowledge/ir/nec.htm
415
 *
610 arune 416
 * @param buf
417
 *      Pointer to buffer to where to data to parse is stored
418
 * @param len
419
 *      Length of the data
420
 * @param proto
421
 *      Pointer to protocol information
608 arune 422
 * @return
423
 *      IR_OK if data parsed successfully, one of several errormessages if not
424
 */
425
int8_t parseNEC(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
426
    /* parse buf[], max is len */
427
 
428
    /* check if we have correct amount of data */
429
    if (len != 67) {
430
        return IR_NOT_CORRECT_DATA;
431
    }
432
 
433
    /* check startbit */
434
    if (buf[0] > IR_NEC_ST_BIT + IR_NEC_ST_BIT/IR_NEC_TOL_DIV || buf[0] < IR_NEC_ST_BIT - IR_NEC_ST_BIT/IR_NEC_TOL_DIV) {
435
        return IR_NOT_CORRECT_DATA;
436
    }
437
 
438
    /* check pause after startbit */
439
    if (buf[1] > IR_NEC_ST_PAUSE + IR_NEC_ST_PAUSE/IR_NEC_TOL_DIV || buf[1] < IR_NEC_ST_PAUSE - IR_NEC_ST_PAUSE/IR_NEC_TOL_DIV) {
440
        return IR_NOT_CORRECT_DATA;
441
    }
442
 
610 arune 443
    uint32_t rawbits = 0;
608 arune 444
 
445
    for (uint8_t i = 3; i < len; i++) {
446
        if ((i&1) == 1) {       /* if odd, ir-pause */
447
            /* check length of pause between bits */
448
            if (buf[i] > IR_NEC_LOW_ONE - IR_NEC_LOW_ONE/IR_NEC_TOL_DIV && buf[i] < IR_NEC_LOW_ONE + IR_NEC_LOW_ONE/IR_NEC_TOL_DIV) {
449
                /* write a one */
610 arune 450
                rawbits |= 1UL<<((i-3)>>1);
608 arune 451
            } else if (buf[i] > IR_NEC_LOW_ZERO - IR_NEC_LOW_ZERO/IR_NEC_TOL_DIV && buf[i] < IR_NEC_LOW_ZERO + IR_NEC_LOW_ZERO/IR_NEC_TOL_DIV) {
452
                /* do nothing, a zero is already in place */
453
            } else {
454
                return IR_NOT_CORRECT_DATA;
455
            }
456
        } else {            /* if even, ir-bit */
457
            if (buf[i] > IR_NEC_HIGH + IR_NEC_HIGH/IR_NEC_TOL_DIV || buf[i] < IR_NEC_HIGH - IR_NEC_HIGH/IR_NEC_TOL_DIV) {
458
                return IR_NOT_CORRECT_DATA;
459
            }
460
        }
461
    }
462
 
463
    proto->protocol=IR_PROTO_NEC;
464
    proto->timeout=IR_NEC_TIMEOUT;
610 arune 465
    proto->data=rawbits;   
608 arune 466
    return IR_OK;
467
}
468
#endif
469
 
610 arune 470
/**
471
 * Expand data from NEC protocol
472
 * http://www.sbprojects.com/knowledge/ir/nec.htm
473
 *
474
 * @param buf
475
 *      Pointer to buffer to store the expanded data
476
 * @param len
477
 *      Pointer to length of the data
478
 * @param proto
479
 *      Pointer to protocol information
480
 * @return
481
 *      IR_OK if data expanded successfully, one of several errormessages if not
482
 */
608 arune 483
int8_t expandNEC(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
484
    /* Set up startbit */
485
    buf[0] = IR_NEC_ST_BIT;
617 arune 486
 
487
    if (proto->framecnt == 0) {
488
        buf[1] = IR_NEC_ST_PAUSE;
489
 
490
        *len = 67;
491
        for (uint8_t i = 0; i < 65; i++) {
492
            if ((i&1) == 1) {       /* if odd, ir-pause */
493
                if ((proto->data>>(i>>1))&1) {
494
                    buf[i+2] = IR_NEC_LOW_ONE;
495
                } else {
496
                    buf[i+2] = IR_NEC_LOW_ZERO;
497
                }
498
            } else {            /* if even, ir-bit */
499
                buf[i+2] = IR_NEC_HIGH;
608 arune 500
            }
501
        }
617 arune 502
        proto->timeout=IR_NEC_TIMEOUT;
503
    } else {
504
        buf[1] = IR_NEC_ST_PAUSE/2;
505
        buf[2] = IR_NEC_HIGH;
506
        proto->timeout=IR_NEC_ST_TIMEOUT;
507
        *len = 3;
608 arune 508
    }
509
    proto->modfreq=(((F_CPU/2000)/IR_NEC_F_MOD) -1);
510
    proto->repeats=IR_NEC_REPS;
511
    return IR_OK;
512
}
513
 
610 arune 514
 
608 arune 515
#if (IR_PROTOCOLS_USE_SAMSUNG)
516
/**
517
 * Test data on Samsung protocol
518
 * Very much like NEC, different start bit/pause lengths etc.
519
 * http://www.sbprojects.com/knowledge/ir/nec.htm
520
 *
610 arune 521
 * @param buf
522
 *      Pointer to buffer to where to data to parse is stored
523
 * @param len
524
 *      Length of the data
525
 * @param proto
526
 *      Pointer to protocol information
608 arune 527
 * @return
528
 *      IR_OK if data parsed successfully, one of several errormessages if not
529
 */
530
int8_t parseSamsung(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
531
    /* parse buf[], max is len */
532
 
533
    /* check if we have correct amount of data */
534
    if (len != 67) {
535
        return IR_NOT_CORRECT_DATA;
536
    }
537
 
538
    /* check startbit */
539
    if (buf[0] > IR_SAMS_ST_BIT + IR_SAMS_ST_BIT/IR_SAMS_TOL_DIV || buf[0] < IR_SAMS_ST_BIT - IR_SAMS_ST_BIT/IR_SAMS_TOL_DIV) {
540
        return IR_NOT_CORRECT_DATA;
541
    }
542
 
543
    /* check pause after startbit */
544
    if (buf[1] > IR_SAMS_ST_PAUSE + IR_SAMS_ST_PAUSE/IR_SAMS_TOL_DIV || buf[1] < IR_SAMS_ST_PAUSE - IR_SAMS_ST_PAUSE/IR_SAMS_TOL_DIV) {
545
        return IR_NOT_CORRECT_DATA;
546
    }
547
 
610 arune 548
    uint32_t rawbits = 0;
608 arune 549
 
550
    for (uint8_t i = 3; i < len; i++) {
551
        if ((i&1) == 1) {       /* if odd, ir-pause */
552
            /* check length of pause between bits */
553
            if (buf[i] > IR_SAMS_LOW_ONE - IR_SAMS_LOW_ONE/IR_SAMS_TOL_DIV && buf[i] < IR_SAMS_LOW_ONE + IR_SAMS_LOW_ONE/IR_SAMS_TOL_DIV) {
554
                /* write a one */
610 arune 555
                rawbits |= 1UL<<((i-3)>>1);
608 arune 556
            } else if (buf[i] > IR_SAMS_LOW_ZERO - IR_SAMS_LOW_ZERO/IR_SAMS_TOL_DIV && buf[i] < IR_SAMS_LOW_ZERO + IR_SAMS_LOW_ZERO/IR_SAMS_TOL_DIV) {
557
                /* do nothing, a zero is already in rawbits */
558
            } else {
559
                return IR_NOT_CORRECT_DATA;
560
            }
561
        } else {            /* if even, ir-bit */
562
            if (buf[i] > IR_SAMS_HIGH + IR_SAMS_HIGH/IR_SAMS_TOL_DIV || buf[i] < IR_SAMS_HIGH - IR_SAMS_HIGH/IR_SAMS_TOL_DIV) {
563
                return IR_NOT_CORRECT_DATA;
564
            }
565
        }
566
    }
567
 
568
    proto->protocol=IR_PROTO_SAMS;
569
    proto->timeout=IR_SAMS_TIMEOUT;
610 arune 570
    proto->data=rawbits;   
608 arune 571
    return IR_OK;
572
}
573
#endif
574
 
610 arune 575
/**
576
 * Expand data from Samsung protocol
577
 * Very much like NEC, different start bit/pause lengths etc.
578
 * http://www.sbprojects.com/knowledge/ir/nec.htm
579
 *
580
 * @param buf
581
 *      Pointer to buffer to store the expanded data
582
 * @param len
583
 *      Pointer to length of the data
584
 * @param proto
585
 *      Pointer to protocol information
586
 * @return
587
 *      IR_OK if data expanded successfully, one of several errormessages if not
588
 */
608 arune 589
int8_t expandSamsung(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
590
    /* Set up startbit */
591
    buf[0] = IR_SAMS_ST_BIT;
592
    buf[1] = IR_SAMS_ST_PAUSE;
593
 
594
    for (uint8_t i = 0; i < 65; i++) {
595
        if ((i&1) == 1) {       /* if odd, ir-pause */
596
            if ((proto->data>>(i>>1))&1) {
597
                buf[i+2] = IR_SAMS_LOW_ONE;
598
            } else {
599
                buf[i+2] = IR_SAMS_LOW_ZERO;
600
            }
601
        } else {                /* if even, ir-bit */
602
            buf[i+2] = IR_SAMS_HIGH;
603
        }
604
    }
605
 
606
    *len = 67;
607
 
608
    proto->modfreq=(((F_CPU/2000)/IR_SAMS_F_MOD) -1);
609
    proto->timeout=IR_SAMS_TIMEOUT;
610
    proto->repeats=IR_SAMS_REPS;
611
    return IR_OK;
612
}
732 noddan 613
 
614
#if (IR_PROTOCOLS_USE_MARANTZ)
615
/**
616
 * Test data on Marantz protocol
617
 * Reverse-Engineered by Noddan, very similar to RC-5.
618
 * Not tested with odd adresses since I have no remote that sends them.
619
 * Don't know what happens with the extra long bit in that case.
620
 * TODO: Replace all the RC5 with Marantz :D
621
 *
622
 * @param buf
623
 *      Pointer to buffer to where to data to parse is stored
624
 * @param len
625
 *      Length of the data
626
 * @param proto
627
 *      Pointer to protocol information
628
 * @return
629
 *      IR_OK if data parsed successfully, one of several errormessages if not
630
 */
631
int8_t parseMarantz(const uint16_t *buf, uint8_t len, Ir_Protocol_Data_t *proto) {
632
    uint8_t halfbitscnt = 1;
633
    uint32_t rawbits = 0;
634
 
635
    for (uint8_t i = 0; i<len; i++) {
636
        //halfbitscnt&1==1 in the middle of bits
637
        //i&1==0 positive flank
638
 
639
        if ((halfbitscnt&1)==1 && (i&1)==0) {       /* in the middle of bit AND a positve flank */
640
            rawbits |= (uint32_t)1<<(19-(halfbitscnt>>1));
641
        }
642
 
734 noddan 643
        if (buf[i] > IR_MARANTZ_HALF_BIT - IR_MARANTZ_HALF_BIT/IR_MARANTZ_TOL_DIV && buf[i] < IR_MARANTZ_HALF_BIT + IR_MARANTZ_HALF_BIT/IR_MARANTZ_TOL_DIV) {
732 noddan 644
            halfbitscnt += 1;
734 noddan 645
        } else if (buf[i] > IR_MARANTZ_BIT - IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV && buf[i] < IR_MARANTZ_BIT + IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV) {
732 noddan 646
            halfbitscnt += 2;
734 noddan 647
        } else if (buf[i] > IR_MARANTZ_BIT - IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV && buf[i] < 5*IR_MARANTZ_HALF_BIT + IR_MARANTZ_BIT/IR_MARANTZ_TOL_DIV) {
732 noddan 648
            halfbitscnt += 1; //It seems to work, not entirely sure of the purpose of this long zero though.
649
        } else {
650
            return IR_NOT_CORRECT_DATA;
651
        }
652
 
653
    }
654
 
655
    //rawbits = (uint32_t)1<<17;
656
    proto->protocol=IR_PROTO_MARANTZ;
734 noddan 657
    proto->timeout=IR_MARANTZ_TIMEOUT;
732 noddan 658
    //support RC5-extended keeping second startbit 
659
    //remove togglebit
660
    //proto->data = rawbits&0x37ff;
661
    proto->data = rawbits&0x0001ffff;
662
 
663
    return IR_OK;
664
}
665
 
666
/**
733 noddan 667
 * Expand data from Marantz. Written by Martin NordŽn
732 noddan 668
 *
669
 * @param buf
670
 *      Pointer to buffer to store the expanded data
671
 * @param len
672
 *      Pointer to length of the data
673
 * @param proto
674
 *      Pointer to protocol information
675
 * @return
676
 *      IR_OK if data expanded successfully, one of several errormessages if not
677
 */
678
int8_t expandMarantz(uint16_t *buf, uint8_t *len, Ir_Protocol_Data_t *proto) {
679
    uint8_t previousBit;
680
    uint32_t tempdata;
681
 
682
    /* Set up startbits */
734 noddan 683
    buf[0] = IR_MARANTZ_HALF_BIT;//first start bit
684
    buf[1] = IR_MARANTZ_HALF_BIT;
685
    buf[2] = IR_MARANTZ_HALF_BIT;//second start bit
732 noddan 686
    //TODO: Toggle bit should be better, not hard-coded
734 noddan 687
    buf[3] = IR_MARANTZ_HALF_BIT;
688
    buf[4] = IR_MARANTZ_HALF_BIT;//toggle bit
732 noddan 689
    *len=5;
690
    previousBit = 1;
691
 
733 noddan 692
    tempdata = (uint32_t)(proto->data)<<14;
693
 
694
    for(uint8_t i = 0; i < 17; i++) {
732 noddan 695
        tempdata = (uint32_t)tempdata<<1;
733 noddan 696
 
697
        if (((uint32_t)tempdata>>31)==1){
732 noddan 698
            if (previousBit == 1){//11
734 noddan 699
                buf[*len] = IR_MARANTZ_HALF_BIT;
700
                buf[*len+1] = IR_MARANTZ_HALF_BIT;
732 noddan 701
                *len = *len + 2;
702
            } else {//01
734 noddan 703
                buf[*len-1] = IR_MARANTZ_BIT;
704
                buf[*len] = IR_MARANTZ_HALF_BIT;
732 noddan 705
                *len = *len + 1;
706
            }
707
            previousBit = 1;
708
        } else {
709
            if (previousBit == 1){//10
734 noddan 710
                buf[*len-1] = IR_MARANTZ_BIT;
711
                buf[*len] = IR_MARANTZ_HALF_BIT;
732 noddan 712
                *len = *len + 1;
713
            } else {//00
734 noddan 714
                buf[*len] = IR_MARANTZ_HALF_BIT;
733 noddan 715
                if (i==4){
734 noddan 716
                    buf[*len+1] = IR_MARANTZ_HALF_BIT*5;
732 noddan 717
                } else {
734 noddan 718
                    buf[*len+1] = IR_MARANTZ_HALF_BIT;
732 noddan 719
                }
720
 
721
                *len = *len + 2;
722
            }
723
            previousBit = 0;
724
        }
725
    }
726
    //make sure that we finish high by removing the last zero if needed
727
    if (*len%2 == 0){
728
        *len = *len - 1;
729
    }
730
 
734 noddan 731
    proto->modfreq=(((F_CPU/2000)/IR_MARANTZ_F_MOD) -1);
732
    proto->timeout=IR_MARANTZ_TIMEOUT;
733
    proto->repeats=IR_MARANTZ_REPS;
732 noddan 734
    return IR_OK;
735
}
736
 
737
 
738
#endif