2 * Copyright Droids Corporation, Microb Technology, Eirbot (2005)
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * Revision : $Id: mf2_client.c,v 1.1.2.5 2007-05-23 17:18:11 zer0 Exp $
22 /* Olivier MATZ, Droids-corp 2006 */
27 #include <mf2_client.h>
28 #include <mf2_client_config.h>
30 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
31 #include <scheduler.h>
33 #include <aversive/wait.h>
36 #define WATCHDOG_TIMEOUT 10000
38 #define MF2_CLIENT_STATE_IDLE 0
39 #define MF2_CLIENT_STATE_RECV 1
40 #define MF2_CLIENT_STATE_XMIT 2
41 #define MF2_CLIENT_STATE_ACK 3
43 #define data_Z() cbi(DDR(MF2_CLIENT_DATA_PORT), MF2_CLIENT_DATA_BIT)
44 #define data_0() sbi(DDR(MF2_CLIENT_DATA_PORT), MF2_CLIENT_DATA_BIT)
45 #define clk_Z() cbi(DDR(MF2_CLIENT_CLK_PORT), MF2_CLIENT_CLK_BIT)
46 #define clk_0() sbi(DDR(MF2_CLIENT_CLK_PORT), MF2_CLIENT_CLK_BIT)
48 /* XXX s08 -> int8_t */
50 static volatile u08 state=MF2_CLIENT_STATE_IDLE;
51 static volatile u08 current_bitnum;
52 static volatile u16 rx_buf;
53 static volatile u16 tx_buf;
54 static volatile u08 tx_c;
55 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
56 static volatile s08 sched_event = -1;
59 typedef void (event)(char);
61 static event * tx_event = NULL;
62 static event * rx_event = NULL;
64 static s16 check_rx_buf(u16 buf);
66 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
67 static void watchdog_timeout(void * dummy);
70 static void disable_intr(void);
71 static void set_falling_edge(void);
73 #define START_BIT 0x0001
74 #define PARITY_BIT 0x0200
75 #define STOP_BIT 0x0400
77 SIGNAL(MF2_CLIENT_INTERRUPT)
83 case MF2_CLIENT_STATE_IDLE:
85 state=MF2_CLIENT_STATE_RECV;
87 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
88 sched_event = scheduler_add_single_event(watchdog_timeout,
89 NULL, WATCHDOG_TIMEOUT/SCHEDULER_UNIT);
93 case MF2_CLIENT_STATE_RECV:
94 if(PIN(MF2_CLIENT_DATA_PORT) & (1<<MF2_CLIENT_DATA_BIT))
95 rx_buf |= (1 << current_bitnum);
97 if (current_bitnum==10) {
101 c=check_rx_buf(rx_buf);
107 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
108 if (sched_event != -1) {
109 scheduler_del_event(sched_event);
116 state=MF2_CLIENT_STATE_IDLE;
123 case MF2_CLIENT_STATE_XMIT:
124 if (current_bitnum < 10) {
125 if (tx_buf & (1<<current_bitnum))
134 state=MF2_CLIENT_STATE_ACK;
138 case MF2_CLIENT_STATE_ACK:
139 /* if(PIN(MF2_CLIENT_DATA_PORT) & (1<<MF2_CLIENT_DATA_BIT)) */
143 tx_event((char)(tx_c));
145 state=MF2_CLIENT_STATE_IDLE;
146 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
147 if (sched_event != -1) {
148 scheduler_del_event(sched_event);
159 static void set_falling_edge(void)
162 cbi(MF2_CLIENT_IMASK, MF2_CLIENT_IMASK_BIT);
164 /* intr on falling edge */
165 cbi(MF2_CLIENT_INT_REG, MF2_CLIENT_INT_BIT0);
166 sbi(MF2_CLIENT_INT_REG, MF2_CLIENT_INT_BIT1);
169 sbi(MF2_CLIENT_IFLAG, MF2_CLIENT_IMASK_BIT);
172 sbi(MF2_CLIENT_IMASK, MF2_CLIENT_IMASK_BIT);
176 static void disable_intr(void)
179 cbi(MF2_CLIENT_IMASK, MF2_CLIENT_IMASK_BIT);
183 void mf2_client_init(void)
188 /* ports are inputs, and values are 0 */
191 cbi(MF2_CLIENT_DATA_PORT, MF2_CLIENT_DATA_BIT);
192 cbi(MF2_CLIENT_CLK_PORT, MF2_CLIENT_CLK_BIT);
196 state = MF2_CLIENT_STATE_IDLE;
201 static s16 check_rx_buf(u16 buf)
205 /* start bit should be 0 */
209 /* stop bit should be 1 */
210 if(! (buf & STOP_BIT))
213 for (mask = START_BIT ; mask != STOP_BIT; mask<<=1 ) {
222 return (buf>>1) & 0xFF;
226 s08 mf2_client_ready(void)
228 return state==MF2_CLIENT_STATE_IDLE;
231 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
232 static void watchdog_timeout(void * dummy)
236 state=MF2_CLIENT_STATE_IDLE;
243 static void start_sending(void * dummy)
245 /* set clk to Z and data to 0 */
249 #ifdef CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
250 sched_event = scheduler_add_single_event(watchdog_timeout,
251 NULL, WATCHDOG_TIMEOUT/SCHEDULER_UNIT);
255 s08 mf2_client_send(char c)
262 /* we don't preempt the remote device, even if the
264 if (!mf2_client_ready()) {
269 state=MF2_CLIENT_STATE_XMIT;
284 for (mask = START_BIT ; mask != STOP_BIT; mask<<=1 ) {
290 tx_buf |= PARITY_BIT;
292 #if CONFIG_MODULE_MF2_CLIENT_USE_SCHEDULER
293 scheduler_add_single_event(start_sending, NULL, 1000L/SCHEDULER_UNIT);
302 /* This function is used to register another function which will be */
303 /* executed at each byte transmission. */
304 void mf2_client_register_tx_event(void (*f)(char))
312 /* This function is used to register another function which will be */
313 /* executed at each byte reception. */
314 void mf2_client_register_rx_event(void (*f)(char))