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>
30 * Photodiodes: PC0 PC1
35 * hfuse: RSTDISBL=1 WTDON=1 SPIEN=0 CKOPT=0 EESAVE=1 BOOTSZ1=0 BOOTSZ0=0 BOOTRST=1
36 * lfuse: BODLEVEL=1 BODEN=1 SUT1=1 SUT0=1 CKSEL3=1 CKSEL2=1 CKSEL1=1 CKSEL0=1
42 #define N_CYCLES_PERIOD (N_CYCLES_0 + N_CYCLES_1)
44 #define LED_PORT PORTD
50 #define LED_TOGGLE(port, bit) do { \
51 if (port & _BV(bit)) \
57 #define LED1_ON() sbi(LED_PORT, LED1_BIT)
58 #define LED1_OFF() cbi(LED_PORT, LED1_BIT)
59 #define LED1_TOGGLE() LED_TOGGLE(LED_PORT, LED1_BIT)
60 #define LED2_ON() sbi(LED_PORT, LED2_BIT)
61 #define LED2_OFF() cbi(LED_PORT, LED2_BIT)
62 #define LED2_TOGGLE() LED_TOGGLE(LED_PORT, LED2_BIT)
63 #define LED3_ON() sbi(LED_PORT, LED3_BIT)
64 #define LED3_OFF() cbi(LED_PORT, LED3_BIT)
65 #define LED3_TOGGLE() LED_TOGGLE(LED_PORT, LED3_BIT)
71 /* FRAME must be odd */
72 /* #define FRAME 0x0B /\* in little endian 1-1-0-1 *\/ */
73 /* #define FRAME_LEN 4 */
74 #define FRAME 0xAA5B /* in little endian */
77 /* pin returns 1 when nothing, and 0 when laser is on photodiode */
78 #define PHOTO_PIN PINC
81 #define READ_PHOTOS() (PHOTO_PIN & (_BV(PHOTO1_BIT) | _BV(PHOTO2_BIT)))
82 #define READ_PHOTO1() (PHOTO_PIN & _BV(PHOTO1_BIT))
83 #define READ_PHOTO2() (PHOTO_PIN & _BV(PHOTO2_BIT))
85 #define PHOTOS_ALL_OFF (_BV(PHOTO1_BIT) | _BV(PHOTO2_BIT))
86 #define PHOTOS_ALL_ON (0)
87 #define PHOTOS_1ON_2OFF (_BV(PHOTO2_BIT))
88 #define PHOTOS_1OFF_2ON (_BV(PHOTO1_BIT))
91 /* in cycles/64 (unit is 4 us at 16Mhz) */
92 #define MAX_PHOTO_TIME ((uint8_t)25) /* t=100us len=5mm rps=40Hz dist=20cm */
94 #define MIN_INTER_TIME ((uint8_t)12) /* t=50us len=50mm rps=40Hz dist=350cm */
95 #define MAX_INTER_TIME ((uint8_t)250) /* t=1000us len=50mm rps=40Hz dist=20cm */
98 #define INTER_LASER_TIME 10
100 #define NO_MODULATION
103 /* basic functions to transmit on IR */
105 static inline void xmit_0(void)
107 uint8_t t = ((N_CYCLES_PERIOD * N_PERIODS) / 3);
109 cbi(IR_PORT, IR_BIT);
114 _delay_loop_1(t); /* 3 cycles per loop */
117 static inline void xmit_1(void)
119 uint8_t t = ((N_CYCLES_PERIOD * N_PERIODS) / 3);
121 sbi(IR_PORT, IR_BIT);
123 TCCR1B = _BV(WGM13) | _BV(WGM12);
124 TCNT1 = N_CYCLES_PERIOD-1;
125 TCCR1A = _BV(COM1A1) | _BV(WGM11);
126 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
128 _delay_loop_1(t); /* 3 cycles per loop */
131 /* transmit in manchester code */
133 static inline void xmit_manchester_0(void)
139 static inline void xmit_manchester_1(void)
145 /* transmit a full frame. Each byte is lsb first. */
147 static void xmit_bits(uint32_t frame, uint8_t nbit)
151 for (i=0; i<nbit; i++) {
164 static inline int8_t wait_laser(void)
170 /* wait until all is off */
171 while (READ_PHOTOS() != PHOTOS_ALL_OFF);
173 /* wait an event, it must be photo1 on */
174 while ((photos = READ_PHOTOS()) == PHOTOS_ALL_OFF);
176 if (photos != PHOTOS_1ON_2OFF)
181 /* wait an event, it must be photo1 off */
182 while ((photos = READ_PHOTOS()) == PHOTOS_1ON_2OFF) {
184 if (diff > MAX_PHOTO_TIME)
187 if (photos != PHOTOS_ALL_OFF)
191 /* wait an event, it must be photo2 on */
192 while ((photos = READ_PHOTOS()) == PHOTOS_ALL_OFF) {
194 if (diff > MAX_INTER_TIME)
200 if (diff < MIN_INTER_TIME)
202 if (photos != PHOTOS_1OFF_2ON)
208 /* wait an event, it must be photo2 off */
209 while ((photos = READ_PHOTOS()) == PHOTOS_1OFF_2ON) {
211 if (diff > MAX_PHOTO_TIME)
214 if (photos != PHOTOS_ALL_OFF)
227 uint32_t frame = FRAME;
232 LED_DDR = _BV(LED1_BIT) | _BV(LED2_BIT) | _BV(LED3_BIT);
233 IR_DDR |= _BV(IR_BIT);
236 fdevopen(uart0_dev_send, uart0_dev_recv);
241 c = uart_recv_nowait(0);
243 printf("%c", (char)(c+1));
253 if (READ_PHOTO() & _BV(PHOTO1_BIT))
260 #ifndef NO_MODULATION
262 ICR1 = N_CYCLES_PERIOD;
264 TCCR1A = _BV(COM1A1) | _BV(WGM11);
265 TCCR1B = _BV(WGM13) | _BV(WGM12);
268 /* configure timer 0, prescaler = 64 */
269 TCCR0 = _BV(CS01) | _BV(CS00);
285 /* ok, transmit frame */
286 xmit_bits(frame, FRAME_LEN);
288 /* don't watch a laser during this time */
289 wait_ms(INTER_LASER_TIME);