+
+static inline void decode_frame(struct frame_status *status,
+ uint16_t ref_time, uint16_t cur_time, uint8_t cur_tsop)
+{
+ uint16_t diff_time = cur_time - status->prev_time;
+
+ /* first rising edge */
+ if (status->len == 0 && cur_tsop && diff_time > TSOP_TIME_LONG) {
+ status->len = 1;
+ status->val = 1;
+ status->frame = 0;
+ status->start_angle_time = cur_time - ref_time;
+ status->mask = 1;
+ }
+ /* any short edge */
+ else if (status->len != 0 && diff_time < TSOP_TIME_SHORT) {
+ if (status->len & 1) {
+ if (status->val)
+ status->frame |= status->mask;
+ status->mask <<= 1;
+ }
+ status->len ++;
+ }
+ /* any long edge */
+ else if (status->len != 0 && diff_time < TSOP_TIME_LONG) {
+ status->val = !status->val;
+ if (status->val)
+ status->frame |= status->mask;
+ status->mask <<= 1;
+ status->len += 2;
+ }
+ /* error case, reset */
+ else {
+ status->len = 0;
+ }
+
+ /* end of frame */
+ if (status->len == FRAME_LEN*2) {
+ uint8_t tail_next = (status->tail+1) & FRAME_RING_MASK;
+
+ if (tail_next != status->head) {
+ status->ring[status->tail].frame = (status->frame & FRAME_MASK);
+ status->ring[status->tail].time = status->start_angle_time;
+ status->tail = tail_next;
+ if ((status->led_cpt & 0x7) == 0)
+ LED3_TOGGLE();
+ status->led_cpt ++;
+ }
+ status->len = 0;
+ }
+
+ status->prev_time = cur_time;
+ status->prev_tsop = cur_tsop;
+}