]>
Commit | Line | Data |
---|---|---|
ec1bef8e | 1 | /* vim:ts=4 sts=4 et tw=80 |
2 | * | |
3 | * fnordlicht firmware | |
4 | * | |
5 | * for additional information please | |
6 | * see http://lochraster.org/fnordlichtmini | |
7 | * | |
8 | * (c) by Alexander Neumann <alexander@bumpern.de> | |
9 | * | |
10 | * This program is free software: you can redistribute it and/or modify it | |
11 | * under the terms of the GNU General Public License version 3 as published by | |
12 | * the Free Software Foundation. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
15 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
17 | * more details. | |
18 | * | |
19 | * You should have received a copy of the GNU General Public License along with | |
20 | * this program. If not, see <http://www.gnu.org/licenses/>. | |
21 | */ | |
22 | ||
23 | /* includes */ | |
24 | #include "globals.h" | |
25 | #include "../common/io.h" | |
26 | ||
27 | #include <stdint.h> | |
28 | #include <stdbool.h> | |
29 | ||
30 | #include "../common/common.h" | |
31 | #include "usbdrv/usbdrv.h" | |
32 | #include "timer.h" | |
33 | #include "uart.h" | |
34 | #include "ir.h" | |
35 | ||
36 | static bool usb_status; | |
37 | ||
38 | /* supply custom usbDeviceConnect() and usbDeviceDisconnect() macros | |
39 | * which turn the interrupt on and off at the right times, | |
40 | * and prevent the execution of an interrupt while the pullup resistor | |
41 | * is switched off */ | |
42 | #ifdef USB_CFG_PULLUP_IOPORTNAME | |
43 | #undef usbDeviceConnect | |
44 | #define usbDeviceConnect() do { \ | |
45 | USB_PULLUP_DDR |= (1<<USB_CFG_PULLUP_BIT); \ | |
46 | USB_PULLUP_OUT |= (1<<USB_CFG_PULLUP_BIT); \ | |
47 | USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT); \ | |
48 | } while(0); | |
49 | #undef usbDeviceDisconnect | |
50 | #define usbDeviceDisconnect() do { \ | |
51 | USB_INTR_ENABLE &= ~(1 << USB_INTR_ENABLE_BIT); \ | |
52 | USB_PULLUP_DDR &= ~(1<<USB_CFG_PULLUP_BIT); \ | |
53 | USB_PULLUP_OUT &= ~(1<<USB_CFG_PULLUP_BIT); \ | |
54 | } while(0); | |
55 | #endif | |
56 | ||
57 | #define USBRQ_SEND 1 | |
58 | #define USBRQ_IR_STATE 2 | |
59 | #define USBRQ_IR_READ 3 | |
60 | ||
61 | struct usb_state_t { | |
62 | enum { | |
63 | USB_STATE_IDLE = 0, | |
64 | USB_STATE_SEND = 1, | |
65 | } state; | |
66 | ||
67 | usbMsgLen_t bytes_remaining; | |
68 | }; | |
69 | ||
70 | struct usb_state_t usb; | |
71 | ||
72 | USB_PUBLIC usbMsgLen_t usbFunctionSetup(uchar data[8]) | |
73 | { | |
74 | usbRequest_t *req = (void *)data; | |
75 | usbMsgLen_t len = 0; | |
76 | static uint8_t buf[8]; | |
77 | ||
78 | /* set global data pointer to local buffer */ | |
79 | usbMsgPtr = buf; | |
80 | ||
81 | if (req->bRequest == USBRQ_SEND && req->wLength.word > 0) { | |
82 | usb.state = USB_STATE_SEND; | |
83 | if (req->wLength.word < 256) { | |
84 | usb.bytes_remaining = req->wLength.bytes[0]; | |
85 | return USB_NO_MSG; | |
86 | } else { | |
87 | /* too long */ | |
88 | buf[0] = 1; | |
89 | len = 1; | |
90 | } | |
91 | } else if (req->bRequest == USBRQ_IR_STATE) { | |
92 | /* read or set state? */ | |
93 | if (req->bmRequestType & USBRQ_DIR_MASK) { | |
94 | /* read */ | |
95 | buf[0] = ir_global.mode; | |
96 | len = 1; | |
97 | } else { | |
98 | /* write */ | |
99 | uint8_t new_state = req->wValue.bytes[0]; | |
100 | if (new_state <= IR_RECEIVE) | |
101 | ir_set_mode(new_state); | |
102 | } | |
103 | } else if (req->bRequest == USBRQ_IR_READ) { | |
104 | if (ir_global.mode == IR_DISABLED) { | |
105 | usbMsgPtr = (void *)ir_global.time; | |
106 | return 2*ir_global.pos; | |
107 | } | |
108 | } | |
109 | ||
110 | return len; | |
111 | } | |
112 | ||
113 | uchar usbFunctionWrite(uchar *data, uchar len) | |
114 | { | |
115 | if (len > usb.bytes_remaining) | |
116 | len = usb.bytes_remaining; | |
117 | ||
118 | usb.bytes_remaining -= len; | |
119 | ||
120 | while (len--) { | |
121 | /* ugly hack: busy wait until the fifo is ready for another byte... */ | |
122 | while (fifo_full(&global_uart.tx)); | |
123 | uart_putc(*data++); | |
124 | } | |
125 | ||
126 | if (usb.bytes_remaining == 0) { | |
127 | return true; | |
128 | usb.state == USB_STATE_IDLE; | |
129 | } else | |
130 | return len; | |
131 | } | |
132 | ||
133 | void usb_init(void) | |
134 | { | |
135 | usbInit(); | |
136 | } | |
137 | ||
138 | void usb_enable(void) | |
139 | { | |
140 | usbDeviceConnect(); | |
141 | usb_status = true; | |
142 | } | |
143 | ||
144 | void usb_disable(void) | |
145 | { | |
146 | usbDeviceDisconnect(); | |
147 | usb_status = false; | |
148 | } | |
149 | ||
150 | bool usb_enabled(void) | |
151 | { | |
152 | return usb_status; | |
153 | } | |
154 | ||
155 | void usb_poll(void) | |
156 | { | |
157 | if (usb_status) | |
158 | usbPoll(); | |
159 | } |