Root/atusb-sil/fw/atusb/atusb.c

1/*
2 * atusb/atusb.c - ATUSB initialization and main loop
3 *
4 * Written 2008-2010 by Werner Almesberger
5 * Copyright 2008-2010 Werner Almesberger
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 */
12
13
14#include "regs.h"
15#include "io.h"
16#include "usb.h"
17#include "atusb/ep0.h"
18#include "version.h"
19
20
21static int in_test_mode = 0;
22
23
24static void set_test_mode(int on)
25{
26    in_test_mode = on;
27    if (on) {
28        TST_MODE |= 1 << TST_BIT;
29        TST = 1;
30        LED_MODE |= 1 << LED_BIT;
31    } else {
32        TST = 0;
33        TST_MODE &= ~(1 << TST_BIT);
34        LED_MODE &= ~(1 << LED_BIT);
35        LED = 0;
36    }
37}
38
39
40void reset_rf(void)
41{
42    int i;
43
44    set_test_mode(0);
45
46    nRST_RF = 0;
47    /*
48     * 11.4.12: min 625 ns.
49     * The pulse we generate is slightly longer than 4 us.
50     */
51    for (i = 0; i != 10; i++);
52    nRST_RF = 1;
53}
54
55
56void test_mode(void)
57{
58    set_test_mode(1);
59}
60
61
62/*
63 * The following macros set all unused pins on a given port to zero. This is
64 * more elaborate than just setting the ports directly, but it has the
65 * advantage of hiding the pin to port relation.
66 */
67
68#define PORT_NUM_P0 0
69#define PORT_NUM_P2 2
70#define PORT_NUM_P3 3
71
72#define __PORT_NUM(mode) PORT_NUM_##mode
73#define PORT_NUM(mode) __PORT_NUM(mode)
74
75#define USED(port, net) (PORT_NUM(net##_PORT) == port ? 1 << net##_BIT : 0)
76
77#define ZERO_UNUSED(port) \
78    P##port &= \
79        USED(port, LED) | \
80        USED(port, ID) | \
81        USED(port, MOSI) | \
82        USED(port, MISO) | \
83        USED(port, SCLK) | \
84        USED(port, nSS) | \
85        USED(port, nRST_RF) | \
86        USED(port, IRQ_RF) | \
87        USED(port, SLP_TR) | \
88        USED(port, TST)
89
90    
91static void init_io(void)
92{
93    /*
94     * Signal Mode Value
95     *
96     * MOSI push-pull 0
97     * MISO open drain 1 (input)
98     * SCLK push-pull 0
99     * nSS push-pull 1
100     * nRST_RF push-pull 1
101     * IRQ_RF open drain 1 (input)
102     * SLP_TR push-pull 0
103     * TST open drain 0
104     *
105     * LED push-pull 0 (set up by boot loader)
106     *
107     * all unused open drain 0
108     */
109
110    MOSI = 0;
111    MOSI_MODE |= 1 << MOSI_BIT;
112
113    SCLK = 0;
114    SCLK_MODE |= 1 << SCLK_BIT;
115
116    nSS_MODE |= 1 << nSS_BIT;
117
118    nRST_RF_MODE |= 1 << nRST_RF_BIT;
119
120    SLP_TR = 0;
121    SLP_TR_MODE |= 1 << SLP_TR_BIT;
122
123    IRQ_RF = 1;
124    LED = 0;
125    TST = 0;
126
127    ZERO_UNUSED(0);
128    ZERO_UNUSED(2);
129    ZERO_UNUSED(3);
130
131#if 0
132    /*
133     * We can *almost* disable the pull-ups. The only obstacle is that
134     * MISO is not driven when not in use. So we either need an external
135     * pull-up/down or keep all the pull-ups on.
136     */
137
138    /*
139     * Disable pull-ups
140     */
141    GPIOCN |= WEAKPUD;
142#endif
143
144    /*
145     * The manual says the reset is optional, but reality disagrees with
146     * this optimistic assessment quite violently.
147     */
148
149    reset_rf();
150}
151
152
153void main(void)
154{
155    int i;
156
157    init_io();
158
159    /*
160     * Make sure the host has enough time (2.5 us) to detect that we reset
161     * our USB stack.
162     */
163    for (i = 0; i != 10; i++);
164
165    usb_init();
166    ep0_init();
167
168    while (1) {
169        if (in_test_mode) {
170            i++;
171            LED = !(i >> 11);
172        }
173        usb_poll();
174    }
175}
176

Archive Download this file



interactive