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 !0 when nothing, and 0 when laser is on photodiode */
78 #define PHOTO_PIN PINC
80 #define READ_PHOTO() (!!(PHOTO_PIN & (_BV(PHOTO_BIT))))
82 /* in cycles/64 (unit is 4 us at 16Mhz) */
83 #define MAX_PHOTO_TIME ((uint8_t)25) /* t=100us len=5mm rps=40Hz dist=20cm */
85 /* XXX to be recalculated */
86 #define MIN_INTER_TIME ((uint8_t)12) /* t=50us len=50mm rps=40Hz dist=350cm */
87 #define MAX_INTER_TIME ((uint8_t)250) /* t=1000us len=50mm rps=40Hz dist=20cm */
90 #define INTER_LASER_TIME 10
92 //#define NO_MODULATION
95 /* basic functions to transmit on IR */
97 static inline void xmit_0(void)
99 uint8_t t = ((N_CYCLES_PERIOD * N_PERIODS) / 3);
101 cbi(IR_PORT, IR_BIT);
106 _delay_loop_1(t); /* 3 cycles per loop */
109 static inline void xmit_1(void)
111 uint8_t t = ((N_CYCLES_PERIOD * N_PERIODS) / 3);
113 sbi(IR_PORT, IR_BIT);
115 TCCR1B = _BV(WGM13) | _BV(WGM12);
116 TCNT1 = N_CYCLES_PERIOD-1;
117 TCCR1A = _BV(COM1A1) | _BV(WGM11);
118 TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);
120 _delay_loop_1(t); /* 3 cycles per loop */
123 /* transmit in manchester code */
125 static inline void xmit_manchester_0(void)
131 static inline void xmit_manchester_1(void)
137 /* transmit a full frame. Each byte is lsb first. */
139 static void xmit_bits(uint32_t frame, uint8_t nbit)
143 for (i=0; i<nbit; i++) {
156 static inline int8_t wait_laser(void)
159 uint8_t time1, time2;
165 wait photo on or timeout
167 should return the amount of time to wait
170 /* wait until all is off */
171 while (READ_PHOTO() != 0);
173 /* wait until photo is on */
174 while (READ_PHOTO() != 1);
178 /* wait until photo is off, if it takes too long time,
180 while (READ_PHOTO() != 0) {
181 diff = TCNT0 - time1;
182 if (diff > MAX_PHOTO_TIME)
187 while (READ_PHOTO() != 1) {
188 diff = TCNT0 - time1;
189 if (diff > MAX_INTER_TIME)
194 /* wait until photo is off, if it takes too long time,
196 while (READ_PHOTO() != 0) {
197 diff = TCNT0 - time2;
198 if (diff > MAX_PHOTO_TIME)
204 diff = time2 - time1;
205 if (diff < MIN_INTER_TIME)
217 uint32_t frame = FRAME;
222 LED_DDR = _BV(LED1_BIT) | _BV(LED2_BIT) | _BV(LED3_BIT);
223 IR_DDR |= _BV(IR_BIT);
226 fdevopen(uart0_dev_send, uart0_dev_recv);
231 c = uart_recv_nowait(0);
233 printf("%c", (char)(c+1));
243 if (READ_PHOTO() & _BV(PHOTO1_BIT))
250 #ifndef NO_MODULATION
252 ICR1 = N_CYCLES_PERIOD;
254 TCCR1A = _BV(COM1A1) | _BV(WGM11);
255 TCCR1B = _BV(WGM13) | _BV(WGM12);
258 /* configure timer 0, prescaler = 64 */
259 TCCR0 = _BV(CS01) | _BV(CS00);
275 /* ok, transmit frame */
276 xmit_bits(frame, FRAME_LEN);
278 /* don't watch a laser during this time */
279 wait_ms(INTER_LASER_TIME);