2 * Copyright Droids Corporation (2009)
3 * Olivier Matz <zer0@droids-corp.org>
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * Revision : $Id: main.c,v 1.8 2009-05-02 10:08:09 zer0 Exp $
24 #include <aversive/wait.h>
28 * Photodiodes: PC0 PC1
33 * hfuse: RSTDISBL=1 WTDON=1 SPIEN=0 CKOPT=0 EESAVE=1 BOOTSZ1=0 BOOTSZ0=0 BOOTRST=1
34 * lfuse: BODLEVEL=1 BODEN=1 SUT1=1 SUT0=1 CKSEL3=1 CKSEL2=1 CKSEL1=1 CKSEL0=1
40 #define N_CYCLES_PERIOD (N_CYCLES_0 + N_CYCLES_1)
42 #define LED_PORT PORTD
48 #define LED_TOGGLE(port, bit) do { \
49 if (port & _BV(bit)) \
55 #define LED1_ON() sbi(LED_PORT, LED1_BIT)
56 #define LED1_OFF() cbi(LED_PORT, LED1_BIT)
57 #define LED1_TOGGLE() LED_TOGGLE(LED_PORT, LED1_BIT)
58 #define LED2_ON() sbi(LED_PORT, LED2_BIT)
59 #define LED2_OFF() cbi(LED_PORT, LED2_BIT)
60 #define LED2_TOGGLE() LED_TOGGLE(LED_PORT, LED2_BIT)
61 #define LED3_ON() sbi(LED_PORT, LED3_BIT)
62 #define LED3_OFF() cbi(LED_PORT, LED3_BIT)
63 #define LED3_TOGGLE() LED_TOGGLE(LED_PORT, LED3_BIT)
69 /* FRAME must be odd */
70 #define FRAME 0x0B /* in little endian 1-1-0-1 */
73 /* pin returns 1 when nothing, and 0 when laser is on photodiode */
74 #define PHOTO_PIN PINC
77 #define READ_PHOTOS() (PHOTO_PIN & (_BV(PHOTO1_BIT) | _BV(PHOTO2_BIT)))
78 #define READ_PHOTO1() (PHOTO_PIN & _BV(PHOTO1_BIT))
79 #define READ_PHOTO2() (PHOTO_PIN & _BV(PHOTO2_BIT))
81 #define PHOTOS_ALL_OFF (_BV(PHOTO1_BIT) | _BV(PHOTO2_BIT))
82 #define PHOTOS_ALL_ON (0)
83 #define PHOTOS_1ON_2OFF (_BV(PHOTO2_BIT))
84 #define PHOTOS_1OFF_2ON (_BV(PHOTO1_BIT))
87 /* in cycles/64 (unit is 4 us at 16Mhz) */
88 #define MAX_PHOTO_TIME ((uint8_t)25) /* t=100us len=5mm rps=40Hz dist=20cm */
90 #define MIN_INTER_TIME ((uint8_t)12) /* t=50us len=50mm rps=40Hz dist=350cm */
91 #define MAX_INTER_TIME ((uint8_t)250) /* t=1000us len=50mm rps=40Hz dist=20cm */
94 #define INTER_LASER_TIME 10
98 /* basic functions to transmit on IR */
100 static inline void xmit_0(void)
102 uint8_t t = ((N_CYCLES_PERIOD * N_PERIODS) / 3);
105 _delay_loop_1(t); /* 3 cycles per loop */
108 static inline void xmit_1(void)
110 uint8_t t = ((N_CYCLES_PERIOD * N_PERIODS) / 3);
111 TCCR1B = _BV(WGM13) | _BV(WGM12);
112 TCNT1 = N_CYCLES_PERIOD-1;
113 TCCR1A = _BV(COM1A1) | _BV(WGM11);
114 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
115 _delay_loop_1(t); /* 3 cycles per loop */
118 /* transmit in manchester code */
120 static inline void xmit_manchester_0(void)
126 static inline void xmit_manchester_1(void)
132 /* transmit a full frame. Each byte is lsb first. */
134 static void xmit_bits(uint8_t *buf, uint8_t nbit)
139 for (i=0; i<nbit; i++) {
149 if (((i & 0x07) == 0) && (i != 0))
156 static inline int8_t wait_laser(void)
162 /* wait until all is off */
163 while (READ_PHOTOS() != PHOTOS_ALL_OFF);
165 /* wait an event, it must be photo1 on */
166 while ((photos = READ_PHOTOS()) == PHOTOS_ALL_OFF);
168 if (photos != PHOTOS_1ON_2OFF)
173 /* wait an event, it must be photo1 off */
174 while ((photos = READ_PHOTOS()) == PHOTOS_1ON_2OFF) {
176 if (diff > MAX_PHOTO_TIME)
179 if (photos != PHOTOS_ALL_OFF)
183 /* wait an event, it must be photo2 on */
184 while ((photos = READ_PHOTOS()) == PHOTOS_ALL_OFF) {
186 if (diff > MAX_INTER_TIME)
192 if (diff < MIN_INTER_TIME)
194 if (photos != PHOTOS_1OFF_2ON)
200 /* wait an event, it must be photo2 off */
201 while ((photos = READ_PHOTOS()) == PHOTOS_1OFF_2ON) {
203 if (diff > MAX_PHOTO_TIME)
206 if (photos != PHOTOS_ALL_OFF)
219 uint8_t frame = FRAME;
223 LED_DDR = _BV(LED1_BIT) | _BV(LED2_BIT) | _BV(LED3_BIT);
224 IR_DDR |= _BV(IR_BIT);
237 if (READ_PHOTO() & _BV(PHOTO1_BIT))
245 ICR1 = N_CYCLES_PERIOD;
247 TCCR1A = _BV(COM1A1) | _BV(WGM11);
248 TCCR1B = _BV(WGM13) | _BV(WGM12);
250 /* configure timer 0, prescaler = 64 */
251 TCCR0 = _BV(CS01) | _BV(CS00);
267 /* ok, transmit frame */
268 xmit_bits(&frame, FRAME_LEN);
270 /* don't watch a laser during this time */
271 wait_ms(INTER_LASER_TIME);