├── .gitmodules
├── LICENSE
├── firmware
├── LUFAConfig.h
├── arduino_leonardo
│ ├── devconfig.h
│ ├── hwconfig.h
│ ├── makefile
│ ├── pinmap.h
│ └── readme.txt
├── arduino_mega2560
│ ├── devconfig.h
│ ├── m16u2
│ │ ├── hwconfig.h
│ │ └── makefile
│ ├── m2560
│ │ ├── hwconfig.h
│ │ ├── makefile
│ │ └── pinmap.h
│ ├── makefile
│ └── readme.txt
├── arduino_promicro
│ ├── devconfig.h
│ ├── hwconfig.h
│ ├── makefile
│ └── pinmap.h
├── arduino_uno
│ ├── devconfig.h
│ ├── m328
│ │ ├── hwconfig.h
│ │ ├── makefile
│ │ └── pinmap.h
│ ├── m8u2
│ │ ├── hwconfig.h
│ │ └── makefile
│ ├── makefile
│ └── readme.txt
├── breakout_32u2
│ ├── devconfig.h
│ ├── hwconfig.h
│ ├── makefile
│ └── pinmap.h
├── clock.c
├── clock.h
├── comm.c
├── comm.h
├── data_uart0.h
├── data_uart1.h
├── default.mk
├── descriptors.c
├── descriptors.h
├── keydefs.h
├── led.c
├── led.h
├── lufa.mk
├── main_led.c
├── main_usb.c
├── makefile
├── panel.c
├── panel.h
├── queue.c
└── queue.h
├── readme.txt
├── schematic
├── breakout32u2.brd
└── breakout32u2.sch
└── win32
├── driver
├── build
│ ├── vs_2008
│ │ ├── ledwiz.sln
│ │ └── ledwiz.vcproj
│ └── vs_2012
│ │ ├── ledwiz.sln
│ │ ├── ledwiz.vcxproj
│ │ └── ledwiz.vcxproj.filters
├── include
│ └── ledwiz.h
└── src
│ ├── ledwiz.cpp
│ ├── ledwiz.def
│ ├── usbdev.cpp
│ └── usbdev.h
├── lwcconfig
├── build
│ └── vs_2008
│ │ ├── lwcconfig.sln
│ │ └── lwcconfig.vcproj
└── src
│ └── main.cpp
└── testapp
├── build
├── vs_2008
│ ├── testapp.sln
│ └── testapp.vcproj
└── vs_2012
│ ├── testapp.sln
│ ├── testapp.vcxproj
│ └── testapp.vcxproj.filters
└── src
└── main.cpp
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "firmware/lufa"]
2 | path = firmware/lufa
3 | url = https://github.com/abcminiuser/lufa.git
4 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/firmware/LUFAConfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | /*
18 | LUFA Library
19 | Copyright (C) Dean Camera, 2012.
20 |
21 | dean [at] fourwalledcubicle [dot] com
22 | www.lufa-lib.org
23 | */
24 |
25 | /*
26 | Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
27 |
28 | Permission to use, copy, modify, distribute, and sell this
29 | software and its documentation for any purpose is hereby granted
30 | without fee, provided that the above copyright notice appear in
31 | all copies and that both that the copyright notice and this
32 | permission notice and warranty disclaimer appear in supporting
33 | documentation, and that the name of the author not be used in
34 | advertising or publicity pertaining to distribution of the
35 | software without specific, written prior permission.
36 |
37 | The author disclaim all warranties with regard to this
38 | software, including all implied warranties of merchantability
39 | and fitness. In no event shall the author be liable for any
40 | special, indirect or consequential damages or any damages
41 | whatsoever resulting from loss of use, data or profits, whether
42 | in an action of contract, negligence or other tortious action,
43 | arising out of or in connection with the use or performance of
44 | this software.
45 | */
46 |
47 | /** \file
48 | * \brief LUFA Library Configuration Header File
49 | *
50 | * This header file is used to configure LUFA's compile time options,
51 | * as an alternative to the compile time constants supplied through
52 | * a makefile.
53 | *
54 | * For information on what each token does, refer to the LUFA
55 | * manual section "Summary of Compile Tokens".
56 | */
57 |
58 | #ifndef _LUFA_CONFIG_H_
59 | #define _LUFA_CONFIG_H_
60 |
61 | #if (ARCH == ARCH_AVR8)
62 |
63 | /* Non-USB Related Configuration Tokens: */
64 | // #define DISABLE_TERMINAL_CODES
65 |
66 | /* USB Class Driver Related Tokens: */
67 | // #define HID_HOST_BOOT_PROTOCOL_ONLY
68 | // #define HID_STATETABLE_STACK_DEPTH {Insert Value Here}
69 | // #define HID_USAGE_STACK_DEPTH {Insert Value Here}
70 | // #define HID_MAX_COLLECTIONS {Insert Value Here}
71 | // #define HID_MAX_REPORTITEMS {Insert Value Here}
72 | // #define HID_MAX_REPORT_IDS {Insert Value Here}
73 | // #define NO_CLASS_DRIVER_AUTOFLUSH
74 |
75 | /* General USB Driver Related Tokens: */
76 | // #define ORDERED_EP_CONFIG
77 | #define USE_STATIC_OPTIONS (USB_DEVICE_OPT_FULLSPEED | USB_OPT_REG_ENABLED | USB_OPT_AUTO_PLL)
78 | #define USB_DEVICE_ONLY
79 | // #define USB_HOST_ONLY
80 | // #define USB_STREAM_TIMEOUT_MS {Insert Value Here}
81 | // #define NO_LIMITED_CONTROLLER_CONNECT
82 | // #define NO_SOF_EVENTS
83 |
84 | /* USB Device Mode Driver Related Tokens: */
85 | // #define USE_RAM_DESCRIPTORS
86 | // #define USE_FLASH_DESCRIPTORS
87 | // #define USE_EEPROM_DESCRIPTORS
88 | // #define NO_INTERNAL_SERIAL
89 | #define FIXED_CONTROL_ENDPOINT_SIZE 8
90 | // #define DEVICE_STATE_AS_GPIOR {Insert Value Here}
91 | #define FIXED_NUM_CONFIGURATIONS 1
92 | // #define CONTROL_ONLY_DEVICE
93 | // #define INTERRUPT_CONTROL_ENDPOINT
94 | // #define NO_DEVICE_REMOTE_WAKEUP
95 | // #define NO_DEVICE_SELF_POWER
96 |
97 | /* USB Host Mode Driver Related Tokens: */
98 | // #define HOST_STATE_AS_GPIOR {Insert Value Here}
99 | // #define USB_HOST_TIMEOUT_MS {Insert Value Here}
100 | // #define HOST_DEVICE_SETTLE_DELAY_MS {Insert Value Here}
101 | // #define NO_AUTO_VBUS_MANAGEMENT
102 | // #define INVERTED_VBUS_ENABLE_LINE
103 |
104 | #else
105 |
106 | #error Unsupported architecture for this LUFA configuration file.
107 |
108 | #endif
109 | #endif
110 |
--------------------------------------------------------------------------------
/firmware/arduino_leonardo/devconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef DEVCONFIG_H__INCLUDED
18 | #define DEVCONFIG_H__INCLUDED
19 |
20 |
21 | /****************************************
22 | USB device config
23 | ****************************************/
24 |
25 | #define ENABLE_LED_DEVICE
26 |
27 |
28 |
29 | #endif
30 |
31 |
--------------------------------------------------------------------------------
/firmware/arduino_leonardo/hwconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef HWCONFIG_H__INCLUDED
18 | #define HWCONFIG_H__INCLUDED
19 |
20 | #if (F_CPU != 16000000)
21 | #error "invalid CPU clock frequency ==> should be 16 MHZ"
22 | #endif
23 |
24 | #if !defined(__AVR_ATmega32U4__)
25 | #error "invalid CPU type ==> should be ATMega32u4"
26 | #endif
27 |
28 | #include "devconfig.h"
29 | #include "pinmap.h"
30 |
31 |
32 | /****************************************
33 | LED driver config
34 | ****************************************/
35 |
36 | #if defined(ENABLE_LED_DEVICE)
37 |
38 | #define LED_TIMER_vect TIMER0_COMPA_vect
39 |
40 | static void inline led_timer_init(void)
41 | {
42 | const int T0_CYCLE_US = 200;
43 | OCR0A = (((T0_CYCLE_US * (F_CPU / 1000L)) / (64 * 1000L)) - 1);
44 | TCCR0A = _BV(WGM01); // clear timer/counter on compare0 match
45 | TCCR0B = _BV(CS01) |_BV(CS00); // prescale 64
46 | TIMSK0 = _BV(OCIE0A); // enable Output Compare 0 overflow interrupt
47 | TCNT0 = 0x00;
48 | }
49 |
50 | #endif
51 |
52 |
53 | /****************************************
54 | Panel config
55 | ****************************************/
56 |
57 | #if defined(ENABLE_PANEL_DEVICE)
58 | #define PANEL_TASK
59 | #endif
60 |
61 |
62 | /****************************************
63 | Clock config
64 | ****************************************/
65 |
66 | #define CLOCK_COMPARE_MATCH_vect TIMER1_COMPA_vect
67 | #define CLOCK_TCNT TCNT1
68 | #define CLOCK_OCR OCR1A
69 |
70 | static void inline clock_init(void)
71 | {
72 | OCR1A = TCNT1 + (F_CPU / 1000);
73 | TCCR1B = _BV(CS10); // normal mode, no prescale
74 | TIMSK1 = _BV(OCIE1A); // enable Output Compare 1 interrupt
75 | }
76 |
77 |
78 | /****************************************
79 | Debug UART config
80 | ****************************************/
81 |
82 | #if defined(DEBUGLEVEL)
83 |
84 | #define DEBUG_TX_UART_vect USART1_UDRE_vect
85 |
86 | static void inline debug_uart_setUDRIE(uint8_t x) { if (x) { UCSR1B |= (1 << UDRIE1); } else { UCSR1B &= ~(1 << UDRIE1); } }
87 | static void inline debug_uart_writeUDR(uint8_t x) { UDR1 = x; }
88 |
89 | static void inline debug_uart_init(void)
90 | {
91 | UBRR1 = 16; // 115200 bit/s @ 16MHz (==> 2.1% error)
92 | UCSR1A |= (1 << U2X1);
93 | UCSR1C = (3 << UCSZ10); // 1 stop, 8 data
94 | UCSR1B |= (1 << TXEN1);
95 | }
96 |
97 | #endif
98 |
99 |
100 |
101 | #endif
102 |
--------------------------------------------------------------------------------
/firmware/arduino_leonardo/makefile:
--------------------------------------------------------------------------------
1 |
2 | TARGET = arduino_leonardo
3 | TARGET_PATH = ./arduino_leonardo
4 | PARENT_PATH = ./..
5 | MCU = atmega32u4
6 | F_CPU = 16000000
7 | LWCLONE_SRC = ../main_usb.c ../descriptors.c ../comm.c ../led.c ../panel.c ../queue.c ../clock.c
8 |
9 | include ../lufa.mk
10 |
--------------------------------------------------------------------------------
/firmware/arduino_leonardo/pinmap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #define LED_MAPPING_TABLE(_map_) \
18 | /* the following corresponds to the Arduino Leonardo mapping */ \
19 | \
20 | _map_( F, 7, 0 ) /* Analog Pin 0 */ \
21 | _map_( F, 6, 0 ) /* Analog Pin 1 */ \
22 | _map_( F, 5, 0 ) /* Analog Pin 2 */ \
23 | _map_( F, 4, 0 ) /* Analog Pin 3 */ \
24 | _map_( F, 1, 0 ) /* Analog Pin 4 */ \
25 | _map_( F, 0, 0 ) /* Analog Pin 5 */ \
26 | \
27 | _map_( D, 2, 0 ) /* Digital Pin 0 */ \
28 | _map_( D, 3, 0 ) /* Digital Pin 1 */ \
29 | _map_( D, 1, 0 ) /* Digital Pin 2 */ \
30 | _map_( D, 0, 0 ) /* Digital Pin 3 */ \
31 | _map_( D, 4, 0 ) /* Digital Pin 4 */ \
32 | _map_( C, 6, 0 ) /* Digital Pin 5 */ \
33 | _map_( D, 7, 0 ) /* Digital Pin 6 */ \
34 | _map_( E, 6, 0 ) /* Digital Pin 7 */ \
35 | _map_( B, 4, 0 ) /* Digital Pin 8 */ \
36 | _map_( B, 5, 0 ) /* Digital Pin 9 */ \
37 | _map_( B, 6, 0 ) /* Digital Pin 10 */ \
38 | _map_( B, 7, 0 ) /* Digital Pin 11 */ \
39 | _map_( D, 6, 0 ) /* Digital Pin 12 */ \
40 | _map_( C, 7, 0 ) /* Digital Pin 13 (L LED) */ \
41 | \
42 | _map_( B, 0, 1 ) /* RX LED */ \
43 | _map_( D, 5, 1 ) /* TX LED */ \
44 | \
45 | _map_( B, 1, 0 ) /* SCK */ \
46 | _map_( B, 2, 0 ) /* MOSI */ \
47 | _map_( B, 3, 0 ) /* MISO */ \
48 | \
49 | /* end */
50 |
--------------------------------------------------------------------------------
/firmware/arduino_leonardo/readme.txt:
--------------------------------------------------------------------------------
1 | To upload the firmware the Leonardo has to put into bootloader mode by pressing the reset button.
2 | It will then appear at your PC as a serial device with a specific COM port, e.g. COM7.
3 | Quickly before it leaves the bootloader due to timeout, run avrdude:
4 |
5 | avrdude -c avr109 -p atmega32u4 -P COM7 -U flash:w:arduino_leonardo.hex:i
6 |
7 | where you have to adjust this line with the respective com port.
8 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/devconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef DEVCONFIG_H__INCLUDED
18 | #define DEVCONFIG_H__INCLUDED
19 |
20 |
21 | /****************************************
22 | USB device config
23 | ****************************************/
24 |
25 | #define ENABLE_LED_DEVICE
26 |
27 | #define ENABLE_PANEL_DEVICE
28 | #define NUM_JOYSTICKS 2
29 | #define USE_MOUSE 0
30 | #define USE_CONSUMER 1
31 | #define USE_KEYBOARD 1
32 |
33 |
34 |
35 | #endif
36 |
37 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/m16u2/hwconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef HWCONFIG_H__INCLUDED
18 | #define HWCONFIG_H__INCLUDED
19 |
20 | #if (F_CPU != 16000000)
21 | #error "invalid CPU clock frequency ==> should be 16 MHZ"
22 | #endif
23 |
24 | #if !defined(__AVR_ATmega8U2__) && !defined(__AVR_ATmega16U2__) && !defined(__AVR_ATmega32U2__)
25 | #error "invalid CPU type ==> should be atmega8u2/16u2/32u2"
26 | #endif
27 |
28 | #include
29 | #include "../devconfig.h"
30 |
31 |
32 | /****************************************
33 | Data UART config
34 | ****************************************/
35 |
36 | #define DATA_TX_UART_vect USART1_UDRE_vect
37 | #define DATA_RX_UART_vect USART1_RX_vect
38 |
39 | #include "../../data_uart1.h"
40 |
41 | static void inline data_uart_init(void)
42 | {
43 | UBRR1 = 3; // 250 kBit/s @ 16 MHz CPU
44 | UCSR1C |= (1 << UCSZ11) | (1 << UCSZ10) | (1 << UPM11) | (1 << UPM10); // asynchron uart, odd parity, 9-bit-character, 1 stop bit
45 | UCSR1B |= (1 << UCSZ12) | (1 << TXEN1) | (1 << RXEN1) | (1 << RXCIE1); // enable Receiver and Transmitter
46 | }
47 |
48 |
49 | /****************************************
50 | Clock config
51 | ****************************************/
52 |
53 | #define CLOCK_COMPARE_MATCH_vect TIMER1_COMPA_vect
54 | #define CLOCK_TCNT TCNT1
55 | #define CLOCK_OCR OCR1A
56 |
57 | static void inline clock_init(void)
58 | {
59 | OCR1A = TCNT1 + (F_CPU / 1000);
60 | TCCR1B = _BV(CS10); // normal mode, no prescale
61 | TIMSK1 = _BV(OCIE1A); // enable Output Compare 1 interrupt
62 | }
63 |
64 |
65 | /****************************************
66 | Bootloader shutdown config
67 | ****************************************/
68 |
69 | #define exit_bootloader(x) exit_bootloader_stk500v2(x)
70 | #include
71 |
72 | static void inline exit_bootloader_stk500v2(void)
73 | {
74 | UBRR1 = 16; // 115200 bit/s @ 16MHz (==> 2.1% error)
75 | UCSR1A |= (1 << U2X1);
76 | UCSR1B |= (1 << TXEN1);
77 |
78 | _delay_ms(70); // wait until the uC is active (worst case: 65ms + 14CK with LFUSE=0xFF) and waits for data
79 |
80 | #define SEND(_b_) do { \
81 | loop_until_bit_is_set(UCSR1A, UDRE1); \
82 | UDR1 = _b_; } while(0)
83 |
84 | SEND(0x1B); // message start
85 | SEND(0); // sequence number
86 | SEND(0); // message size high
87 | SEND(3); // message size low
88 | SEND(0x0E); // token
89 | SEND(0x11); // command id "leave progmode"
90 | SEND(0); // pre delay
91 | SEND(0); // post delay
92 | SEND(0x1B ^ 3 ^ 0x0e ^ 0x11); // checksum
93 |
94 | _delay_ms(60); // wait until the bootloader has replied and exited (50 ms minimum for shutting down the LEDs --> see stk500boot.c)
95 | UCSR1A &= ~(1 << U2X1); // restore previous state of the uart
96 | UCSR1B &= ~(1 << TXEN1);
97 |
98 | #undef SEND
99 | }
100 |
101 |
102 | #define BOOTLOADER_SIZE 4096
103 | #define BOOTLOADER_START_ADDR ((uint8_t*)1 + FLASHEND - BOOTLOADER_SIZE)
104 |
105 |
106 |
107 | #endif
108 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/m16u2/makefile:
--------------------------------------------------------------------------------
1 |
2 | TARGET = arduino_mega2560__m16u2
3 | TARGET_PATH = ./arduino_mega2560/m16u2
4 | PARENT_PATH = ../..
5 | MCU = atmega16u2
6 | F_CPU = 16000000
7 | LWCLONE_SRC = ../../main_usb.c ../../descriptors.c ../../comm.c ../../led.c ../../panel.c ../../queue.c ../../clock.c
8 | CFLAGS = -I./.
9 |
10 | include ../../lufa.mk
11 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/m2560/hwconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef HWCONFIG_H__INCLUDED
18 | #define HWCONFIG_H__INCLUDED
19 |
20 | #include
21 | #include
22 |
23 | #if (F_CPU != 16000000)
24 | #error "invalid CPU clock frequency ==> should be 16 MHZ"
25 | #endif
26 |
27 | #if !defined(__AVR_ATmega2560__ )
28 | #error "invalid CPU type ==> should be ATMega2560"
29 | #endif
30 |
31 | #include "../devconfig.h"
32 | #include "pinmap.h"
33 |
34 |
35 | /****************************************
36 | LED driver config
37 | ****************************************/
38 |
39 | #if defined(ENABLE_LED_DEVICE)
40 |
41 | #define LED_TIMER_vect TIMER0_COMPA_vect
42 |
43 | static void inline led_timer_init(void)
44 | {
45 | const int T0_CYCLE_US = 200;
46 | OCR0A = (((T0_CYCLE_US * (F_CPU / 1000L)) / (64 * 1000L)) - 1);
47 | TCCR0A = _BV(WGM01); // clear timer/counter on compare0 match
48 | TCCR0B = _BV(CS01) |_BV(CS00); // prescale 64
49 | TIMSK0 = _BV(OCIE0A); // enable Output Compare 0 overflow interrupt
50 | TCNT0 = 0x00;
51 | }
52 |
53 | #endif
54 |
55 |
56 | /****************************************
57 | Panel config
58 | ****************************************/
59 |
60 | #if defined(ENABLE_PANEL_DEVICE)
61 | #define PANEL_TASK
62 | #endif
63 |
64 |
65 | /****************************************
66 | ADC config
67 | ****************************************/
68 |
69 | #if defined(ENABLE_ANALOG_INPUT)
70 |
71 | static void inline ADC_init(void)
72 | {
73 | ADMUX = (1 << REFS0); // VCC with external capacitor on ARef pin
74 |
75 | ADCSRA =
76 | (1 << ADEN) | //enable
77 | (1 << ADSC) | //start conversion(s)
78 | (1 << ADIE) | // interrupt enable
79 | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler 128x
80 | }
81 |
82 | // https://ww1.microchip.com/downloads/en/devicedoc/atmel-2549-8-bit-avr-microcontroller-atmega640-1280-1281-2560-2561_datasheet.pdf
83 | // page 266 : 25.2.1
84 | #define ADCSRB_MUX5 3
85 |
86 | static void inline ADC_setmux(uint8_t mux)
87 | {
88 | ADMUX &= ~0x1F;
89 | ADMUX |= mux & 0x1F;
90 | ADCSRB &= ~(1 << ADCSRB_MUX5);
91 | ADCSRB |= (((mux >> 5) & 0x01) << ADCSRB_MUX5);
92 | }
93 |
94 | #endif
95 |
96 |
97 | /****************************************
98 | Clock config
99 | ****************************************/
100 |
101 | #define CLOCK_COMPARE_MATCH_vect TIMER1_COMPA_vect
102 | #define CLOCK_TCNT TCNT1
103 | #define CLOCK_OCR OCR1A
104 |
105 | static void inline clock_init(void)
106 | {
107 | OCR1A = TCNT1 + (F_CPU / 1000);
108 | TCCR1B = _BV(CS10); // normal mode, no prescale
109 | TIMSK1 = _BV(OCIE1A); // enable Output Compare 1 interrupt
110 | }
111 |
112 |
113 | /****************************************
114 | Data UART config
115 | ****************************************/
116 |
117 | #define DATA_TX_UART_vect USART0_UDRE_vect
118 | #define DATA_RX_UART_vect USART0_RX_vect
119 |
120 | #include "../../data_uart0.h"
121 |
122 | static void inline data_uart_init(void)
123 | {
124 | UBRR0 = 3; // 250 kBit/s @ 16 MHz CPU
125 | UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00) | (1 << UPM01) | (1 << UPM00); // asynchron uart, odd parity, 9-bit-character, 1 stop bit
126 | UCSR0B |= (1 << UCSZ02) | (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0); // enable Receiver and Transmitter
127 | }
128 |
129 |
130 | /****************************************
131 | Debug UART config
132 | ****************************************/
133 |
134 | #if defined(DEBUGLEVEL)
135 |
136 | #define DEBUG_TX_UART_vect USART1_UDRE_vect
137 |
138 | static void inline debug_uart_setUDRIE(uint8_t x) { if (x) { UCSR1B |= (1 << UDRIE1); } else { UCSR1B &= ~(1 << UDRIE1); } }
139 | static void inline debug_uart_writeUDR(uint8_t x) { UDR1 = x; }
140 |
141 | static void inline debug_uart_init(void)
142 | {
143 | UBRR1 = 16; // 115200 bit/s @ 16MHz (==> 2.1% error)
144 | UCSR1A |= (1 << U2X1);
145 | UCSR1C = (3 << UCSZ10); // 1 stop, 8 data
146 | UCSR1B |= (1 << TXEN1);
147 | }
148 |
149 | #endif
150 |
151 |
152 |
153 | #endif
154 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/m2560/makefile:
--------------------------------------------------------------------------------
1 |
2 | MCU = atmega2560
3 | F_CPU = 16000000
4 | TARGET = arduino_mega2560__m2560
5 | LWCLONE_SRC = ../../main_led.c ../../comm.c ../../led.c ../../panel.c ../../queue.c ../../clock.c
6 |
7 | include ../../default.mk
8 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/m2560/pinmap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 |
18 | #define LED_MAPPING_TABLE(_map_) \
19 | \
20 | _map_( A, 0, 0 ) /* ( AD0 ) Digital pin 22 */ \
21 | _map_( A, 1, 0 ) /* ( AD1 ) Digital pin 23 */ \
22 | _map_( A, 2, 0 ) /* ( AD2 ) Digital pin 24 */ \
23 | _map_( A, 3, 0 ) /* ( AD3 ) Digital pin 25 */ \
24 | _map_( A, 4, 0 ) /* ( AD4 ) Digital pin 26 */ \
25 | _map_( A, 5, 0 ) /* ( AD5 ) Digital pin 27 */ \
26 | _map_( A, 6, 0 ) /* ( AD6 ) Digital pin 28 */ \
27 | _map_( A, 7, 0 ) /* ( AD7 ) Digital pin 29 */ \
28 | _map_( C, 7, 0 ) /* ( A15 ) Digital pin 30 */ \
29 | _map_( C, 6, 0 ) /* ( A14 ) Digital pin 31 */ \
30 | _map_( C, 5, 0 ) /* ( A13 ) Digital pin 32 */ \
31 | _map_( C, 4, 0 ) /* ( A12 ) Digital pin 33 */ \
32 | _map_( C, 3, 0 ) /* ( A11 ) Digital pin 34 */ \
33 | _map_( C, 2, 0 ) /* ( A10 ) Digital pin 35 */ \
34 | _map_( C, 1, 0 ) /* ( A9 ) Digital pin 36 */ \
35 | _map_( C, 0, 0 ) /* ( A8 ) Digital pin 37 */ \
36 | _map_( D, 7, 0 ) /* ( T0 ) Digital pin 38 */ \
37 | _map_( G, 2, 0 ) /* ( ALE ) Digital pin 39 */ \
38 | _map_( G, 1, 0 ) /* ( RD ) Digital pin 40 */ \
39 | _map_( G, 0, 0 ) /* ( WR ) Digital pin 41 */ \
40 | _map_( L, 7, 0 ) /* Digital pin 42 */ \
41 | _map_( L, 6, 0 ) /* Digital pin 43 */ \
42 | _map_( L, 5, 0 ) /* ( OC5C ) Digital pin 44 (PWM) */ \
43 | _map_( L, 4, 0 ) /* ( OC5B ) Digital pin 45 (PWM) */ \
44 | _map_( L, 3, 0 ) /* ( OC5A ) Digital pin 46 (PWM) */ \
45 | _map_( L, 2, 0 ) /* ( T5 ) Digital pin 47 */ \
46 | _map_( L, 1, 0 ) /* ( ICP5 ) Digital pin 48 */ \
47 | _map_( L, 0, 0 ) /* ( ICP4 ) Digital pin 49 */ \
48 | _map_( B, 3, 0 ) /* ( MISO/PCINT3 ) Digital pin 50 (MISO) */ \
49 | _map_( B, 2, 0 ) /* ( MOSI/PCINT2 ) Digital pin 51 (MOSI) */ \
50 | _map_( B, 1, 0 ) /* ( SCK/PCINT1 ) Digital pin 52 (SCK) */ \
51 | _map_( B, 0, 0 ) /* ( SS/PCINT0 ) Digital pin 53 (SS) */ \
52 | \
53 | /* end */
54 |
55 | #if (USE_MOUSE)
56 | #define MOUSE_X_CLK_INDEX 9
57 | #define MOUSE_X_DIR_INDEX 10
58 | #define MOUSE_Y_CLK_INDEX 11
59 | #define MOUSE_Y_DIR_INDEX 12
60 | #endif
61 |
62 | #define SHIFT_SWITCH_INDEX 13
63 |
64 | #define PANEL_MAPPING_TABLE(_map_) \
65 | \
66 | _map_( E, 4, MOD_LeftShift, 0 ) /* ( OC3B/INT4 ) Digital pin 2 (PWM) */ \
67 | _map_( E, 5, MOD_RightShift, 0 ) /* ( OC3C/INT5 ) Digital pin 3 (PWM) */ \
68 | _map_( G, 5, MOD_LeftControl, 0 ) /* ( OC0B ) Digital pin 4 (PWM) */ \
69 | _map_( E, 3, MOD_RightControl,0 ) /* ( OC3A/AIN1 ) Digital pin 5 (PWM) */ \
70 | _map_( H, 3, KEY_Esc, 0 ) /* ( OC4A ) Digital pin 6 (PWM) */ \
71 | _map_( H, 4, KEY_Enter, 0 ) /* ( OC4B ) Digital pin 7 (PWM) */ \
72 | _map_( H, 5, KEY_1, KEY_P ) /* ( OC4C ) Digital pin 8 (PWM) */ \
73 | _map_( H, 6, KEY_5, KEY_5 ) /* ( OC2B ) Digital pin 9 (PWM) */ \
74 | _map_( B, 4, KEY_A, KEY_A ) /* ( OC2A/PCINT4 ) Digital pin 10 (PWM) */ \
75 | _map_( B, 5, KEY_S, KEY_S ) /* ( OC1A/PCINT5 ) Digital pin 11 (PWM) */ \
76 | _map_( B, 6, KEY_D, KEY_D ) /* ( OC1B/PCINT6 ) Digital pin 12 (PWM) */ \
77 | _map_( B, 7, J1_Up, KEY_UpArrow ) /* ( OC0A/OC1C/PCINT7 ) Digital pin 13 (PWM) */ \
78 | _map_( J, 1, J1_Left, KEY_LeftArrow ) /* ( TXD3/PCINT10 ) Digital pin 14 (TX3) */ \
79 | _map_( J, 0, 0, 0 ) /* ( RXD3/PCINT9 ) Digital pin 15 (RX3) */ \
80 | _map_( H, 1, J2_Button5, 0 ) /* ( TXD2 ) Digital pin 16 (TX2) */ \
81 | _map_( H, 0, J2_Button4, 0 ) /* ( RXD2 ) Digital pin 17 (RX2) */ \
82 | _map_( D, 1, J2_Button3, KM_ALT_F4 ) /* ( SDA/INT1 ) Digital pin 20 (SDA) */ \
83 | _map_( D, 0, J2_Button2, KM_SHIFT_F7 ) /* ( SCL/INT0 ) Digital pin 21 (SCL) */ \
84 | _map_( F, 0, J1_Right, KEY_RightArrow ) /* ( ADC0 ) Analog pin 0 */ \
85 | _map_( F, 1, J1_Button1, KEY_Enter ) /* ( ADC1 ) Analog pin 1 */ \
86 | _map_( F, 4, J1_Button4, 0 ) /* ( ADC4/TMK ) Analog pin 4 */ \
87 | _map_( F, 5, J1_Button5, 0 ) /* ( ADC5/TMS ) Analog pin 5 */ \
88 | _map_( F, 6, J2_Button1, KEY_F7 ) /* ( ADC6 ) Analog pin 6 */ \
89 | _map_( F, 7, J2_Right, AC_VolumeUp ) /* ( ADC7 ) Analog pin 7 */ \
90 | _map_( K, 0, J2_Left, AC_VolumeDown ) /* ( ADC8/PCINT16 ) Analog pin 8 */ \
91 | _map_( K, 1, J2_Up, KEY_PageUp ) /* ( ADC9/PCINT17 ) Analog pin 9 */ \
92 | _map_( K, 2, J2_Down, KEY_PageDown ) /* ( ADC10/PCINT18 ) Analog pin 10 */ \
93 | _map_( K, 3, J1_Down, KEY_DownArrow ) /* ( ADC11/PCINT19 ) Analog pin 11 */ \
94 | _map_( K, 4, KEY_2, AC_Mute ) /* ( ADC12/PCINT20 ) Analog pin 12 */ \
95 | _map_( K, 5, J1_Button8, 0 ) /* ( ADC13/PCINT21 ) Analog pin 13 */ \
96 | _map_( K, 6, J1_Button7, 0 ) /* ( ADC14/PCINT22 ) Analog pin 14 */ \
97 | _map_( K, 7, J1_Button6, 0 ) /* ( ADC15/PCINT23 ) Analog pin 15 */ \
98 | \
99 | /* end */
100 |
101 |
102 | // (port, pin, mux, value_min, value_max, joyid, axis
103 | // for mega2560, mux is 0x00..0x07 => (ADC0..ADC7) and 0x20..0x27 => (ADC8..ADC15)
104 | #define ADC_MAPPING_TABLE(_map_) \
105 | \
106 | _map_( F, 2, 0x02, 0.000, 1.000, ID_Joystick2, 0 ) /* Analog Pin 2 */ \
107 | _map_( F, 3, 0x03, 0.000, 1.000, ID_Joystick2, 1 ) /* Analog Pin 3 */ \
108 | \
109 | /* end */
110 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/makefile:
--------------------------------------------------------------------------------
1 |
2 | DIRS = m16u2 m2560
3 |
4 | all:
5 | for i in $(DIRS); do make --directory=$$i clean; make --directory=$$i all; done
6 |
7 | clean:
8 | for i in $(DIRS); do make --directory=$$i clean; done
9 |
--------------------------------------------------------------------------------
/firmware/arduino_mega2560/readme.txt:
--------------------------------------------------------------------------------
1 |
2 | Program ATmega2560:
3 | -------------------
4 | avrdude -c wiring -p atmega2560 -P com20 -b 115200 -v -U flash:w:m2560/arduino_mega2560__m2560.hex:i
5 |
6 |
7 | Program ATmega8u2 / ATmega16u2
8 | ------------------------------
9 | Use the tool "Flip" from Atmel and upload "arduino_mega2560__m16u2.hex" or
10 | to revert to Arduino, upload "Arduino-usbserial-atmega16u2-Mega2560-Rev3.hex" from Arduino installation folder "arduino-root\hardware\arduino\firmwares\atmegaxxu2\arduino-usbserial"
11 |
--------------------------------------------------------------------------------
/firmware/arduino_promicro/devconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef DEVCONFIG_H__INCLUDED
18 | #define DEVCONFIG_H__INCLUDED
19 |
20 |
21 | /****************************************
22 | USB device config
23 | ****************************************/
24 |
25 | #define ENABLE_LED_DEVICE
26 | #define ENABLE_ANALOG_INPUT
27 | #define ENABLE_PANEL_DEVICE
28 | #define NUM_JOYSTICKS 2
29 | #define USE_MOUSE 1
30 | #define USE_CONSUMER 0
31 | #define USE_KEYBOARD 1
32 |
33 |
34 | #endif
35 |
36 |
--------------------------------------------------------------------------------
/firmware/arduino_promicro/hwconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef HWCONFIG_H__INCLUDED
18 | #define HWCONFIG_H__INCLUDED
19 |
20 | #if (F_CPU != 16000000)
21 | #error "invalid CPU clock frequency ==> should be 16 MHZ"
22 | #endif
23 |
24 | #if !defined(__AVR_ATmega32U4__)
25 | #error "invalid CPU type ==> should be ATMega32u4"
26 | #endif
27 |
28 | #include "devconfig.h"
29 | #include "pinmap.h"
30 |
31 |
32 | /****************************************
33 | LED driver config
34 | ****************************************/
35 |
36 | #if defined(ENABLE_LED_DEVICE)
37 |
38 | #define LED_TIMER_vect TIMER0_COMPA_vect
39 |
40 | static void inline led_timer_init(void)
41 | {
42 | const int T0_CYCLE_US = 200;
43 | OCR0A = (((T0_CYCLE_US * (F_CPU / 1000L)) / (64 * 1000L)) - 1);
44 | TCCR0A = _BV(WGM01); // clear timer/counter on compare0 match
45 | TCCR0B = _BV(CS01) |_BV(CS00); // prescale 64
46 | TIMSK0 = _BV(OCIE0A); // enable Output Compare 0 overflow interrupt
47 | TCNT0 = 0x00;
48 | }
49 |
50 | #endif
51 |
52 |
53 | /****************************************
54 | Panel config
55 | ****************************************/
56 |
57 | #if defined(ENABLE_PANEL_DEVICE)
58 | #define PANEL_TASK
59 | #endif
60 |
61 |
62 | /****************************************
63 | ADC config
64 | ****************************************/
65 |
66 | #if defined(ENABLE_ANALOG_INPUT)
67 |
68 | static void inline ADC_init(void)
69 | {
70 | ADMUX = (1 << REFS0); // VCC with external capacitor on ARef pin
71 |
72 | ADCSRA =
73 | (1 << ADEN) | //enable
74 | (1 << ADSC) | //start conversion(s)
75 | (1 << ADIE) | // interrupt enable
76 | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // prescaler 128x
77 | }
78 |
79 | static void inline ADC_setmux(uint8_t mux)
80 | {
81 | ADMUX &= ~0x1F;
82 | ADMUX |= mux & 0x1F;
83 | ADCSRB &= ~(1 << MUX5);
84 | ADCSRB |= (((mux >> 5) & 0x01) << MUX5);
85 | }
86 |
87 | #endif
88 |
89 |
90 | /****************************************
91 | Clock config
92 | ****************************************/
93 |
94 | #define CLOCK_COMPARE_MATCH_vect TIMER1_COMPA_vect
95 | #define CLOCK_TCNT TCNT1
96 | #define CLOCK_OCR OCR1A
97 |
98 | static void inline clock_init(void)
99 | {
100 | OCR1A = TCNT1 + (F_CPU / 1000);
101 | TCCR1B = _BV(CS10); // normal mode, no prescale
102 | TIMSK1 = _BV(OCIE1A); // enable Output Compare 1 interrupt
103 | }
104 |
105 |
106 | /****************************************
107 | Debug UART config
108 | ****************************************/
109 |
110 | #if defined(DEBUGLEVEL)
111 |
112 | #define DEBUG_TX_UART_vect USART1_UDRE_vect
113 |
114 | static void inline debug_uart_setUDRIE(uint8_t x) { if (x) { UCSR1B |= (1 << UDRIE1); } else { UCSR1B &= ~(1 << UDRIE1); } }
115 | static void inline debug_uart_writeUDR(uint8_t x) { UDR1 = x; }
116 |
117 | static void inline debug_uart_init(void)
118 | {
119 | UBRR1 = 16; // 115200 bit/s @ 16MHz (==> 2.1% error)
120 | UCSR1A |= (1 << U2X1);
121 | UCSR1C = (3 << UCSZ10); // 1 stop, 8 data
122 | UCSR1B |= (1 << TXEN1);
123 | }
124 |
125 | #endif
126 |
127 |
128 |
129 | #endif
130 |
--------------------------------------------------------------------------------
/firmware/arduino_promicro/makefile:
--------------------------------------------------------------------------------
1 |
2 | TARGET = arduino_promicro
3 | TARGET_PATH = ./arduino_promicro
4 | PARENT_PATH = ./..
5 | MCU = atmega32u4
6 | F_CPU = 16000000
7 | LWCLONE_SRC = ../main_usb.c ../descriptors.c ../comm.c ../led.c ../panel.c ../queue.c ../clock.c
8 |
9 | include ../lufa.mk
10 |
--------------------------------------------------------------------------------
/firmware/arduino_promicro/pinmap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #define LED_MAPPING_TABLE(_map_) \
18 | /* the following corresponds to the Arduino Leonardo mapping */ \
19 | \
20 | _map_( B, 0, 1 ) /* RX LED */ \
21 | _map_( D, 5, 1 ) /* TX LED */ \
22 | \
23 | /* end */
24 |
25 |
26 | #define MOUSE_X_CLK_INDEX 9
27 | #define MOUSE_X_DIR_INDEX 10
28 | #define MOUSE_Y_CLK_INDEX 11
29 | #define MOUSE_Y_DIR_INDEX 12
30 | #define MOUSE_X_DELTA 2
31 | #define MOUSE_Y_DELTA 2
32 |
33 | #define SHIFT_SWITCH_INDEX 13
34 |
35 | #define PANEL_MAPPING_TABLE(_map_) \
36 | \
37 | _map_( D, 2, KEY_Esc, 0 ) /* Digital Pin 0 */ \
38 | _map_( D, 3, KEY_1, KEY_P ) /* Digital Pin 1 */ \
39 | _map_( D, 1, KEY_2, AC_Mute ) /* Digital Pin 2 */ \
40 | _map_( D, 0, KEY_5, KEY_5 ) /* Digital Pin 3 */ \
41 | _map_( D, 4, J1_Up, KEY_UpArrow ) /* Digital Pin 4 */ \
42 | _map_( C, 6, J1_Left, KEY_LeftArrow ) /* Digital Pin 5 */ \
43 | _map_( D, 7, J1_Right, KEY_RightArrow ) /* Digital Pin 6 */ \
44 | _map_( E, 6, J1_Down, KEY_DownArrow ) /* Digital Pin 7 */ \
45 | _map_( B, 4, J1_Button1, KEY_Enter ) /* Digital Pin 8 */ \
46 | _map_( B, 5, 0, 0 ) /* Digital Pin 9 */ \
47 | _map_( B, 6, 0, 0 ) /* Digital Pin 10 */ \
48 | _map_( B, 3, 0, 0 ) /* Digital Pin 14 / MISO */ \
49 | _map_( B, 1, 0, 0 ) /* Digital Pin 15 / SCK */ \
50 | _map_( B, 2, 0, 0 ) /* Digital Pin 16 / MOSI */ \
51 | \
52 | /* end */
53 |
54 |
55 | // (port, pin, mux, value_min, value_max, joyid, axis
56 | #define ADC_MAPPING_TABLE(_map_) \
57 | \
58 | _map_( F, 7, 0x07, 0.000, 1.000, ID_Joystick1, 0 ) /* Analog Pin 0 */ \
59 | _map_( F, 6, 0x06, 1.000, 0.000, ID_Joystick1, 1 ) /* Analog Pin 1 */ \
60 | _map_( F, 5, 0x05, 0.100, 0.500, ID_Joystick2, 0 ) /* Analog Pin 2 */ \
61 | _map_( F, 4, 0x04, 0.000, 0.500, ID_Joystick2, 1 ) /* Analog Pin 3 */ \
62 | \
63 | /* end */
64 |
65 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/devconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef DEVCONFIG_H__INCLUDED
18 | #define DEVCONFIG_H__INCLUDED
19 |
20 |
21 | /****************************************
22 | USB device config
23 | ****************************************/
24 |
25 | #define ENABLE_LED_DEVICE
26 |
27 |
28 |
29 | #endif
30 |
31 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/m328/hwconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef HWCONFIG_H__INCLUDED
18 | #define HWCONFIG_H__INCLUDED
19 |
20 | #include
21 | #include
22 |
23 | #if (F_CPU != 16000000)
24 | #error "invalid CPU clock frequency ==> should be 16 MHZ"
25 | #endif
26 |
27 | #if !defined(__AVR_ATmega8__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega328__)
28 | #error "invalid CPU type ==> should be ATMega8/168/328"
29 | #endif
30 |
31 | #include "../devconfig.h"
32 | #include "pinmap.h"
33 |
34 |
35 | /****************************************
36 | LED driver config
37 | ****************************************/
38 |
39 | #if defined(ENABLE_LED_DEVICE)
40 |
41 | #define LED_TIMER_vect TIMER0_COMPA_vect
42 |
43 | static void inline led_timer_init(void)
44 | {
45 | const int T0_CYCLE_US = 200;
46 | OCR0A = (((T0_CYCLE_US * (F_CPU / 1000L)) / (64 * 1000L)) - 1);
47 | TCCR0A = _BV(WGM01); // clear timer/counter on compare0 match
48 | TCCR0B = _BV(CS01) |_BV(CS00); // prescale 64
49 | TIMSK0 = _BV(OCIE0A); // enable Output Compare 0 overflow interrupt
50 | TCNT0 = 0x00;
51 | }
52 |
53 | #endif
54 |
55 |
56 | /****************************************
57 | Panel config
58 | ****************************************/
59 |
60 | #if defined(ENABLE_PANEL_DEVICE)
61 | #define PANEL_TASK
62 | #endif
63 |
64 |
65 | /****************************************
66 | Data UART config
67 | ****************************************/
68 |
69 | #define DATA_TX_UART_vect USART_UDRE_vect
70 | #define DATA_RX_UART_vect USART_RX_vect
71 |
72 | #include "../../data_uart0.h"
73 |
74 | static void inline data_uart_init(void)
75 | {
76 | UBRR0 = 3; // 250 kBit/s @ 16 MHz CPU
77 | UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00) | (1 << UPM01) | (1 << UPM00); // asynchron uart, odd parity, 9-bit-character, 1 stop bit
78 | UCSR0B |= (1 << UCSZ02) | (1 << TXEN0) | (1 << RXEN0) | (1 << RXCIE0); // enable Receiver and Transmitter
79 | }
80 |
81 |
82 | /****************************************
83 | Clock config
84 | ****************************************/
85 |
86 | #define CLOCK_COMPARE_MATCH_vect TIMER1_COMPA_vect
87 | #define CLOCK_TCNT TCNT1
88 | #define CLOCK_OCR OCR1A
89 |
90 | static void inline clock_init(void)
91 | {
92 | OCR1A = TCNT1 + (F_CPU / 1000);
93 | TCCR1B = _BV(CS10); // normal mode, no prescale
94 | TIMSK1 = _BV(OCIE1A); // enable Output Compare 1 interrupt
95 | }
96 |
97 |
98 |
99 | #endif
100 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/m328/makefile:
--------------------------------------------------------------------------------
1 |
2 | MCU = atmega328
3 | F_CPU = 16000000
4 | TARGET = arduino_uno__m328
5 | LWCLONE_SRC = ../../main_led.c ../../comm.c ../../led.c ../../panel.c ../../queue.c ../../clock.c
6 |
7 | include ../../default.mk
8 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/m328/pinmap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #define LED_MAPPING_TABLE(_map_) \
18 | \
19 | _map_( D, 2, 0 ) /* Digital Pin 2 */ \
20 | _map_( D, 3, 0 ) /* Digital Pin 3 */ \
21 | _map_( D, 4, 0 ) /* Digital Pin 4 */ \
22 | _map_( D, 5, 0 ) /* Digital Pin 5 */ \
23 | _map_( D, 6, 0 ) /* Digital Pin 6 */ \
24 | _map_( D, 7, 0 ) /* Digital Pin 7 */ \
25 | _map_( B, 0, 0 ) /* Digital Pin 8 */ \
26 | _map_( B, 1, 0 ) /* Digital Pin 9 */ \
27 | _map_( B, 2, 0 ) /* Digital Pin 10 */ \
28 | _map_( B, 3, 0 ) /* Digital Pin 11 */ \
29 | _map_( B, 4, 0 ) /* Digital Pin 12 */ \
30 | _map_( B, 5, 0 ) /* Digital Pin 13 */ \
31 | \
32 | _map_( C, 0, 0 ) /* Analog Pin 0 */ \
33 | _map_( C, 1, 0 ) /* Analog Pin 1 */ \
34 | _map_( C, 2, 0 ) /* Analog Pin 2 */ \
35 | _map_( C, 3, 0 ) /* Analog Pin 3 */ \
36 | _map_( C, 4, 0 ) /* Analog Pin 4 */ \
37 | _map_( C, 5, 0 ) /* Analog Pin 5 */ \
38 | \
39 | /* end */
40 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/m8u2/hwconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef HWCONFIG_H__INCLUDED
18 | #define HWCONFIG_H__INCLUDED
19 |
20 | #if (F_CPU != 16000000)
21 | #error "invalid CPU clock frequency ==> should be 16 MHZ"
22 | #endif
23 |
24 | #if !defined(__AVR_ATmega8U2__) && !defined(__AVR_ATmega16U2__) && !defined(__AVR_ATmega32U2__)
25 | #error "invalid CPU type ==> should be atmega8u2/16u2/32u2"
26 | #endif
27 |
28 | #include
29 | #include "../devconfig.h"
30 |
31 |
32 | /****************************************
33 | Data UART config
34 | ****************************************/
35 |
36 | #define DATA_TX_UART_vect USART1_UDRE_vect
37 | #define DATA_RX_UART_vect USART1_RX_vect
38 |
39 | #include "../../data_uart1.h"
40 |
41 | static void inline data_uart_init(void)
42 | {
43 | UBRR1 = 3; // 250 kBit/s @ 16 MHz CPU
44 | UCSR1C |= (1 << UCSZ11) | (1 << UCSZ10) | (1 << UPM11) | (1 << UPM10); // asynchron uart, odd parity, 9-bit-character, 1 stop bit
45 | UCSR1B |= (1 << UCSZ12) | (1 << TXEN1) | (1 << RXEN1) | (1 << RXCIE1); // enable Receiver and Transmitter
46 | }
47 |
48 |
49 | /****************************************
50 | Clock config
51 | ****************************************/
52 |
53 | #define CLOCK_COMPARE_MATCH_vect TIMER1_COMPA_vect
54 | #define CLOCK_TCNT TCNT1
55 | #define CLOCK_OCR OCR1A
56 |
57 | static void inline clock_init(void)
58 | {
59 | OCR1A = TCNT1 + (F_CPU / 1000);
60 | TCCR1B = _BV(CS10); // normal mode, no prescale
61 | TIMSK1 = _BV(OCIE1A); // enable Output Compare 1 interrupt
62 | }
63 |
64 |
65 | /****************************************
66 | Bootloader shutdown config
67 | ****************************************/
68 |
69 | #define exit_bootloader(x) exit_bootloader_optiboot(x)
70 | #include
71 |
72 | static void inline exit_bootloader_optiboot(void)
73 | {
74 | // todo
75 | }
76 |
77 |
78 | #define BOOTLOADER_SIZE 4096
79 | #define BOOTLOADER_START_ADDR ((uint8_t*)1 + FLASHEND - BOOTLOADER_SIZE)
80 |
81 |
82 |
83 | #endif
84 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/m8u2/makefile:
--------------------------------------------------------------------------------
1 |
2 | TARGET = arduino_uno__m8u2
3 | TARGET_PATH = ./arduino_uno/m8u2
4 | PARENT_PATH = ../..
5 | MCU = atmega8u2
6 | F_CPU = 16000000
7 | LWCLONE_SRC = ../../main_usb.c ../../descriptors.c ../../comm.c ../../led.c ../../panel.c ../../queue.c ../../clock.c
8 | CFLAGS = -I./.
9 |
10 | include ../../lufa.mk
11 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/makefile:
--------------------------------------------------------------------------------
1 |
2 | DIRS = m328 m8u2
3 |
4 | all:
5 | for i in $(DIRS); do make --directory=$$i clean; make --directory=$$i all; done
6 |
7 | clean:
8 | for i in $(DIRS); do make --directory=$$i clean; done
9 |
--------------------------------------------------------------------------------
/firmware/arduino_uno/readme.txt:
--------------------------------------------------------------------------------
1 |
2 | Program ATmega328p:
3 | -------------------
4 | avrdude -c arduino -p m328p -P COM22 -v -U flash:w:m328/arduino_uno__m328.hex:i
5 |
6 |
7 | Program ATmega8u2
8 | -------------------
9 |
10 |
--------------------------------------------------------------------------------
/firmware/breakout_32u2/devconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef DEVCONFIG_H__INCLUDED
18 | #define DEVCONFIG_H__INCLUDED
19 |
20 |
21 | /****************************************
22 | USB device config
23 | ****************************************/
24 |
25 | #define ENABLE_LED_DEVICE
26 |
27 | #define ENABLE_PANEL_DEVICE
28 | #define NUM_JOYSTICKS 2
29 | #define USE_MOUSE 0
30 | #define USE_CONSUMER 1
31 | #define USE_KEYBOARD 1
32 |
33 |
34 |
35 | #endif
36 |
37 |
--------------------------------------------------------------------------------
/firmware/breakout_32u2/hwconfig.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef HWCONFIG_H__INCLUDED
18 | #define HWCONFIG_H__INCLUDED
19 |
20 | #if ((F_CPU != 8000000) && (F_CPU != 16000000))
21 | #error "invalid CPU clock frequency ==> should be 8 MHZ or 16 MHZ"
22 | #endif
23 |
24 | #if !defined(__AVR_ATmega32U2__)
25 | #error "invalid CPU type ==> should be ATMega32u2"
26 | #endif
27 |
28 | #include
29 | #include "devconfig.h"
30 | #include "pinmap.h"
31 |
32 |
33 | /****************************************
34 | LED driver config
35 | ****************************************/
36 |
37 | #if defined(ENABLE_LED_DEVICE)
38 |
39 | #define LED_TIMER_vect TIMER0_COMPA_vect
40 |
41 | static void inline led_timer_init(void)
42 | {
43 | const int T0_CYCLE_US = 200;
44 | OCR0A = (((T0_CYCLE_US * (F_CPU / 1000L)) / (64 * 1000L)) - 1);
45 | TCCR0A = _BV(WGM01); // clear timer/counter on compare0 match
46 | TCCR0B = _BV(CS01) |_BV(CS00); // prescale 64
47 | TIMSK0 = _BV(OCIE0A); // enable Output Compare 0 overflow interrupt
48 | TCNT0 = 0x00;
49 | }
50 |
51 | #endif
52 |
53 |
54 | /****************************************
55 | Panel config
56 | ****************************************/
57 |
58 | #if defined(ENABLE_PANEL_DEVICE)
59 | #define PANEL_TASK
60 | #endif
61 |
62 |
63 | /****************************************
64 | Clock config
65 | ****************************************/
66 |
67 | #define CLOCK_COMPARE_MATCH_vect TIMER1_COMPA_vect
68 | #define CLOCK_TCNT TCNT1
69 | #define CLOCK_OCR OCR1A
70 |
71 | static void inline clock_init(void)
72 | {
73 | OCR1A = TCNT1 + (F_CPU / 1000);
74 | TCCR1B = _BV(CS10); // normal mode, no prescale
75 | TIMSK1 = _BV(OCIE1A); // enable Output Compare 1 interrupt
76 | }
77 |
78 |
79 | /****************************************
80 | Debug UART config
81 | ****************************************/
82 |
83 | #if defined(DEBUGLEVEL)
84 |
85 | #define DEBUG_TX_UART_vect USART1_UDRE_vect
86 |
87 | static void inline debug_uart_setUDRIE(uint8_t x) { if (x) { UCSR1B |= (1 << UDRIE1); } else { UCSR1B &= ~(1 << UDRIE1); } }
88 | static void inline debug_uart_writeUDR(uint8_t x) { UDR1 = x; }
89 |
90 | static void inline debug_uart_init(void)
91 | {
92 | #if (F_CPU == 16000000)
93 | UBRR1 = 16; // 115200 bit/s @ 16MHz (==> 2.1% error)
94 | #else
95 | UBRR1 = 12; // 76800 bit/s @ 8Hz (==> 0.2% error)
96 | #endif
97 | UCSR1A |= (1 << U2X1);
98 | UCSR1C = (3 << UCSZ10); // 1 stop, 8 data
99 | UCSR1B |= (1 << TXEN1);
100 | }
101 |
102 | #endif
103 |
104 |
105 | #define BOOTLOADER_SIZE 4096
106 | #define BOOTLOADER_START_ADDR ((uint8_t*)1 + FLASHEND - BOOTLOADER_SIZE)
107 |
108 |
109 |
110 | #endif
111 |
--------------------------------------------------------------------------------
/firmware/breakout_32u2/makefile:
--------------------------------------------------------------------------------
1 |
2 | TARGET = breakout_32u2
3 | TARGET_PATH = ./breakout_32u2
4 | PARENT_PATH = ./..
5 | MCU = atmega32u2
6 | F_CPU = 8000000
7 | LWCLONE_SRC = ../main_usb.c ../descriptors.c ../comm.c ../led.c ../panel.c ../queue.c ../clock.c
8 |
9 | include ../lufa.mk
10 |
--------------------------------------------------------------------------------
/firmware/breakout_32u2/pinmap.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #define LED_MAPPING_TABLE(_map_) \
18 | \
19 | _map_( B, 3, 0 ) \
20 | _map_( B, 2, 0 ) \
21 | _map_( B, 1, 0 ) \
22 | _map_( D, 6, 0 ) \
23 | _map_( D, 7, 0 ) \
24 | _map_( B, 0, 0 ) \
25 | \
26 | /* end */
27 |
28 |
29 |
30 | #define SHIFT_SWITCH_INDEX 3
31 |
32 | #define MULTIFIRE_INDEX 7 // if this key is pressed once, it will result in 'MULTIFIRE_COUNT' presses
33 | #define MULTIFIRE_COUNT 5 // usefull for coin trigger that should give more than one credit
34 |
35 | #define PANEL_MAPPING_TABLE(_map_) \
36 | \
37 | _map_( D, 0, KEY_1, KEY_Tab ) \
38 | _map_( D, 1, J1_Button1, KEY_Esc ) \
39 | _map_( D, 2, KEY_2, KEY_P ) \
40 | _map_( D, 3, 0, 0 ) \
41 | _map_( D, 4, 0, 0 ) \
42 | _map_( D, 5, 0, 0 ) \
43 | _map_( B, 6, KEY_5, KEY_5 ) \
44 | _map_( B, 7, KEY_5, KEY_5 ) \
45 | _map_( C, 5, J1_Button2, J1_Button2 ) \
46 | _map_( C, 4, J1_Right, KEY_Equal ) \
47 | _map_( C, 7, J1_Left, KEY_Minus ) \
48 | _map_( C, 2, J1_Down, AC_VolumeDown ) \
49 | _map_( C, 6, 0, 0 ) \
50 | _map_( B, 5, J1_Up, AC_VolumeUp ) \
51 | _map_( B, 4, 0, 0 )
52 | \
53 | /* end */
54 |
55 |
--------------------------------------------------------------------------------
/firmware/clock.c:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 | #include "comm.h"
24 | #include "clock.h"
25 |
26 |
27 | static volatile uint16_t g_tsc_lo = 0;
28 | static volatile uint16_t g_tsc_hi = 0;
29 | static volatile uint16_t g_time_ms = 0;
30 |
31 |
32 | ISR(CLOCK_COMPARE_MATCH_vect)
33 | {
34 | #if defined(ENABLE_PROFILING)
35 | profile_start();
36 | #endif
37 |
38 | uint16_t const t = CLOCK_TCNT;
39 |
40 | if (g_tsc_lo > t) {
41 | g_tsc_hi += 1;
42 | }
43 |
44 | g_tsc_lo = t;
45 | g_time_ms += 1;
46 |
47 | CLOCK_OCR += (F_CPU / 1000);
48 | }
49 |
50 | uint32_t clock(void)
51 | {
52 | uint16_t t_lo;
53 | uint16_t t_hi;
54 |
55 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
56 | {
57 | t_lo = g_tsc_lo;
58 | t_hi = g_tsc_hi;
59 | }
60 |
61 | uint16_t const t = CLOCK_TCNT;
62 |
63 | if (t_lo > t) {
64 | t_hi += 1;
65 | }
66 |
67 | return ((uint32_t)t_hi << 16) | t;
68 | }
69 |
70 | uint16_t clock_ms(void)
71 | {
72 | uint16_t t0;
73 |
74 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
75 | {
76 | t0 = g_time_ms;
77 | }
78 |
79 | return t0;
80 | }
81 |
82 |
--------------------------------------------------------------------------------
/firmware/clock.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef CLOCK_H__INCLUDED
18 | #define CLOCK_H__INCLUDED
19 |
20 | #include
21 |
22 |
23 | uint32_t clock(void);
24 | uint16_t clock_ms(void);
25 |
26 |
27 |
28 | #endif // CLOCK_H__INCLUDED
29 |
30 |
--------------------------------------------------------------------------------
/firmware/comm.c:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include "clock.h"
24 | #include "comm.h"
25 |
26 | extern FILE g_stdout_uart;
27 |
28 |
29 | void comm_init(void)
30 | {
31 | #if defined(exit_bootloader)
32 | exit_bootloader();
33 | #endif
34 |
35 | #if defined(DATA_TX_UART_vect) || defined(DATA_RX_UART_vect)
36 | data_uart_init();
37 | #endif
38 |
39 | #if defined(DEBUG_TX_UART_vect) || defined(DEBUG_TX_SOFT_UART_vect)
40 | debug_uart_init();
41 | stdout = &g_stdout_uart;
42 | #endif
43 | }
44 |
45 |
46 | #if defined(DEBUG_TX_UART_vect) || defined(DEBUG_TX_SOFT_UART_vect)
47 |
48 | CREATE_FIFO(g_dbgfifo, 7, 0)
49 |
50 | static int putchar_uart_txt(char c, FILE *stream);
51 | static int putchar_uart_raw(char c, FILE *stream);
52 |
53 | FILE g_stdout_uart = FDEV_SETUP_STREAM(putchar_uart_txt, NULL, _FDEV_SETUP_WRITE);
54 |
55 | static int putchar_uart_raw(char c, FILE *stream)
56 | {
57 | for (;;)
58 | {
59 | if (0 == queue_push(g_dbgfifo, c)) {
60 | break;
61 | }
62 | }
63 |
64 | debug_uart_setUDRIE(1);
65 |
66 | return 0;
67 | }
68 |
69 | static int putchar_uart_txt(char c, FILE *stream)
70 | {
71 | if (c == '\n') {
72 | putchar_uart_raw('\r', stream);
73 | }
74 |
75 | putchar_uart_raw(c, stream);
76 |
77 | return 0;
78 | }
79 |
80 | #if defined(DEBUG_TX_UART_vect)
81 |
82 | ISR(DEBUG_TX_UART_vect)
83 | {
84 | #if defined(ENABLE_PROFILING)
85 | profile_start();
86 | #endif
87 |
88 | uint8_t x;
89 |
90 | int8_t res = queue_pop(g_dbgfifo, &x);
91 |
92 | if (res != 0)
93 | {
94 | debug_uart_setUDRIE(0);
95 | return;
96 | }
97 |
98 | debug_uart_writeUDR(x);
99 | }
100 |
101 | #elif defined(DEBUG_TX_SOFT_UART_vect)
102 |
103 | #define BAUDRATE 9600
104 | #define DURATION_TXBIT ((F_CPU/8 + (BAUDRATE/2)) / BAUDRATE)
105 |
106 | ISR(DEBUG_TX_SOFT_UART_vect)
107 | {
108 | #if defined(ENABLE_PROFILING)
109 | profile_start();
110 | #endif
111 |
112 | OCR0A += DURATION_TXBIT;
113 |
114 | static uint8_t count = 0;
115 | static uint8_t x = 0;
116 |
117 | if (count == 0)
118 | {
119 | int8_t res = queue_pop(g_dbgfifo, &x);
120 |
121 | if (res != 0)
122 | {
123 | debug_uart_setUDRIE(0);
124 | return;
125 | }
126 |
127 | x = ~x; // invert data for Stop bit generation
128 | count = 9; // 10 bits: Start + data + Stop
129 |
130 | TCCR0A = 1 << COM0A1; // clear on next compare
131 |
132 | return;
133 | }
134 |
135 | if (count)
136 | {
137 | count--;
138 | TCCR0A = 1 << COM0A1; // clear on next compare
139 |
140 | // no start bit
141 | if (!(x & 0x01)) // test inverted data
142 | TCCR0A = (1 << COM0A1) | (1 << COM0A0); // set on next compare
143 |
144 | x >>= 1; // shift zero in from left
145 | }
146 | }
147 |
148 | #endif
149 | #endif
150 |
151 | #if defined(ENABLE_PROFILING)
152 |
153 | static volatile uint8_t s_profiling = 0;
154 | static volatile uint32_t s_t_start = 0;
155 |
156 | void profile_stop(void)
157 | {
158 | if (!s_profiling) {
159 | return;
160 | }
161 |
162 | uint32_t t_now = clock();
163 | uint32_t duration;
164 |
165 | ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
166 | {
167 | duration = t_now - s_t_start;
168 | s_profiling = 0;
169 | }
170 |
171 | static uint32_t duration_total = 0;
172 | static uint32_t t_start_total = 0;
173 |
174 | if (t_start_total == 0)
175 | {
176 | t_start_total = t_now;
177 | duration_total = 0;
178 | return;
179 | }
180 |
181 | duration_total += duration;
182 |
183 | if ((t_now - t_start_total) > (((uint32_t)1 << 18) * 100)) {
184 | MsgOut("\rCPU usage: %2d%%", (uint16_t)(duration_total >> 18));
185 | t_start_total = t_now;
186 | duration_total = 0;
187 | }
188 | }
189 |
190 | void profile_start(void)
191 | {
192 | if (!s_profiling) {
193 | s_profiling = 1;
194 | s_t_start = clock();
195 | }
196 | }
197 |
198 | #endif
199 |
200 |
201 | void sleep_ms(uint16_t ms)
202 | {
203 | if (ms > 0) {
204 | ms = clock_ms() + ms;
205 | }
206 |
207 | for (;;)
208 | {
209 | #if defined(ENABLE_PROFILING)
210 | profile_stop();
211 | #endif
212 |
213 | sleep_mode();
214 |
215 | if (ms == 0) {
216 | break;
217 | }
218 |
219 | uint16_t const t_now = clock_ms();
220 |
221 | if (((int16_t)t_now - (int16_t)ms) >= 0) {
222 | break;
223 | }
224 | }
225 | }
226 |
227 |
228 | #if defined(DATA_TX_UART_vect)
229 |
230 | CREATE_FIFO(g_txfifo, 2, 4)
231 |
232 | msg_t* msg_prepare(void)
233 | {
234 | uint8_t * const pdata = chunk_prepare(g_txfifo);
235 |
236 | if (pdata == NULL) {
237 | return NULL;
238 | }
239 |
240 | return (msg_t*)pdata;
241 | }
242 |
243 | void msg_send(void)
244 | {
245 | chunk_push(g_txfifo);
246 | uart_setUDRIE(1);
247 | }
248 |
249 | ISR(DATA_TX_UART_vect)
250 | {
251 | #if defined(ENABLE_PROFILING)
252 | profile_start();
253 | #endif
254 |
255 | static uint8_t nbytes = 0;
256 | static uint8_t * pdata = NULL;
257 |
258 | // start new data frame?
259 |
260 | if (nbytes == 0)
261 | {
262 | pdata = chunk_peek(g_txfifo);
263 |
264 | if (pdata == NULL)
265 | {
266 | //clear UDRE interrupt
267 | uart_setUDRIE(0);
268 | return; // end of transmission
269 | }
270 |
271 | uint8_t const nlen = pdata[0];
272 |
273 | if (nlen >= g_txfifo->chunksize)
274 | {
275 | DbgOut(DBGERROR, "ISR(TX), invalid argument nlen");
276 | chunk_release(g_txfifo);
277 | return;
278 | }
279 |
280 | uart_setBIT8TX(1); // set 9nth bit
281 |
282 | nbytes = nlen + 1;
283 | }
284 | else
285 | {
286 | uart_setBIT8TX(0); // clear 9nth bit
287 | }
288 |
289 | // transmit byte
290 |
291 | uart_writeUDR(*pdata++);
292 | nbytes--;
293 |
294 | // advance fifo
295 |
296 | if (nbytes == 0)
297 | chunk_release(g_txfifo);
298 | }
299 |
300 | #endif
301 |
302 |
303 | #if defined(DATA_RX_UART_vect)
304 |
305 | CREATE_FIFO(g_rxfifo, 2, 4)
306 |
307 | msg_t* msg_recv(void)
308 | {
309 | uint8_t * const pdata = chunk_peek(g_rxfifo);
310 |
311 | if (pdata == NULL) {
312 | return NULL;
313 | }
314 |
315 | return (msg_t*)pdata;
316 | }
317 |
318 | void msg_release(void)
319 | {
320 | chunk_release(g_rxfifo);
321 | }
322 |
323 | ISR(DATA_RX_UART_vect)
324 | {
325 | #if defined(ENABLE_PROFILING)
326 | profile_start();
327 | #endif
328 |
329 | static uint8_t nbytes = 0;
330 | static uint8_t * pdata = NULL;
331 |
332 | uint8_t e = uart_getError();
333 | uint8_t s = uart_getBIT8RX();
334 | uint8_t b = uart_readUDR();
335 |
336 | // check error condition
337 |
338 | if (e)
339 | {
340 | #if 0
341 | if (e & (1 << FE0))
342 | DbgOut(DBGERROR, "ISR(rx), FE0");
343 |
344 | if (e & (1 << DOR0))
345 | DbgOut(DBGERROR, "ISR(rx), DOR0");
346 |
347 | if (e & (1 << UPE0))
348 | DbgOut(DBGERROR, "ISR(rx), UPE0");
349 | #endif
350 |
351 | nbytes = 0;
352 | return;
353 | }
354 |
355 | // sync to start of frame, i.e. bit 8 is set
356 |
357 | if (s)
358 | {
359 | if (nbytes > 0)
360 | {
361 | DbgOut(DBGERROR, "ISR(rx), nbytes > 0");
362 | }
363 |
364 | nbytes = 0;
365 | }
366 |
367 | if (nbytes == 0)
368 | {
369 | if (!s) {
370 | DbgOut(DBGERROR, "ISR(rx), !s");
371 | return;
372 | }
373 |
374 | if (b >= g_rxfifo->chunksize) {
375 | DbgOut(DBGERROR, "ISR(rx), message size to big");
376 | return;
377 | }
378 |
379 | pdata = chunk_prepare(g_rxfifo);
380 |
381 | if (pdata == NULL)
382 | {
383 | DbgOut(DBGERROR, "ISR(rx), buffer full");
384 | return;
385 | }
386 |
387 | nbytes = b + 1;
388 | }
389 |
390 | // store byte
391 |
392 | *pdata++ = b;
393 | nbytes--;
394 |
395 | // commit the message
396 |
397 | if (nbytes == 0)
398 | chunk_push(g_rxfifo);
399 | }
400 |
401 | #endif
402 |
--------------------------------------------------------------------------------
/firmware/comm.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef UART_H__INCLUDED
18 | #define UART_H__INCLUDED
19 |
20 | #include
21 | #include
22 | #include "queue.h"
23 |
24 |
25 | typedef struct {
26 | uint8_t nlen;
27 | uint8_t data[1];
28 | } msg_t;
29 |
30 |
31 | void comm_init(void);
32 |
33 | #if defined(DATA_TX_UART_vect)
34 | msg_t* msg_prepare(void);
35 | void msg_send(void);
36 | #endif
37 |
38 | #if defined(DATA_RX_UART_vect)
39 | msg_t* msg_recv(void);
40 | void msg_release(void);
41 | #endif
42 |
43 |
44 | typedef enum {
45 | DBGERROR = 0,
46 | DBGLOG,
47 | DBGINFO,
48 | DBGTRACE,
49 | } debuglevel;
50 |
51 | #if defined(DEBUG_TX_UART_vect) || defined(DEBUG_TX_SOFT_UART_vect)
52 |
53 | #define DbgOut(_level_, _msg_, ...) do { \
54 | if ((_level_) > DEBUGLEVEL) break; \
55 | printf_P( \
56 | ((_level_) == DBGERROR) ? PSTR("[Error] ") : \
57 | ((_level_) == DBGLOG) ? PSTR("[Log] ") : \
58 | ((_level_) == DBGINFO) ? PSTR("[Info] ") : \
59 | ((_level_) == DBGTRACE) ? PSTR("[Trace] ") : PSTR("[] ")); \
60 | printf_P(PSTR(_msg_), ##__VA_ARGS__); \
61 | printf_P(PSTR("\n")); \
62 | } while (0)
63 |
64 | #define MsgOut(_msg_, ...) printf_P(PSTR(_msg_), ##__VA_ARGS__)
65 |
66 | #else
67 |
68 | #define DbgOut(_level_, _msg_, ...)
69 | #define MsgOut(_msg_, ...)
70 |
71 | #endif
72 |
73 |
74 | #if defined(ENABLE_PROFILING)
75 | void profile_start(void);
76 | void profile_stop(void);
77 | #endif
78 |
79 | void sleep_ms(uint16_t ms);
80 |
81 |
82 |
83 | #endif
--------------------------------------------------------------------------------
/firmware/data_uart0.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef DATA_UART0_H__INCLUDED
18 | #define DATA_UART0_H__INCLUDED
19 |
20 | #include
21 | #include
22 |
23 | static void inline uart_setUDRIE(uint8_t x) { if (x) { UCSR0B |= (1 << UDRIE0); } else { UCSR0B &= ~(1 << UDRIE0); } }
24 | static void inline uart_writeUDR(uint8_t x) { UDR0 = x; }
25 | static uint8_t inline uart_readUDR(void) { return UDR0; }
26 | static void inline uart_setBIT8TX(uint8_t x) { if (x) { UCSR0B |= (1 << TXB80); } else { UCSR0B &= ~(1 << TXB80); } }
27 | static uint8_t inline uart_getBIT8RX(void) { return UCSR0B & (1 << RXB80); }
28 | static uint8_t inline uart_getSRA(void) { return UCSR0A; }
29 | static uint8_t inline uart_getError(void) { return UCSR0A & ((1 << FE0) | (1 << DOR0) | (1 << UPE0)); }
30 |
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/firmware/data_uart1.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef DATA_UART1_H__INCLUDED
18 | #define DATA_UART1_H__INCLUDED
19 |
20 | #include
21 | #include
22 |
23 | static void inline uart_setUDRIE(uint8_t x) { if (x) { UCSR1B |= (1 << UDRIE1); } else { UCSR1B &= ~(1 << UDRIE1); } }
24 | static void inline uart_writeUDR(uint8_t x) { UDR1 = x; }
25 | static uint8_t inline uart_readUDR(void) { return UDR1; }
26 | static void inline uart_setBIT8TX(uint8_t x) { if (x) { UCSR1B |= (1 << TXB81); } else { UCSR1B &= ~(1 << TXB81); } }
27 | static uint8_t inline uart_getBIT8RX(void) { return UCSR1B & (1 << RXB81); }
28 | static uint8_t inline uart_getSRA(void) { return UCSR1A; }
29 | static uint8_t inline uart_getError(void) { return UCSR1A & ((1 << FE1) | (1 << DOR1) | (1 << UPE1)); }
30 |
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/firmware/default.mk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cithraidt/lwcloneu2/40e39ac1b384716857c1152be3767d8e6d0bd674/firmware/default.mk
--------------------------------------------------------------------------------
/firmware/descriptors.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | /*
18 | LUFA Library
19 | Copyright (C) Dean Camera, 2012.
20 |
21 | dean [at] fourwalledcubicle [dot] com
22 | www.lufa-lib.org
23 | */
24 |
25 | /*
26 | Copyright 2012 Dean Camera (dean [at] fourwalledcubicle [dot] com)
27 |
28 | Permission to use, copy, modify, distribute, and sell this
29 | software and its documentation for any purpose is hereby granted
30 | without fee, provided that the above copyright notice appear in
31 | all copies and that both that the copyright notice and this
32 | permission notice and warranty disclaimer appear in supporting
33 | documentation, and that the name of the author not be used in
34 | advertising or publicity pertaining to distribution of the
35 | software without specific, written prior permission.
36 |
37 | The author disclaim all warranties with regard to this
38 | software, including all implied warranties of merchantability
39 | and fitness. In no event shall the author be liable for any
40 | special, indirect or consequential damages or any damages
41 | whatsoever resulting from loss of use, data or profits, whether
42 | in an action of contract, negligence or other tortious action,
43 | arising out of or in connection with the use or performance of
44 | this software.
45 | */
46 |
47 | #ifndef _DESCRIPTORS_H_
48 | #define _DESCRIPTORS_H_
49 |
50 | #include
51 | #include
52 | #include
53 |
54 | #define XYZ_TO_BCD(a,b,c) \
55 | ((uint16_t)(((a)/10) % 10) << 12) | \
56 | ((uint16_t)((a) % 10) << 8) | \
57 | ((uint16_t)((b) % 10) << 4) | \
58 | ((uint16_t)((c) % 10) << 0)
59 |
60 | #define NUMBER_TO_BCD(x) \
61 | ((uint16_t)(((x) / 1000) % 10) << 12) | \
62 | ((uint16_t)(((x) % 1000) / 100) << 8) | \
63 | ((uint16_t)(((x) % 100) / 10) << 4) | \
64 | ((uint16_t)(((x) % 10) ) << 0)
65 |
66 | #if defined(ENABLE_LED_DEVICE)
67 | #define USB_VENDOR_ID 0xFAFA
68 | #define USB_PRODUCT_ID 0x00F3 // this is used as the device identifier, 0x00F0 is '1' up to 0x00FF is '16'
69 | #else
70 | #define USB_VENDOR_ID 0x03EB // Atmel
71 | #define USB_PRODUCT_ID 0x0147
72 | #endif
73 |
74 | #define LWCLONEU2_VERSION 1
75 |
76 |
77 | /* Type Defines: */
78 | /** Type define for the device configuration descriptor structure. This must be defined in the
79 | * application code, as the configuration descriptor contains several sub-descriptors which
80 | * vary between devices, and which describe the device's usage to the host.
81 | */
82 | typedef struct
83 | {
84 | USB_Descriptor_Configuration_Header_t Config;
85 | USB_Descriptor_Interface_t HID_MiscInterface;
86 | USB_HID_Descriptor_HID_t HID_MiscHID;
87 | USB_Descriptor_Endpoint_t HID_MiscReportINEndpoint;
88 | #if defined(ENABLE_PANEL_DEVICE)
89 | USB_Descriptor_Interface_t HID_PanelInterface;
90 | USB_HID_Descriptor_HID_t HID_PanelHID;
91 | USB_Descriptor_Endpoint_t HID_PanelReportINEndpoint;
92 | #endif
93 | #if defined(ENABLE_LED_DEVICE)
94 | USB_Descriptor_Interface_t HID_LEDInterface;
95 | USB_HID_Descriptor_HID_t HID_LEDHID;
96 | USB_Descriptor_Endpoint_t HID_LEDReportINEndpoint;
97 | #endif
98 | } USB_Descriptor_Configuration_t;
99 |
100 | /* Macros: */
101 | /** Endpoint address of the Panel HID reporting IN endpoint. */
102 | #define MISC_EPADDR (ENDPOINT_DIR_IN | 1)
103 | #define PANEL_EPADDR (ENDPOINT_DIR_IN | 2)
104 | #define LED_EPADDR (ENDPOINT_DIR_IN | 3)
105 |
106 | /** Size in bytes of the Panel HID reporting IN endpoint. */
107 | #define MISC_EPSIZE 64
108 | #define PANEL_EPSIZE 8
109 | #define LED_EPSIZE 64
110 |
111 | #define MISC_INTERVAL_MS 10
112 | #define PANEL_INTERVAL_MS 2
113 | #define LED_INTERVAL_MS 10
114 |
115 | /** Descriptor header type value, to indicate a HID class HID descriptor. */
116 | #define DTYPE_HID 0x21
117 |
118 | /** Descriptor header type value, to indicate a HID class HID report descriptor. */
119 | #define DTYPE_Report 0x22
120 |
121 | /* Function Prototypes: */
122 | uint16_t CALLBACK_USB_GetDescriptor(
123 | const uint16_t wValue,
124 | const uint8_t wIndex,
125 | const void** const DescriptorAddress,
126 | uint8_t *const DescriptorMemorySpace)
127 | ATTR_WARN_UNUSED_RESULT ATTR_NON_NULL_PTR_ARG(3);
128 |
129 | void SetProductID(uint16_t id);
130 |
131 |
132 | #endif
133 |
--------------------------------------------------------------------------------
/firmware/keydefs.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | /* Name: hid_input.h
18 | * Project: V-USB Mame Panel
19 | * Author: Andreas Oberdorfer
20 | * Creation Date: 2009-09-19
21 | * Copyright 2009 - 2011 Andreas Oberdorfer
22 | * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
23 | */
24 |
25 | #ifndef KEYDEFS_H__INCLUDED
26 | #define KEYDEFS_H__INCLUDED
27 |
28 |
29 | enum KeyboardCodes
30 | {
31 | KEY_reserved = 0,
32 | KEY_errorRollOver,
33 | KEY_POSTfail,
34 | KEY_errorUndefined,
35 | KEY_A,
36 | KEY_B,
37 | KEY_C,
38 | KEY_D,
39 | KEY_E,
40 | KEY_F,
41 | KEY_G,
42 | KEY_H,
43 | KEY_I,
44 | KEY_J,
45 | KEY_K,
46 | KEY_L,
47 | KEY_M, // 0x10
48 | KEY_N,
49 | KEY_O,
50 | KEY_P,
51 | KEY_Q,
52 | KEY_R,
53 | KEY_S,
54 | KEY_T,
55 | KEY_U,
56 | KEY_V,
57 | KEY_W,
58 | KEY_X,
59 | KEY_Y,
60 | KEY_Z,
61 | KEY_1,
62 | KEY_2,
63 | KEY_3, // 0x20
64 | KEY_4,
65 | KEY_5,
66 | KEY_6,
67 | KEY_7,
68 | KEY_8,
69 | KEY_9,
70 | KEY_0,
71 | KEY_Enter,
72 | KEY_Esc,
73 | KEY_BackSpace,
74 | KEY_Tab,
75 | KEY_Space,
76 | KEY_Minus, // - (and _)
77 | KEY_Equal, // = (and +)
78 | KEY_LeftBr, // [
79 | KEY_RightBr, // ] -- 0x30
80 | KEY_BackSlash, // \ (and |)
81 | KEY_Hash, // Non-US # and ~
82 | KEY_Semicolon, // ; (and :)
83 | KEY_Quotation, // ' and "
84 | KEY_Tilde, // Grave accent and tilde
85 | KEY_Comma, // , (and <)
86 | KEY_Dot, // . (and >)
87 | KEY_Slash, // / (and ?)
88 | KEY_CapsLock, // capslock
89 | KEY_F1,
90 | KEY_F2,
91 | KEY_F3,
92 | KEY_F4,
93 | KEY_F5,
94 | KEY_F6,
95 | KEY_F7, // 0x40
96 | KEY_F8,
97 | KEY_F9,
98 | KEY_F10,
99 | KEY_F11,
100 | KEY_F12,
101 | KEY_PrtScr,
102 | KEY_ScrLck,
103 | KEY_Pause,
104 | KEY_Ins,
105 | KEY_Home,
106 | KEY_PageUp,
107 | KEY_Del,
108 | KEY_End,
109 | KEY_PageDown,
110 | KEY_RightArrow,
111 | KEY_LeftArrow, // 0x50
112 | KEY_DownArrow,
113 | KEY_UpArrow,
114 | KEY_NumLock,
115 | KEY_KP_Slash,
116 | KEY_KP_Ast,
117 | KEY_KP_Minus,
118 | KEY_KP_Plus,
119 | KEY_KP_Enter,
120 | KEY_KP_1,
121 | KEY_KP_2,
122 | KEY_KP_3,
123 | KEY_KP_4,
124 | KEY_KP_5,
125 | KEY_KP_6,
126 | KEY_KP_7,
127 | KEY_KP_8, // 0x60
128 | KEY_KP_9,
129 | KEY_KP_0,
130 | KEY_KP_Comma,
131 | KEY_Euro, // <|> Typically near the Left-Shift key in AT-102 implementations
132 | KEY_Application
133 | };
134 |
135 | enum KeyModCodes
136 | {
137 | KM_ALT_F4 = 0x70,
138 | KM_SHIFT_F7
139 | };
140 |
141 | enum ModifiersCodes
142 | {
143 | MOD_LeftControl = 0x80,
144 | MOD_LeftShift,
145 | MOD_LeftAlt,
146 | MOD_LeftGUI,
147 | MOD_RightControl,
148 | MOD_RightShift,
149 | MOD_RightAlt,
150 | MOD_RightGUI,
151 | };
152 | #define ModifierBit(key) (1 << (key - MOD_LeftControl))
153 |
154 | enum ConsumerCodes
155 | {
156 | AC_VolumeUp = 0x90,
157 | AC_VolumeDown,
158 | AC_Mute
159 | };
160 | #define ConsumerBit(key) (1 << (key - AC_VolumeUp))
161 |
162 | enum MouseButtonCodes
163 | {
164 | MB_Left = 0x98,
165 | MB_Right,
166 | MB_Middle
167 | };
168 | #define MouseButtonBit(key) (1 << (key - MB_Left))
169 |
170 | enum JoystickCodes
171 | {
172 | NR_OF_EVENTS_PER_JOY = 12,
173 |
174 | J1_Left = 0xA0,
175 | J1_Right,
176 | J1_Up,
177 | J1_Down,
178 | J1_Button1,
179 | J1_Button2,
180 | J1_Button3,
181 | J1_Button4,
182 | J1_Button5,
183 | J1_Button6,
184 | J1_Button7,
185 | J1_Button8,
186 |
187 | J2_Left,
188 | J2_Right,
189 | J2_Up,
190 | J2_Down,
191 | J2_Button1,
192 | J2_Button2,
193 | J2_Button3,
194 | J2_Button4,
195 | J2_Button5,
196 | J2_Button6,
197 | J2_Button7,
198 | J2_Button8,
199 |
200 | J3_Left,
201 | J3_Right,
202 | J3_Up,
203 | J3_Down,
204 | J3_Button1,
205 | J3_Button2,
206 | J3_Button3,
207 | J3_Button4,
208 | J3_Button5,
209 | J3_Button6,
210 | J3_Button7,
211 | J3_Button8,
212 |
213 | J4_Left,
214 | J4_Right,
215 | J4_Up,
216 | J4_Down,
217 | J4_Button1,
218 | J4_Button2,
219 | J4_Button3,
220 | J4_Button4,
221 | J4_Button5,
222 | J4_Button6,
223 | J4_Button7,
224 | J4_Button8,
225 |
226 | AG_Left,
227 | AG_Right,
228 | AG_Up,
229 | AG_Down,
230 | AG_Button1,
231 | AG_Button2,
232 | AG_Button3,
233 | AG_Button4,
234 | AG_Button5,
235 | AG_Button6,
236 | AG_Button7,
237 | AG_Button8
238 | };
239 | #define JoyButtonBit(key) (0x01 << (key - J1_Button1))
240 |
241 |
242 |
243 | #endif // KEYDEFS_H__INCLUDED
244 |
--------------------------------------------------------------------------------
/firmware/led.c:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 |
21 | #include
22 | #include "led.h"
23 |
24 |
25 | #if !defined(LED_TIMER_vect)
26 | void led_init(void) {}
27 | void led_update(uint8_t *p8bytes) {}
28 | #else
29 |
30 |
31 | #define MAP(X, pin, inv) X##pin##_index,
32 | enum { LED_MAPPING_TABLE(MAP) NUMBER_OF_LEDS };
33 | #undef MAP
34 |
35 | #define NUMBER_OF_BANKS ((NUMBER_OF_LEDS + 7) / 8)
36 | #define MAX_PWM 49
37 |
38 |
39 | #if (NUMBER_OF_LEDS > 32)
40 | #error "number of led pins is bigger than 32!"
41 | #endif
42 |
43 |
44 | struct {
45 | volatile uint8_t enable;
46 | volatile uint8_t mode;
47 | } g_LED[NUMBER_OF_BANKS * 8];
48 |
49 | volatile uint16_t g_dt = 256; // access is not atomic, but the read in the pwm loop is not critical
50 |
51 |
52 | static void update_state(uint8_t * p5bytes);
53 | static void update_profile(int8_t k, uint8_t * p8bytes);
54 | static void update_pwm(uint8_t *pwm, int8_t n, uint16_t t);
55 | static void led_ports_init(void);
56 |
57 |
58 |
59 | void led_init(void)
60 | {
61 | /* LED driver */
62 | led_ports_init();
63 |
64 | // Timer for soft-PWM
65 | led_timer_init();
66 | }
67 |
68 |
69 | void led_update(uint8_t *p8bytes)
70 | {
71 | static uint8_t nbank = 0;
72 |
73 | if (p8bytes[0] == 64)
74 | {
75 | update_state(p8bytes + 1);
76 | nbank = 0;
77 | }
78 | else
79 | {
80 | update_profile(nbank, p8bytes);
81 | nbank = (nbank + 1) & 0x03;
82 | }
83 | }
84 |
85 |
86 | static void update_state(uint8_t * p5bytes)
87 | {
88 | for (int8_t k = 0; k < NUMBER_OF_BANKS; k++)
89 | {
90 | uint8_t b = p5bytes[k];
91 |
92 | for (int8_t i = 0; i < 8; i++)
93 | {
94 | g_LED[k * 8 + i].enable = b & 0x01;
95 | b >>= 1;
96 | }
97 | }
98 |
99 | uint8_t pulse_speed = p5bytes[4];
100 |
101 | if (pulse_speed > 7)
102 | pulse_speed = 7;
103 |
104 | if (pulse_speed == 0)
105 | pulse_speed = 1;
106 |
107 | g_dt = pulse_speed * 128;
108 | }
109 |
110 |
111 | static void update_profile(int8_t k, uint8_t * p8bytes)
112 | {
113 | if (k >= NUMBER_OF_BANKS)
114 | return;
115 |
116 | for (int8_t i = 0; i < 8; i++)
117 | {
118 | g_LED[k * 8 + i].mode = p8bytes[i];
119 | }
120 | }
121 |
122 |
123 | static void update_pwm(uint8_t *pwm, int8_t n, uint16_t t)
124 | {
125 | for (int8_t i = 0; i < n; i++)
126 | {
127 | if (g_LED[i].enable == 0)
128 | {
129 | pwm[i] = 0;
130 | }
131 | else
132 | {
133 | uint8_t b = g_LED[i].mode;
134 |
135 | if ((b >= 0) && (b <= MAX_PWM))
136 | {
137 | // constant brightness
138 |
139 | pwm[i] = b;
140 | }
141 | else if (b == 129)
142 | {
143 | // triangle
144 |
145 | uint16_t x = t >> 8;
146 | if (x & 0x80) // 128..255
147 | x = 255 - x;
148 |
149 | pwm[i] = (MAX_PWM * x) >> 7;
150 |
151 | }
152 | else if (b == 130)
153 | {
154 | // rect
155 |
156 | pwm[i] = (t & 0x8000) ? MAX_PWM : 0;
157 | }
158 | else if (b == 131)
159 | {
160 | // fall
161 |
162 | uint16_t x = 255 - (t >> 8);
163 |
164 | pwm[i] = (MAX_PWM * x) >> 8;
165 | }
166 | else if (b == 132)
167 | {
168 | // rise
169 |
170 | uint16_t x = t >> 8;
171 |
172 | pwm[i] = (MAX_PWM * x) >> 8;
173 | }
174 | else
175 | {
176 | // unexpected!
177 |
178 | pwm[i] = 0;
179 | }
180 | }
181 | }
182 | }
183 |
184 |
185 | ISR(LED_TIMER_vect)
186 | {
187 | #if defined(ENABLE_PROFILING)
188 | profile_start();
189 | #endif
190 |
191 | static int8_t counter = 0;
192 | static uint16_t t = 0;
193 | static uint8_t pwm[NUMBER_OF_LEDS];
194 |
195 | counter--;
196 |
197 | if (counter < 0)
198 | {
199 | // reset counter
200 | counter = MAX_PWM - 1; // pwm value of MAX_PWM should be allways 'on', 0 should be allways 'off'
201 |
202 | // increment time counter
203 | t += g_dt;
204 |
205 | // update pwm values
206 | update_pwm(pwm, sizeof(pwm) / sizeof(pwm[0]), t);
207 | }
208 |
209 | // set or clear all defined pins
210 |
211 | #define MAP(X, pin, inv) if ((pwm[X##pin##_index] > counter) == (!inv)) { PORT##X |= (1 << pin); } else { PORT##X &= ~(1 << pin); }
212 | LED_MAPPING_TABLE(MAP)
213 | #undef MAP
214 | }
215 |
216 |
217 | static void led_ports_init(void)
218 | {
219 | #define MAP(X, pin, inv) \
220 | PORT##X &= ~(1 << pin); \
221 | DDR##X |= (1 << pin);
222 | LED_MAPPING_TABLE(MAP)
223 | #undef MAP
224 | }
225 |
226 | #endif
227 |
--------------------------------------------------------------------------------
/firmware/led.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef LWCLONE_LED_H__INCLUDED
18 | #define LWCLONE_LED_H__INCLUDED
19 |
20 | #include
21 |
22 | void led_init(void);
23 | void led_update(uint8_t *p8bytes);
24 |
25 |
26 |
27 | #endif
28 |
--------------------------------------------------------------------------------
/firmware/lufa.mk:
--------------------------------------------------------------------------------
1 |
2 | # --------------------------------------
3 | # LUFA Library
4 | # Copyright (C) Dean Camera, 2012.
5 | #
6 | # dean [at] fourwalledcubicle [dot] com
7 | # www.lufa-lib.org
8 | #
9 | # --------------------------------------
10 | # LUFA Project Makefile.
11 | # --------------------------------------
12 |
13 | ARCH = AVR8
14 | BOARD = USER
15 | F_USB = $(F_CPU)
16 | OPTIMIZATION = s
17 | LUFA_PATH = $(PARENT_PATH)/lufa/LUFA
18 | SRC = $(LWCLONE_SRC) $(LUFA_SRC_USB)
19 | CC_FLAGS = -DUSE_LUFA_CONFIG_HEADER -I$(TARGET_PATH) -I$(PARENT_PATH)
20 | LD_FLAGS =
21 |
22 | # Default target
23 | all:
24 |
25 | # Include LUFA build script makefiles
26 | include $(LUFA_PATH)/Build/lufa_core.mk
27 | include $(LUFA_PATH)/Build/lufa_sources.mk
28 | include $(LUFA_PATH)/Build/lufa_build.mk
29 | include $(LUFA_PATH)/Build/lufa_cppcheck.mk
30 | include $(LUFA_PATH)/Build/lufa_doxygen.mk
31 | include $(LUFA_PATH)/Build/lufa_dfu.mk
32 | include $(LUFA_PATH)/Build/lufa_hid.mk
33 | include $(LUFA_PATH)/Build/lufa_avrdude.mk
34 | include $(LUFA_PATH)/Build/lufa_atprogram.mk
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/firmware/main_led.c:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 |
25 | #include
26 | #include "comm.h"
27 | #include "led.h"
28 | #include "panel.h"
29 |
30 |
31 | int main(void)
32 | {
33 | clock_init();
34 | comm_init();
35 | led_init();
36 | panel_init();
37 |
38 | set_sleep_mode(SLEEP_MODE_IDLE);
39 |
40 | sei();
41 |
42 | DbgOut(DBGINFO, "main_led, enter main loop");
43 |
44 | for (;;)
45 | {
46 | // process LED messages
47 |
48 | #if defined(LED_TIMER_vect)
49 |
50 | msg_t * const prxmsg = msg_recv();
51 |
52 | if (prxmsg != NULL)
53 | {
54 | DbgOut(DBGINFO, "main_led, message received");
55 |
56 | // is the message valid?
57 |
58 | if (prxmsg->nlen != 8)
59 | {
60 | DbgOut(DBGERROR, "main_led, invalid framesize");
61 | }
62 | else
63 | {
64 | // process the data
65 | led_update(&prxmsg->data[0]);
66 | }
67 |
68 | msg_release();
69 |
70 | continue;
71 | }
72 |
73 | #endif
74 |
75 | // process panel changes
76 |
77 | #if defined(PANEL_TASK)
78 |
79 | uint8_t * pdata = NULL;
80 | uint8_t const ndata = panel_get_report(&pdata);
81 |
82 | if (ndata > 0)
83 | {
84 | msg_t * const ptxmsg = msg_prepare();
85 |
86 | if (ptxmsg != NULL)
87 | {
88 | memcpy(&ptxmsg->data[0], pdata, ndata);
89 | ptxmsg->nlen = ndata;
90 | msg_send();
91 | }
92 | else
93 | {
94 | DbgOut(DBGERROR, "main_led, tx buffer overflow");
95 | }
96 |
97 | continue;
98 | }
99 |
100 | #endif
101 |
102 | // if we are here, there was no new message and no new panel report
103 | // ==> enter idle mode
104 |
105 | sleep_ms(0);
106 | }
107 |
108 | return 0;
109 | }
110 |
--------------------------------------------------------------------------------
/firmware/main_usb.c:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 | #include
23 | #include
24 | #include
25 | #include
26 |
27 | #include
28 | #include "descriptors.h"
29 |
30 | #include
31 | #include "comm.h"
32 | #include "led.h"
33 | #include "panel.h"
34 |
35 |
36 | #define LWCCONFIG_CMD_SETID 65
37 | #define LWCCONFIG_CMD_DFU 66
38 |
39 | #define LWC_CONFIG_IDENTIFIER 0xA62817B2 // some magic number(s)
40 | #define RESETSTATE_BOOTLOADER 0x42B8217C
41 |
42 | #define OFFSET_OF(_struct_, _member_) (((uint8_t*)&(((_struct_*)NULL)->_member_)) - (uint8_t*)NULL)
43 |
44 |
45 | uint32_t g_resetstate __attribute__ ((section (".noinit")));
46 |
47 | typedef struct {
48 | uint32_t id;
49 | uint8_t ledwiz_id;
50 | uint8_t reserved[7];
51 | } lwc_config_t;
52 |
53 | static struct {
54 | uint8_t reserved[16];
55 | uint8_t configdata[sizeof(lwc_config_t)];
56 | } g_eeprom_table EEMEM;
57 |
58 |
59 | static void hardware_init(void);
60 | static void main_task(void);
61 | static uint8_t* buffer_lock(void);
62 | static void buffer_unlock(void);
63 | static void hardware_restart(bool enter_bootloader);
64 | static void configure_device(void);
65 |
66 |
67 | // Main program entry point. This routine configures the hardware required by the application, then
68 | // enters a loop to run the application tasks in sequence.
69 |
70 | int main(void)
71 | {
72 | hardware_init();
73 | USB_Init();
74 |
75 | sei();
76 |
77 | DbgOut(DBGINFO, "enter main loop");
78 |
79 | do {
80 | USB_USBTask();
81 | } while (USB_DeviceState != DEVICE_STATE_Configured);
82 |
83 | for (;;)
84 | {
85 | USB_USBTask();
86 | main_task();
87 | sleep_ms(0);
88 | }
89 | }
90 |
91 |
92 | static void hardware_init(void)
93 | {
94 | uint8_t const mcusr = MCUSR; // save status register
95 |
96 | // Disable watchdog if enabled by bootloader/fuses
97 | MCUSR &= ~(1 << WDRF);
98 | wdt_disable();
99 |
100 | #if defined(BOOTLOADER_START_ADDR)
101 | // if that was a reset due to watchdog timeout that we issued, call the bootloader
102 | if ((mcusr & (1 << WDRF)) &&
103 | (g_resetstate == RESETSTATE_BOOTLOADER))
104 | {
105 | g_resetstate = 0;
106 | void (*bootloader)(void) = (void*)(BOOTLOADER_START_ADDR);
107 | bootloader();
108 | }
109 | #endif
110 |
111 | // Disable clock division
112 | clock_prescale_set(clock_div_1);
113 |
114 | set_sleep_mode(SLEEP_MODE_IDLE);
115 |
116 | // initialize LED driver and UART and panel
117 | clock_init();
118 | comm_init();
119 | led_init();
120 | panel_init();
121 |
122 | // config
123 | configure_device();
124 | }
125 |
126 |
127 | // load current configuration from eeprom and set USB product ID
128 |
129 | static void configure_device(void)
130 | {
131 | lwc_config_t cfg;
132 | eeprom_read_block((void*)&cfg, g_eeprom_table.configdata, sizeof(cfg));
133 |
134 | if (cfg.id != LWC_CONFIG_IDENTIFIER)
135 | {
136 | memset(&cfg, 0x00, sizeof(cfg));
137 | cfg.id = LWC_CONFIG_IDENTIFIER;
138 | cfg.ledwiz_id = USB_PRODUCT_ID & 0x0F;
139 |
140 | eeprom_write_block((void*)&cfg, g_eeprom_table.configdata, sizeof(cfg));
141 | }
142 |
143 | // set USB product ID
144 | uint16_t const product_id = (USB_PRODUCT_ID & ~0x000F) | (cfg.ledwiz_id & 0x0F);
145 | SetProductID(product_id);
146 | }
147 |
148 |
149 | static void main_task(void)
150 | {
151 | #if defined(ENABLE_PANEL_DEVICE)
152 |
153 | /* Select the Joystick Report Endpoint */
154 | Endpoint_SelectEndpoint(PANEL_EPADDR);
155 |
156 | /* Check to see if the host is ready for another packet */
157 | if (!Endpoint_IsINReady())
158 | return;
159 |
160 | #if defined(DATA_RX_UART_vect)
161 |
162 | msg_t * const pmsg = msg_recv();
163 |
164 | if (pmsg != NULL)
165 | {
166 | DbgOut(DBGINFO, "main_usb, message received");
167 |
168 | // is the message valid?
169 |
170 | if (pmsg->nlen < 2 || pmsg->nlen > 8)
171 | {
172 | DbgOut(DBGERROR, "main_usb, invalid framesize");
173 | }
174 | else
175 | {
176 | /* Write Joystick Report Data */
177 | Endpoint_Write_Stream_LE(&pmsg->data[0], pmsg->nlen, NULL);
178 |
179 | /* Finalize the stream transfer to send the last packet */
180 | Endpoint_ClearIN();
181 | }
182 |
183 | msg_release();
184 | }
185 |
186 | #elif defined(PANEL_TASK)
187 |
188 | uint8_t * pdata;
189 | uint8_t const ndata = panel_get_report(&pdata);
190 |
191 | if (ndata > 0)
192 | {
193 | /* Write Joystick Report Data */
194 | Endpoint_Write_Stream_LE(pdata, ndata, NULL);
195 |
196 | /* Finalize the stream transfer to send the last packet */
197 | Endpoint_ClearIN();
198 | }
199 |
200 | #else
201 |
202 | #error "invalid configuration, panel is enabled but no uart-rx-ISR or panel-timer-ISR"
203 |
204 | #endif
205 |
206 | #endif
207 | }
208 |
209 |
210 | // Event handler for the USB_Connect event. This indicates that the device is enumerating via the status LEDs and
211 | // starts the library USB task to begin the enumeration and USB management process.
212 |
213 | void EVENT_USB_Device_Connect(void)
214 | {
215 | }
216 |
217 | // Event handler for the USB_Disconnect event. This indicates that the device is no longer connected to a host via
218 | // the status LEDs and stops the USB management and joystick reporting tasks.
219 |
220 | void EVENT_USB_Device_Disconnect(void)
221 | {
222 | }
223 |
224 | // Event handler for the library USB Configuration Changed event.
225 |
226 | void EVENT_USB_Device_ConfigurationChanged(void)
227 | {
228 | // Setup HID Report Endpoint
229 |
230 | Endpoint_ConfigureEndpoint(MISC_EPADDR, EP_TYPE_INTERRUPT, MISC_EPSIZE, 1);
231 | #if defined(ENABLE_LED_DEVICE)
232 | Endpoint_ConfigureEndpoint(LED_EPADDR, EP_TYPE_INTERRUPT, LED_EPSIZE, 1);
233 | #endif
234 | #if defined(ENABLE_PANEL_DEVICE)
235 | Endpoint_ConfigureEndpoint(PANEL_EPADDR, EP_TYPE_INTERRUPT, PANEL_EPSIZE, 1);
236 | #endif
237 | }
238 |
239 | // Event handler for the USB_ControlRequest event. This is used to catch and process control requests sent to
240 | // the device from the USB host before passing along unhandled control requests to the library for processing
241 | // internally.
242 |
243 | void EVENT_USB_Device_ControlRequest(void)
244 | {
245 | // Handle HID Class specific requests
246 | switch (USB_ControlRequest.bRequest)
247 | {
248 | case HID_REQ_GetReport:
249 | if (USB_ControlRequest.bmRequestType == (REQDIR_DEVICETOHOST | REQTYPE_CLASS | REQREC_INTERFACE))
250 | {
251 | Endpoint_ClearSETUP();
252 |
253 | uint8_t zero = 0;
254 |
255 | // Write one 'zero' byte report data to the control endpoint
256 | Endpoint_Write_Control_Stream_LE(&zero, 1);
257 | Endpoint_ClearOUT();
258 | }
259 | break;
260 |
261 | #if defined(ENABLE_LED_DEVICE)
262 | case HID_REQ_SetReport:
263 | if (USB_ControlRequest.bmRequestType == (REQDIR_HOSTTODEVICE | REQTYPE_CLASS | REQREC_INTERFACE))
264 | {
265 | Endpoint_ClearSETUP();
266 |
267 | DbgOut(DBGINFO, "HID_REQ_SetReport, bRequest: 0x%02X, wIndex: %d, wLength: %d, wValue: %d",
268 | USB_ControlRequest.bRequest, USB_ControlRequest.wIndex, USB_ControlRequest.wLength, USB_ControlRequest.wValue);
269 |
270 | uint8_t * const pdata = buffer_lock();
271 |
272 | if (pdata != NULL)
273 | {
274 | // Read the report data from the control endpoint
275 | Endpoint_Read_Control_Stream_LE(pdata, 8);
276 |
277 | DbgOut(DBGINFO, "HID_REQ_SetReport: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
278 | pdata[0], pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], pdata[6], pdata[7]);
279 |
280 | // if this is a special command to set the ledwiz ID, execute it
281 | if (pdata[0] == LWCCONFIG_CMD_SETID)
282 | {
283 | const uint8_t id = pdata[1];
284 | const uint8_t check = ~id;
285 |
286 | if (pdata[2] == 0xFF &&
287 | pdata[3] == 0xFF &&
288 | pdata[4] == 0xFF &&
289 | pdata[5] == 0xFF &&
290 | pdata[6] == 0xFF &&
291 | pdata[7] == check)
292 | {
293 | eeprom_update_byte(
294 | &g_eeprom_table.configdata[0] + OFFSET_OF(lwc_config_t, ledwiz_id),
295 | id & 0x0F);
296 |
297 | hardware_restart(false);
298 | }
299 | }
300 |
301 | buffer_unlock();
302 | }
303 | else
304 | {
305 | uint8_t temp[8];
306 | Endpoint_Read_Control_Stream_LE(temp, 8); // drop data
307 |
308 | DbgOut(DBGERROR, "HID_REQ_SetReport: buffer overflow");
309 | }
310 |
311 | Endpoint_ClearIN();
312 | }
313 | break;
314 | #endif
315 | }
316 | }
317 |
318 |
319 | static void hardware_restart(bool enter_bootloader)
320 | {
321 | // detach from the bus
322 | USB_Disable();
323 | USB_Detach();
324 |
325 | // Disable all interrupts
326 | cli();
327 |
328 | // Wait some time for the USB detachment to register on the host
329 | _delay_ms(250);
330 |
331 | // force a reset via watchdog timeout
332 | wdt_enable(WDTO_15MS);
333 |
334 | // set persistant variable, so we know that we issued the reset
335 | g_resetstate = enter_bootloader ? RESETSTATE_BOOTLOADER : 0;
336 |
337 | for (;;) {;}
338 | }
339 |
340 |
341 | #if defined(LED_TIMER_vect)
342 |
343 | static uint8_t g_databuffer[8];
344 |
345 | static uint8_t * buffer_lock(void)
346 | {
347 | return &g_databuffer[0];
348 | }
349 |
350 | void buffer_unlock(void)
351 | {
352 | led_update(&g_databuffer[0]);
353 | }
354 |
355 | #endif
356 |
357 |
358 | #if defined(DATA_TX_UART_vect)
359 |
360 | static uint8_t * buffer_lock(void)
361 | {
362 | msg_t * const pmsg = msg_prepare();
363 |
364 | if (pmsg == NULL) {
365 | return NULL;
366 | }
367 |
368 | pmsg->nlen = 8;
369 |
370 | return &pmsg->data[0];
371 | }
372 |
373 | static void buffer_unlock(void)
374 | {
375 | msg_send();
376 | }
377 |
378 | #endif
379 |
--------------------------------------------------------------------------------
/firmware/makefile:
--------------------------------------------------------------------------------
1 |
2 | DIRS = arduino_mega2560 arduino_leonardo arduino_uno breakout_32u2 arduino_promicro
3 |
4 | all:
5 | for i in $(DIRS); do make --directory=$$i clean; make --directory=$$i all; done
6 |
7 | clean:
8 | for i in $(DIRS); do make --directory=$$i clean; done
9 |
--------------------------------------------------------------------------------
/firmware/panel.c:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | /* Name: hid_input.c
18 | * Project: V-USB Mame Panel
19 | * Author: Andreas Oberdorfer
20 | * Creation Date: 2009-09-19
21 | * Copyright 2009 - 2011 Andreas Oberdorfer
22 | * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
23 | */
24 |
25 | #include
26 | #include
27 | #include
28 | #include
29 | #include
30 | #include
31 |
32 | #include
33 | #include "panel.h"
34 | #include "comm.h"
35 | #include "keydefs.h"
36 | #include "clock.h"
37 |
38 |
39 | #if !defined(PANEL_TASK)
40 | void panel_init(void) {}
41 | uint8_t panel_get_report(uint8_t **ppdata) { return 0; }
42 | #else
43 |
44 |
45 | const int DEBOUNCE = 5;
46 |
47 | // derive the number of inputs from the table, let the compiler check that no pin is used twice
48 | enum {
49 | #define MAP(port, pin, normal_id, shift_id) port##pin##_index,
50 | PANEL_MAPPING_TABLE(MAP)
51 | NUMBER_OF_INPUTS,
52 | #undef MAP
53 | #if defined(LED_MAPPING_TABLE)
54 | #define MAP(port, pin, inv) port##pin##_index,
55 | LED_MAPPING_TABLE(MAP)
56 | #undef MAP
57 | #endif
58 | #if defined(ADC_MAPPING_TABLE)
59 | #define MAP(port, pin, mux, minval, maxval, joyid, axis) port##pin##_index,
60 | ADC_MAPPING_TABLE(MAP)
61 | #undef MAP
62 | #endif
63 | };
64 |
65 | #if defined(ADC_MAPPING_TABLE)
66 | enum {
67 | #define MAP(port, pin, mux, minval, maxval, joyid, axis) port##pin##_adcindex,
68 | ADC_MAPPING_TABLE(MAP)
69 | #undef MAP
70 | NUM_ADC_CHANNELS
71 | };
72 | #endif
73 |
74 | static uint8_t ReportBuffer[8];
75 | static uint8_t InputState[NUMBER_OF_INPUTS];
76 | static uint8_t shift_key = 0;
77 | static uint8_t shift_key_cleanup = 0;
78 | static uint8_t need_key_update = 0;
79 | static uint8_t need_consumer_update = 0;
80 |
81 | #if (NUM_JOYSTICKS >= 1)
82 | static uint8_t need_joystick_update[NUM_JOYSTICKS];
83 | #endif
84 |
85 | #if (USE_ACCELGYRO)
86 | static uint8_t need_accelgyro_update = 0;
87 | #endif
88 |
89 | #if (USE_MOUSE != 0)
90 | static uint8_t need_mouse_update = 0;
91 | static uint8_t mouse_x_last_clk_state = 0;
92 | static uint8_t mouse_x_last_dir_state = 0;
93 | static int8_t mouse_x_count = 0;
94 | static uint8_t mouse_y_last_clk_state = 0;
95 | static uint8_t mouse_y_last_dir_state = 0;
96 | static int8_t mouse_y_count = 0;
97 | #if !defined(MOUSE_X_DELTA)
98 | #define MOUSE_X_DELTA 1
99 | #endif
100 | #if !defined(MOUSE_Y_DELTA)
101 | #define MOUSE_Y_DELTA 1
102 | #endif
103 | #endif
104 |
105 | #if defined(ENABLE_ANALOG_INPUT)
106 | static uint16_t adc_values[NUM_ADC_CHANNELS] = {0};
107 | static const uint8_t adc_mux_table[NUM_ADC_CHANNELS] = {
108 | #define MAP(port, pin, mux, minval, maxval, joyid, axis) mux,
109 | ADC_MAPPING_TABLE(MAP)
110 | #undef MAP
111 | };
112 | #endif
113 |
114 |
115 | // Shift switch off
116 | PROGMEM const uint8_t NormalMapping[NUMBER_OF_INPUTS] =
117 | {
118 | #define MAP(port, pin, normal_id, shift_id) normal_id,
119 | PANEL_MAPPING_TABLE(MAP)
120 | #undef MAP
121 | };
122 |
123 | // Shift switch on
124 | PROGMEM const uint8_t ShiftMapping[NUMBER_OF_INPUTS] =
125 | {
126 | #define MAP(port, pin, normal_id, shift_id) shift_id,
127 | PANEL_MAPPING_TABLE(MAP)
128 | #undef MAP
129 | };
130 |
131 |
132 | #define IsKeyDown(index) (InputState[index] & 0x80)
133 |
134 | static uint8_t GetKeyNormalMap(unsigned char index) { return (index < NUMBER_OF_INPUTS) ? pgm_read_byte(NormalMapping + index) : 0; }
135 | static uint8_t GetKeyShiftMap(unsigned char index) { return (index < NUMBER_OF_INPUTS) ? pgm_read_byte(ShiftMapping + index): 0; }
136 | static uint8_t IsKeyboardCode(uint8_t key) { return (key >= KEY_A) && (key <= MOD_RightGUI); }
137 | static uint8_t IsModifierCode(uint8_t key) { return (key >= MOD_LeftControl) && (key <= MOD_RightGUI); }
138 | static uint8_t IsConsumerCode(uint8_t key) { return (key >= AC_VolumeUp) && (key <= AC_Mute); }
139 | static uint8_t GetKey(uint8_t index) { return (shift_key != 0) ? GetKeyShiftMap(index) : GetKeyNormalMap(index); }
140 |
141 |
142 | #if (NUM_JOYSTICKS >= 1)
143 |
144 | static uint8_t IsJoystickCode(uint8_t key, uint8_t joy)
145 | {
146 | key -= (joy * NR_OF_EVENTS_PER_JOY);
147 |
148 | return (key >= J1_Left) && (key < (J1_Left + NR_OF_EVENTS_PER_JOY));
149 | }
150 |
151 | static uint8_t NeedJoystickUpdate(void)
152 | {
153 | uint8_t i;
154 |
155 | for (i = 0; i < NUM_JOYSTICKS; i++)
156 | {
157 | if (need_joystick_update[i]) {
158 | return 1;
159 | }
160 | }
161 |
162 | return 0;
163 | }
164 |
165 | #endif
166 |
167 | #if (USE_ACCELGYRO)
168 |
169 | static uint8_t IsAccelGyroCode(uint8_t key)
170 | {
171 | key -= (4 * NR_OF_EVENTS_PER_JOY);
172 |
173 | return (key >= J1_Left) && (key < (J1_Left + NR_OF_EVENTS_PER_JOY));
174 | }
175 |
176 | #endif
177 |
178 | #if (USE_MOUSE != 0)
179 |
180 | static uint8_t IsMouseButtonCode(uint8_t key)
181 | {
182 | return (key >= MB_Left) && (key <= MB_Middle);
183 | }
184 |
185 | static void MouseMoveX(uint8_t direction)
186 | {
187 | if (direction)
188 | {
189 | if (mouse_x_count > -(127 - MOUSE_X_DELTA)) {
190 | mouse_x_count -= MOUSE_X_DELTA;
191 | }
192 | }
193 | else
194 | {
195 | if (mouse_x_count < (127 - MOUSE_X_DELTA)) {
196 | mouse_x_count += MOUSE_X_DELTA;
197 | }
198 | }
199 |
200 | need_mouse_update = 1;
201 | }
202 |
203 | static void MouseMoveY(uint8_t direction)
204 | {
205 | if (direction)
206 | {
207 | if (mouse_y_count > -(127 - MOUSE_Y_DELTA)) {
208 | mouse_y_count -= MOUSE_Y_DELTA;
209 | }
210 | }
211 | else
212 | {
213 | if (mouse_y_count < (127 - MOUSE_Y_DELTA)) {
214 | mouse_y_count += MOUSE_Y_DELTA;
215 | }
216 | }
217 |
218 | need_mouse_update = 1;
219 | }
220 |
221 | static void CheckMouseUpdate(void)
222 | {
223 | #if defined(MOUSE_X_CLK_INDEX) && defined(MOUSE_X_DIR_INDEX)
224 |
225 | uint8_t mouse_clk_state = InputState[MOUSE_X_CLK_INDEX];
226 | uint8_t mouse_dir_state = InputState[MOUSE_X_DIR_INDEX];
227 |
228 | if (mouse_clk_state != mouse_x_last_clk_state)
229 | {
230 | if (mouse_dir_state == mouse_x_last_dir_state) {
231 | MouseMoveX(mouse_clk_state ^ mouse_dir_state);
232 | }
233 |
234 | mouse_x_last_clk_state = mouse_clk_state;
235 | }
236 |
237 | if (mouse_dir_state != mouse_x_last_dir_state)
238 | {
239 | if (mouse_clk_state == mouse_x_last_clk_state) {
240 | MouseMoveX(!(mouse_clk_state ^ mouse_dir_state));
241 | }
242 |
243 | mouse_x_last_dir_state = mouse_dir_state;
244 | }
245 |
246 | #endif
247 |
248 | #if defined(MOUSE_Y_CLK_INDEX) && defined(MOUSE_Y_DIR_INDEX)
249 |
250 | mouse_clk_state = InputState[MOUSE_Y_CLK_INDEX];
251 | mouse_dir_state = InputState[MOUSE_Y_DIR_INDEX];
252 |
253 | if (mouse_clk_state != mouse_y_last_clk_state)
254 | {
255 | if (mouse_dir_state == mouse_y_last_dir_state) {
256 | MouseMoveY(mouse_clk_state ^ mouse_dir_state);
257 | }
258 |
259 | mouse_y_last_clk_state = mouse_clk_state;
260 | }
261 |
262 | if (mouse_dir_state != mouse_y_last_dir_state)
263 | {
264 | if (mouse_clk_state == mouse_y_last_clk_state) {
265 | MouseMoveY(!(mouse_clk_state ^ mouse_dir_state));
266 | }
267 |
268 | mouse_y_last_dir_state = mouse_dir_state;
269 | }
270 |
271 | #endif
272 | }
273 |
274 | static uint8_t NeedMouseUpdate(void) { return need_mouse_update; }
275 |
276 | #endif
277 |
278 | void panel_init(void)
279 | {
280 | #if (NUM_JOYSTICKS >= 1)
281 | memset(&need_joystick_update[0], 0x00, sizeof(need_joystick_update));
282 | #endif
283 |
284 | #define MAP(port, pin, normal_id, shift_id) \
285 | PORT##port |= (1 << pin); \
286 | DDR##port &= ~(1 << pin);
287 | PANEL_MAPPING_TABLE(MAP)
288 | #undef MAP
289 |
290 | #if defined(ENABLE_ANALOG_INPUT) && defined(ADC_MAPPING_TABLE)
291 | #define MAP(port, pin, mux, minval, maxval, joyid, axis) \
292 | PORT##port &= ~(1 << pin); \
293 | DDR##port &= ~(1 << pin);
294 | ADC_MAPPING_TABLE(MAP)
295 | #undef MAP
296 |
297 | ADC_init();
298 | #endif
299 | };
300 |
301 | static void SetNeedUpdate(uint8_t index)
302 | {
303 | uint8_t key = GetKey(index);
304 |
305 | if (IsConsumerCode(key))
306 | {
307 | need_consumer_update = 1;
308 | return;
309 | }
310 |
311 | if (IsKeyboardCode(key))
312 | {
313 | need_key_update = 1;
314 | return;
315 | }
316 |
317 | #if (USE_MOUSE != 0)
318 | if (IsMouseButtonCode(key))
319 | {
320 | need_mouse_update = 1;
321 | return;
322 | }
323 | #endif
324 |
325 | #if (NUM_JOYSTICKS >= 1)
326 | {
327 | uint8_t i;
328 |
329 | for (i = 0; i < NUM_JOYSTICKS; i++)
330 | {
331 | if (IsJoystickCode(key, i))
332 | {
333 | need_joystick_update[i] = 1;
334 | return;
335 | }
336 | }
337 | }
338 | #endif
339 |
340 | #if (USE_ACCELGYRO)
341 | if (IsAccelGyroCode(key))
342 | {
343 | need_accelgyro_update = 1;
344 | return;
345 | }
346 | #endif
347 | }
348 |
349 | #if defined(SHIFT_SWITCH_INDEX)
350 |
351 | static void ShiftKeyCleanUp(void)
352 | {
353 | if (shift_key_cleanup == 1)
354 | {
355 | uint8_t i;
356 | shift_key_cleanup = 2;
357 |
358 | for (i = 0; i < NUMBER_OF_INPUTS; i++)
359 | {
360 | if (i != SHIFT_SWITCH_INDEX)
361 | {
362 | if (InputState[i] != 0)
363 | {
364 | if (GetKeyNormalMap(i) != GetKeyShiftMap(i))
365 | {
366 | SetNeedUpdate(i);
367 | InputState[i] = 0;
368 | }
369 | }
370 | }
371 | }
372 | }
373 |
374 | if (shift_key_cleanup == 2)
375 | {
376 | bool no_update = !need_consumer_update && !need_key_update;
377 |
378 | #if (USE_MOUSE != 0)
379 | no_update = no_update && !NeedMouseUpdate();
380 | #endif
381 |
382 | #if (NUM_JOYSTICKS >= 1)
383 | no_update = no_update && !NeedJoystickUpdate();
384 | #endif
385 |
386 | #if (USE_ACCELGYRO)
387 | no_update = no_update && !need_accelgyro_update;
388 | #endif
389 |
390 | if (no_update)
391 | {
392 | shift_key_cleanup = 0;
393 | shift_key = IsKeyDown(SHIFT_SWITCH_INDEX);
394 | }
395 | }
396 | }
397 |
398 | #endif
399 |
400 | static uint8_t NeedUpdate(void)
401 | {
402 | #if defined(SHIFT_SWITCH_INDEX)
403 | ShiftKeyCleanUp();
404 | #endif
405 |
406 | #if (USE_MOUSE != 0)
407 | if (NeedMouseUpdate())
408 | {
409 | need_mouse_update = 0;
410 | return ID_Mouse;
411 | }
412 | #endif
413 |
414 | if (need_key_update)
415 | {
416 | need_key_update = 0;
417 | return ID_Keyboard;
418 | }
419 |
420 | if (need_consumer_update)
421 | {
422 | need_consumer_update = 0;
423 | return ID_Consumer;
424 | }
425 |
426 | uint8_t analog_update[NUM_JOYSTICKS + 1] = {0};
427 | static uint8_t analog_counter[NUM_JOYSTICKS + 1];
428 |
429 | #if (NUM_JOYSTICKS >= 1)
430 | for (uint8_t i = 0; i < NUM_JOYSTICKS; i++)
431 | {
432 | if (analog_counter[i] < 0xFF && need_joystick_update[i])
433 | analog_counter[i] += 1;
434 | }
435 | #endif
436 |
437 | #if (USE_ACCELGYRO)
438 | if (analog_counter[NUM_JOYSTICKS] < 0xFF && need_accelgyro_update)
439 | analog_counter[NUM_JOYSTICKS] += 1;
440 | #endif
441 |
442 | #if defined(ENABLE_ANALOG_INPUT) && defined(ADC_MAPPING_TABLE)
443 |
444 | #define MAP(port, pin, mux, minval, maxval, joyid, axis) \
445 | if (joyid >= ID_Joystick1 && (joyid - ID_Joystick1) < NUM_JOYSTICKS) { analog_update[joyid - ID_Joystick1] = 1; } else \
446 | if (joyid == ID_AccelGyro) { analog_update[NUM_JOYSTICKS] = 1; }
447 | ADC_MAPPING_TABLE(MAP)
448 | #undef MAP
449 |
450 | for (uint8_t i = 0; i < sizeof(analog_update) / sizeof(analog_update[0]); i++)
451 | {
452 | if (analog_counter[i] < 0xFF && analog_update[i] > 0)
453 | analog_counter[i] += 1;
454 | }
455 |
456 | #endif
457 |
458 | uint8_t ac_max = 0;
459 | int8_t index_max = -1;
460 |
461 | for (int8_t i = 0; i < sizeof(analog_update) / sizeof(analog_update[0]); i++)
462 | {
463 | if (ac_max < analog_counter[i])
464 | {
465 | ac_max = analog_counter[i];
466 | index_max = i;
467 | }
468 | }
469 |
470 | if (index_max >= 0)
471 | {
472 | analog_counter[index_max] = 0;
473 |
474 | #if (NUM_JOYSTICKS >= 1)
475 | if (index_max < NUM_JOYSTICKS) {
476 | need_joystick_update[index_max] = 0;
477 | return index_max + ID_Joystick1;
478 | }
479 | #endif
480 |
481 | #if (USE_ACCELGYRO)
482 | need_accelgyro_update = 0;
483 | return ID_AccelGyro;
484 | #endif
485 | }
486 |
487 | return ID_Unknown;
488 | }
489 |
490 | static void SetInputCount(uint8_t index, uint8_t condition)
491 | {
492 | #if (USE_MOUSE != 0) && defined(MOUSE_X_CLK_INDEX) && defined(MOUSE_X_DIR_INDEX)
493 | if ((index == MOUSE_X_CLK_INDEX) || (index == MOUSE_X_DIR_INDEX))
494 | {
495 | InputState[index] = condition;
496 | return;
497 | }
498 | #endif
499 |
500 | #if (USE_MOUSE != 0) && defined(MOUSE_Y_CLK_INDEX) && defined(MOUSE_Y_DIR_INDEX)
501 | if ((index == MOUSE_Y_CLK_INDEX) || (index == MOUSE_Y_DIR_INDEX))
502 | {
503 | InputState[index] = condition;
504 | return;
505 | }
506 | #endif
507 |
508 | if (index >= NUMBER_OF_INPUTS)
509 | {
510 | return;
511 | }
512 |
513 | #if defined(MULTIFIRE_INDEX)
514 | if (index == MULTIFIRE_INDEX)
515 | {
516 | static uint16_t ncycle = 0;
517 | static uint8_t ncount = 0;
518 | static uint8_t ndelay = 0;
519 |
520 | // simple debounce
521 | if (ndelay == 0 && condition)
522 | {
523 | ndelay = (100 / (DELTA_TIME_PANEL_REPORT_MS + 1));
524 | ncount += MULTIFIRE_COUNT;
525 | }
526 | else if (ndelay > 1)
527 | {
528 | ndelay--;
529 | }
530 | else if (ndelay == 1)
531 | {
532 | if (!condition)
533 | ndelay = 0;
534 | }
535 |
536 | condition = 0;
537 |
538 | // state machine to generate multiple events
539 | if (ncount > 0)
540 | {
541 | condition = (ncycle < (100 / (DELTA_TIME_PANEL_REPORT_MS + 1))) ? 1 : 0;
542 |
543 | if (ncycle >= (600 / (DELTA_TIME_PANEL_REPORT_MS + 1)))
544 | {
545 | ncycle = 0;
546 | ncount -= 1;
547 | }
548 | else
549 | {
550 | ncycle += 1;
551 | }
552 | }
553 | }
554 | #endif
555 |
556 | uint8_t changed = 0;
557 | uint8_t count = InputState[index];
558 | uint8_t state = count & 0x80;
559 | count &= 0x7f;
560 |
561 | if (condition)
562 | {
563 | if (count <= DEBOUNCE)
564 | {
565 | if ((count == DEBOUNCE) && !state)
566 | {
567 | changed = 1;
568 | state = 0x80;
569 | }
570 |
571 | count++;
572 | }
573 | else
574 | {
575 | return;
576 | }
577 | }
578 | else
579 | {
580 | if (count > 0)
581 | {
582 | if ((count == 1) && state)
583 | {
584 | changed = 1;
585 | state = 0;
586 | }
587 |
588 | count--;
589 | }
590 | else
591 | {
592 | return;
593 | }
594 | }
595 |
596 | InputState[index] = state | count;
597 |
598 | if (changed)
599 | {
600 | #if defined(SHIFT_SWITCH_INDEX)
601 | if (index == SHIFT_SWITCH_INDEX)
602 | {
603 | shift_key_cleanup = 1;
604 | }
605 | else
606 | #endif
607 | {
608 | SetNeedUpdate(index);
609 | }
610 | }
611 | }
612 |
613 | void panel_ScanInput(void)
614 | {
615 | if (shift_key_cleanup) {
616 | return;
617 | }
618 |
619 | #define MAP(port, pin, normal_id, shift_id) SetInputCount(port##pin##_index, 0 == (PIN##port & (1 << pin)));
620 | PANEL_MAPPING_TABLE(MAP)
621 | #undef MAP
622 |
623 | #if (USE_MOUSE != 0)
624 | CheckMouseUpdate();
625 | #endif
626 | }
627 |
628 | #if (USE_CONSUMER != 0)
629 | static uint8_t ReportConsumer(void)
630 | {
631 | uint8_t i;
632 | uint8_t consumer = 0;
633 |
634 | for (i = 0; i < NUMBER_OF_INPUTS; i++)
635 | {
636 | if (IsKeyDown(i))
637 | {
638 | uint8_t key = GetKey(i);
639 |
640 | if (IsConsumerCode(key)) {
641 | consumer |= ConsumerBit(key);
642 | }
643 | }
644 | }
645 |
646 | ReportBuffer[0] = ID_Consumer;
647 | ReportBuffer[1] = consumer;
648 |
649 | return 2;
650 | }
651 | #endif
652 |
653 | static uint8_t ReportKeyboard(void)
654 | {
655 | uint8_t i;
656 | uint8_t r = 2;
657 |
658 | memset(&ReportBuffer[1], 0x00, sizeof(ReportBuffer) - 1);
659 |
660 | ReportBuffer[0] = ID_Keyboard;
661 |
662 | for (i = 0; i < NUMBER_OF_INPUTS; i++)
663 | {
664 | if (IsKeyDown(i))
665 | {
666 | uint8_t key = GetKey(i);
667 |
668 | if (IsKeyboardCode(key))
669 | {
670 | if (IsModifierCode(key))
671 | {
672 | ReportBuffer[1] |= ModifierBit(key);
673 | }
674 | else
675 | {
676 | if (r < sizeof(ReportBuffer))
677 | {
678 | switch (key)
679 | {
680 | case KM_ALT_F4:
681 | ReportBuffer[1] |= ModifierBit(MOD_LeftAlt);
682 | ReportBuffer[r] = KEY_F4;
683 | break;
684 | case KM_SHIFT_F7:
685 | ReportBuffer[1] |= ModifierBit(MOD_LeftShift);
686 | ReportBuffer[r] = KEY_F7;
687 | break;
688 | default:
689 | ReportBuffer[r] = key;
690 | break;
691 | }
692 |
693 | r++;
694 | }
695 | }
696 | }
697 | }
698 | }
699 |
700 | return sizeof(ReportBuffer);
701 | }
702 |
703 | #if defined(ENABLE_ANALOG_INPUT)
704 |
705 | uint16_t ADC_getvalue(uint8_t id)
706 | {
707 | uint16_t x;
708 |
709 | ATOMIC_BLOCK(ATOMIC_FORCEON)
710 | {
711 | x = adc_values[id];
712 | }
713 |
714 | return x;
715 | }
716 |
717 | static int16_t joyval12(uint16_t x, int16_t minval, int16_t maxval)
718 | {
719 | return (int16_t)(((int32_t)x * (int32_t)(maxval - minval) + (1 << 9)) >> 10) + minval - 2047;
720 | }
721 |
722 | static int8_t joyval8(uint16_t x, int16_t minval, int16_t maxval)
723 | {
724 | return (int8_t)(((int32_t)x * (int32_t)(maxval - minval) + (1 << 9)) >> 10) + minval - 127;
725 | }
726 |
727 | #endif
728 |
729 | #if (NUM_JOYSTICKS >= 1)
730 |
731 | static uint8_t ReportJoystick(uint8_t id)
732 | {
733 | uint8_t i;
734 | int16_t joy_x = 0;
735 | int16_t joy_y = 0;
736 | uint8_t joy_b = 0;
737 |
738 | ReportBuffer[0] = id;
739 |
740 | #if defined(ENABLE_ANALOG_INPUT) && defined(ADC_MAPPING_TABLE)
741 | #define MAP(port, pin, mux, minval, maxval, joyid, axis) \
742 | if ((axis == 0) && (joyid == id)) { joy_x = joyval12(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 4094), (int16_t)(maxval * 4094)); } \
743 | if ((axis == 1) && (joyid == id)) { joy_y = joyval12(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 4094), (int16_t)(maxval * 4094)); }
744 | ADC_MAPPING_TABLE(MAP)
745 | #undef MAP
746 | #endif
747 |
748 | id = (id - ID_Joystick1) * NR_OF_EVENTS_PER_JOY;
749 |
750 | for (i = 0; i < NUMBER_OF_INPUTS; i++)
751 | {
752 | if (IsKeyDown(i))
753 | {
754 | uint8_t key = GetKey(i) - id;
755 | switch (key)
756 | {
757 | case J1_Left:
758 | joy_x = -2047;
759 | break;
760 | case J1_Right:
761 | joy_x = +2047;
762 | break;
763 | case J1_Up:
764 | joy_y = -2047;
765 | break;
766 | case J1_Down:
767 | joy_y = +2047;
768 | break;
769 |
770 | case J1_Button1:
771 | case J1_Button2:
772 | case J1_Button3:
773 | case J1_Button4:
774 | case J1_Button5:
775 | case J1_Button6:
776 | case J1_Button7:
777 | case J1_Button8:
778 | joy_b |= JoyButtonBit(key);
779 | break;
780 |
781 | default:
782 | break;
783 | }
784 | }
785 | }
786 |
787 | ReportBuffer[1] = ((uint16_t)joy_x & 0xFF);
788 | ReportBuffer[2] = (((uint16_t)joy_y & 0x0F) << 4) | (((uint16_t)joy_x >> 8) & 0x0F);
789 | ReportBuffer[3] = (((uint16_t)joy_y >> 4) & 0xFF);
790 | ReportBuffer[4] = joy_b;
791 |
792 | return 5;
793 | }
794 |
795 | #endif
796 |
797 | #if (USE_ACCELGYRO)
798 |
799 | static uint8_t ReportAccelGyro()
800 | {
801 | uint8_t id = ID_AccelGyro;
802 |
803 | int8_t joy_x = 0;
804 | int8_t joy_y = 0;
805 | int8_t joy_z = 0;
806 | int8_t joy_rx = 0;
807 | int8_t joy_ry = 0;
808 | int8_t joy_rz = 0;
809 | uint8_t joy_b = 0;
810 |
811 | ReportBuffer[0] = id;
812 |
813 | #if defined(ENABLE_ANALOG_INPUT) && defined(ADC_MAPPING_TABLE)
814 | #define MAP(port, pin, mux, minval, maxval, joyid, axis) \
815 | if ((axis == 0) && (joyid == id)) { joy_x = joyval8(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 254), (int16_t)(maxval * 254)); } \
816 | if ((axis == 1) && (joyid == id)) { joy_y = joyval8(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 254), (int16_t)(maxval * 254)); } \
817 | if ((axis == 2) && (joyid == id)) { joy_z = joyval8(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 254), (int16_t)(maxval * 254)); } \
818 | if ((axis == 3) && (joyid == id)) { joy_rx = joyval8(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 254), (int16_t)(maxval * 254)); } \
819 | if ((axis == 4) && (joyid == id)) { joy_ry = joyval8(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 254), (int16_t)(maxval * 254)); } \
820 | if ((axis == 5) && (joyid == id)) { joy_rz = joyval8(ADC_getvalue(port##pin##_adcindex), (int16_t)(minval * 254), (int16_t)(maxval * 254)); }
821 | ADC_MAPPING_TABLE(MAP)
822 | #undef MAP
823 | #endif
824 |
825 | id = (id - ID_Joystick1) * NR_OF_EVENTS_PER_JOY;
826 |
827 | for (uint8_t i = 0; i < NUMBER_OF_INPUTS; i++)
828 | {
829 | if (IsKeyDown(i))
830 | {
831 | uint8_t key = GetKey(i) - id;
832 | switch (key)
833 | {
834 | case J1_Left:
835 | joy_x = -127;
836 | break;
837 | case J1_Right:
838 | joy_x = +127;
839 | break;
840 | case J1_Up:
841 | joy_y = -127;
842 | break;
843 | case J1_Down:
844 | joy_y = +127;
845 | break;
846 |
847 | case J1_Button1:
848 | case J1_Button2:
849 | case J1_Button3:
850 | case J1_Button4:
851 | case J1_Button5:
852 | case J1_Button6:
853 | case J1_Button7:
854 | case J1_Button8:
855 | joy_b |= JoyButtonBit(key);
856 | break;
857 |
858 | default:
859 | break;
860 | }
861 | }
862 | }
863 |
864 | ReportBuffer[1] = joy_x;
865 | ReportBuffer[2] = joy_y;
866 | ReportBuffer[3] = joy_z;
867 | ReportBuffer[4] = joy_rx;
868 | ReportBuffer[5] = joy_ry;
869 | ReportBuffer[6] = joy_rz;
870 | ReportBuffer[7] = joy_b;
871 |
872 | return 8;
873 | }
874 |
875 | #endif
876 |
877 |
878 | #if (USE_MOUSE != 0)
879 |
880 | static uint8_t ReportMouse(void)
881 | {
882 | uint8_t i;
883 | uint8_t buttons = 0;
884 |
885 | for (i = 0; i < NUMBER_OF_INPUTS; i++)
886 | {
887 | if (IsKeyDown(i))
888 | {
889 | uint8_t key = GetKey(i);
890 |
891 | if (IsMouseButtonCode(key)) {
892 | buttons |= MouseButtonBit(key);
893 | }
894 | }
895 | }
896 |
897 | ReportBuffer[0] = ID_Mouse;
898 | ReportBuffer[1] = buttons;
899 | ReportBuffer[2] = mouse_x_count;
900 | ReportBuffer[3] = mouse_y_count;
901 | mouse_x_count = 0;
902 | mouse_y_count = 0;
903 |
904 | return 4;
905 | }
906 |
907 | #endif
908 |
909 |
910 | static uint8_t BuildReport(uint8_t id)
911 | {
912 | switch (id)
913 | {
914 | #if (USE_KEYBOARD != 0)
915 | case ID_Keyboard:
916 | return ReportKeyboard();
917 | #endif
918 |
919 | #if (USE_CONSUMER != 0)
920 | case ID_Consumer:
921 | return ReportConsumer();
922 | #endif
923 |
924 | #if (NUM_JOYSTICKS >= 1)
925 | case ID_Joystick4:
926 | case ID_Joystick3:
927 | case ID_Joystick2:
928 | case ID_Joystick1:
929 | return ReportJoystick(id);
930 | #endif
931 |
932 | #if (USE_ACCELGYRO)
933 | case ID_AccelGyro:
934 | return ReportAccelGyro(id);
935 | #endif
936 |
937 | #if (USE_MOUSE != 0)
938 | case ID_Mouse:
939 | return ReportMouse();
940 | #endif
941 |
942 | default:
943 | break;
944 | }
945 |
946 | return 0;
947 | }
948 |
949 | uint8_t panel_get_report(uint8_t **ppdata)
950 | {
951 | if (ppdata == NULL) {
952 | return 0;
953 | }
954 |
955 | static uint16_t time_next_ms = 0;
956 | uint16_t const time_curr_ms = clock_ms();
957 |
958 | if (((int16_t)time_curr_ms - (int16_t)time_next_ms) < 0) {
959 | return 0;
960 | }
961 |
962 | time_next_ms = time_curr_ms + DELTA_TIME_PANEL_REPORT_MS;
963 |
964 | panel_ScanInput();
965 |
966 | uint8_t const id = NeedUpdate();
967 |
968 | if (id == ID_Unknown) {
969 | return 0;
970 | }
971 |
972 | uint8_t const ndata = BuildReport(id);
973 | *ppdata = ReportBuffer;
974 |
975 | return ndata;
976 | }
977 |
978 |
979 | #if defined(ENABLE_ANALOG_INPUT)
980 |
981 | // ADC Interrupt Routine
982 |
983 | ISR(ADC_vect)
984 | {
985 | #if defined(ENABLE_PROFILING)
986 | profile_start();
987 | #endif
988 |
989 | static int i = 0;
990 |
991 | // get value
992 |
993 | adc_values[i] = ADC;
994 |
995 | // cycle
996 |
997 | i -= 1;
998 |
999 | if (i < 0)
1000 | i += NUM_ADC_CHANNELS;
1001 |
1002 | // set mux channel for the next conversion
1003 |
1004 | ADC_setmux(adc_mux_table[i]);
1005 |
1006 | // start new conversion
1007 |
1008 | ADCSRA |= (1 << ADSC);
1009 | }
1010 |
1011 | #endif
1012 |
1013 |
1014 |
1015 | #endif
1016 |
--------------------------------------------------------------------------------
/firmware/panel.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | /* Name: hid_input.h
18 | * Project: V-USB Mame Panel
19 | * Author: Andreas Oberdorfer
20 | * Creation Date: 2009-09-19
21 | * Copyright 2009 - 2011 Andreas Oberdorfer
22 | * License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
23 | */
24 |
25 | #ifndef PANEL_H__INCLUDED
26 | #define PANEL_H__INCLUDED
27 |
28 | #include
29 |
30 |
31 | enum ReportIds
32 | {
33 | ID_Unknown = 0,
34 | ID_Keyboard,
35 | ID_Consumer,
36 | ID_Joystick1,
37 | ID_Joystick2,
38 | ID_Joystick3,
39 | ID_Joystick4,
40 | ID_AccelGyro,
41 | ID_Mouse,
42 | };
43 |
44 | static const uint16_t DELTA_TIME_PANEL_REPORT_MS = 2;
45 |
46 | void panel_init(void);
47 | uint8_t panel_get_report(uint8_t **ppdata);
48 |
49 |
50 |
51 | #endif // PANEL_H__INCLUDED
52 |
--------------------------------------------------------------------------------
/firmware/queue.c:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include "queue.h"
19 |
20 |
21 | static uint8_t fifo_getlevel(fifo_t const *f) { return f->wpos - f->rpos; }
22 | static uint8_t fifo_getfree(fifo_t const *f) { return f->mask - fifo_getlevel(f) + 1; }
23 |
24 |
25 | int8_t queue_push(fifo_t *f, uint8_t x)
26 | {
27 | uint8_t const nfree = fifo_getfree(f);
28 |
29 | if (nfree == 0)
30 | return -1;
31 |
32 | uint8_t const index = f->wpos & f->mask;
33 | f->buf[index] = x;
34 | f->wpos += 1;
35 |
36 | return 0;
37 | }
38 |
39 |
40 | int8_t queue_pop(fifo_t *f, uint8_t *px)
41 | {
42 | uint8_t const ndata = fifo_getlevel(f);
43 |
44 | if (ndata == 0 || px == NULL)
45 | return -1;
46 |
47 | uint8_t const index = f->rpos & f->mask;
48 | *px = f->buf[index];
49 | f->rpos += 1;
50 |
51 | return 0;
52 | }
53 |
54 |
55 | uint8_t* chunk_peek(fifo_t *f)
56 | {
57 | uint8_t const ndata = fifo_getlevel(f);
58 |
59 | if (ndata == 0)
60 | return NULL;
61 |
62 | uint8_t index = f->rpos & f->mask;
63 |
64 | return &f->buf[index];
65 | }
66 |
67 |
68 | void chunk_release(fifo_t *f)
69 | {
70 | f->rpos += f->chunksize;
71 | }
72 |
73 |
74 | uint8_t* chunk_prepare(fifo_t *f)
75 | {
76 | uint8_t const nfree = fifo_getfree(f);
77 |
78 | if (nfree == 0)
79 | return NULL;
80 |
81 | uint8_t index = f->wpos & f->mask;
82 |
83 | return &f->buf[index];
84 | }
85 |
86 |
87 | void chunk_push(fifo_t* f)
88 | {
89 | f->wpos += f->chunksize;
90 | }
91 |
--------------------------------------------------------------------------------
/firmware/queue.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef QUEUE_H_INCLUDED
18 | #define QUEUE_H_INCLUDED
19 |
20 | #include
21 | #include
22 |
23 |
24 | typedef struct {
25 | uint8_t volatile rpos;
26 | uint8_t volatile wpos;
27 | uint8_t chunksize;
28 | uint8_t mask;
29 | uint8_t volatile buf[1];
30 | } fifo_t;
31 |
32 |
33 | // helper to allocate and initialize a fifo buffer
34 | #define CREATE_FIFO(_name_, _num_chunks_log2_, _chunksize_log2_) \
35 | union { \
36 | uint8_t volatile _name_##_buffer__[sizeof(fifo_t) - 1 + (1 << (_num_chunks_log2_ + _chunksize_log2_))]; \
37 | fifo_t fifo; \
38 | } _name_##_fifo__ = { \
39 | .fifo.chunksize = (1 << (_chunksize_log2_)), \
40 | .fifo.mask = ((1 << (_num_chunks_log2_ + _chunksize_log2_)) - 1) \
41 | }; \
42 | fifo_t * const _name_ = &_name_##_fifo__.fifo;
43 |
44 |
45 | int8_t queue_push(fifo_t *f, uint8_t x);
46 | int8_t queue_pop(fifo_t *f, uint8_t *px);
47 |
48 | uint8_t* chunk_prepare(fifo_t *f);
49 | void chunk_push(fifo_t *f);
50 | uint8_t* chunk_peek(fifo_t *f);
51 | void chunk_release(fifo_t *f);
52 |
53 |
54 |
55 | #endif
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | LWCloneU2
2 | =========
3 |
4 | A firmware for Atmel AVR microcontroller for controlling LEDs or Light Bulbs via USB *and* a Joystick/Mouse/Keyboard Encoder.
5 |
6 | The device is compatible with the LED-WIZ controller on the USB protocol level and thus can be used with many existing software.
7 | Additionally the firmware allows to add panel support, i.e. up to 4 yoysticks, 1 mouse, 1 keyboard and more. That is with one board you can get an input encoder and an LED output controller perfectly suited for MAME.
8 |
9 | The LWCloneU2 project contains a compatible driver DLL "ledwiz.dll" replacement that fixes some bugs of the original one and does not block your main application, i.e. the I/O is fully asynchron.
10 |
11 |
12 | Supported Hardware
13 | ==================
14 | - Custom Breakout Board with ATMega32U2
15 | - Arduino Leonardo (ATMega32U4)
16 | - Arduino Mega 2560 (tested with Rev. 3)
17 | - Arduino Uno Rev. 2/3 (untested)
18 |
19 |
20 | Building the firmware
21 | =====================
22 |
23 | In order to build all this, you need a recent toolchain for AVR microcontroller, e.g. the 'AVR Toolchain 3.4.2-1573' from Atmel or the one that is bundled with the Atmel AVRStudio.
24 | Get the sources from the Git repository, then do a 'git submodule update --init' in order to get the required LUFA (USB framework) sources. Then a 'make' should build the firmwares for all supported platforms.
25 |
26 |
27 | Building the Windows DLL
28 | ========================
29 |
30 | There are project files for Visualstudio 2008 Express and Visualstudio 2012 Express. The VS 2012 solution supports creating a 64 bit DLL.
31 |
--------------------------------------------------------------------------------
/schematic/breakout32u2.brd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cithraidt/lwcloneu2/40e39ac1b384716857c1152be3767d8e6d0bd674/schematic/breakout32u2.brd
--------------------------------------------------------------------------------
/schematic/breakout32u2.sch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cithraidt/lwcloneu2/40e39ac1b384716857c1152be3767d8e6d0bd674/schematic/breakout32u2.sch
--------------------------------------------------------------------------------
/win32/driver/build/vs_2008/ledwiz.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 10.00
3 | # Visual C++ Express 2008
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ledwiz", "ledwiz.vcproj", "{E498CD63-429C-4443-BA3E-CC0600379F31}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Release|Win32 = Release|Win32
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {E498CD63-429C-4443-BA3E-CC0600379F31}.Debug|Win32.ActiveCfg = Debug|Win32
13 | {E498CD63-429C-4443-BA3E-CC0600379F31}.Debug|Win32.Build.0 = Debug|Win32
14 | {E498CD63-429C-4443-BA3E-CC0600379F31}.Release|Win32.ActiveCfg = Release|Win32
15 | {E498CD63-429C-4443-BA3E-CC0600379F31}.Release|Win32.Build.0 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/win32/driver/build/vs_2008/ledwiz.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
52 |
55 |
58 |
61 |
70 |
73 |
76 |
79 |
82 |
85 |
88 |
91 |
92 |
101 |
104 |
107 |
110 |
113 |
116 |
133 |
136 |
139 |
142 |
153 |
156 |
159 |
162 |
165 |
168 |
171 |
174 |
175 |
176 |
177 |
178 |
179 |
182 |
183 |
186 |
187 |
190 |
191 |
194 |
195 |
198 |
199 |
200 |
201 |
202 |
203 |
--------------------------------------------------------------------------------
/win32/driver/build/vs_2012/ledwiz.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ledwiz", "ledwiz.vcxproj", "{255DA939-7CAD-4705-A71E-DCCE0FD0FA84}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Debug|x64 = Debug|x64
10 | Release|Win32 = Release|Win32
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Debug|Win32.ActiveCfg = Release|Win32
15 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Debug|Win32.Build.0 = Release|Win32
16 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Debug|x64.ActiveCfg = Release|x64
17 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Debug|x64.Build.0 = Release|x64
18 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Release|Win32.ActiveCfg = Release|Win32
19 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Release|Win32.Build.0 = Release|Win32
20 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Release|x64.ActiveCfg = Release|x64
21 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}.Release|x64.Build.0 = Release|x64
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/win32/driver/build/vs_2012/ledwiz.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {255DA939-7CAD-4705-A71E-DCCE0FD0FA84}
23 | Win32Proj
24 | ledwiz
25 |
26 |
27 |
28 | DynamicLibrary
29 | true
30 | v110
31 | MultiByte
32 |
33 |
34 | DynamicLibrary
35 | true
36 | v110
37 | MultiByte
38 |
39 |
40 | DynamicLibrary
41 | false
42 | false
43 | MultiByte
44 | v110
45 |
46 |
47 | DynamicLibrary
48 | false
49 | false
50 | MultiByte
51 | v110
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 | ..\..\bin\
72 |
73 |
74 | true
75 | ..\..\bin\x64\
76 |
77 |
78 | false
79 | ..\..\bin\
80 |
81 |
82 | false
83 | ..\..\bin\x64\
84 |
85 |
86 |
87 |
88 |
89 | Level3
90 | Disabled
91 | WIN32;_DEBUG;_WINDOWS;_USRDLL;LEDWIZ_EXPORTS;%(PreprocessorDefinitions)
92 | ..\..\include
93 |
94 |
95 | Windows
96 | true
97 | hid.lib;Setupapi.lib;%(AdditionalDependencies)
98 | ../../src/ledwiz.def
99 |
100 |
101 |
102 |
103 |
104 |
105 | Level3
106 | Disabled
107 | WIN32;_DEBUG;_WINDOWS;_USRDLL;LEDWIZ_EXPORTS;%(PreprocessorDefinitions)
108 | ..\..\include
109 |
110 |
111 | Windows
112 | true
113 | hid.lib;Setupapi.lib;%(AdditionalDependencies)
114 | ../../src/ledwiz.def
115 |
116 |
117 |
118 |
119 | Level3
120 |
121 |
122 | MaxSpeed
123 | false
124 | true
125 | WIN32;NDEBUG;_WINDOWS;_USRDLL;LEDWIZ_EXPORTS;%(PreprocessorDefinitions)
126 | ..\..\include
127 | OnlyExplicitInline
128 | Speed
129 | true
130 | false
131 | false
132 |
133 |
134 | Windows
135 | false
136 | true
137 | true
138 | hid.lib;Setupapi.lib;%(AdditionalDependencies)
139 | ../../src/ledwiz.def
140 |
141 |
142 |
143 |
144 | Level3
145 |
146 |
147 | MaxSpeed
148 | false
149 | true
150 | WIN32;NDEBUG;_WINDOWS;_USRDLL;LEDWIZ_EXPORTS;%(PreprocessorDefinitions)
151 | ..\..\include
152 | OnlyExplicitInline
153 | Speed
154 | true
155 | false
156 | false
157 |
158 |
159 | Windows
160 | false
161 | true
162 | true
163 | hid.lib;Setupapi.lib;%(AdditionalDependencies)
164 | ../../src/ledwiz.def
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/win32/driver/build/vs_2012/ledwiz.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/win32/driver/include/ledwiz.h:
--------------------------------------------------------------------------------
1 |
2 | #ifndef LEDWIZ_H__INCLUDED
3 | #define LEDWIZ_H__INCLUDED
4 |
5 |
6 | #if defined(_MSC_VER)
7 |
8 | #define LWZCALL __cdecl // this is what the 'original' ledwiz.dll uses
9 | #define LWZCALLBACK __stdcall
10 |
11 | #if (_MSC_VER >= 1600) // starting with VisualStudio 2010 stdint.h is available
12 | #include
13 | #else
14 | typedef signed char int8_t;
15 | typedef unsigned char uint8_t;
16 | typedef short int16_t;
17 | typedef unsigned short uint16_t;
18 | typedef int int32_t;
19 | typedef unsigned int uint32_t;
20 | #endif
21 |
22 | #else
23 |
24 | #include
25 | #define LWZCALL
26 | #define LWZCALLBACK
27 |
28 | #endif
29 |
30 |
31 | #ifdef __cplusplus
32 | extern "C" {
33 | #endif
34 |
35 |
36 | #define LWZ_MAX_DEVICES 16
37 |
38 | typedef enum {
39 | LWZ_REASON_ADD = 1,
40 | LWZ_REASON_DELETE = 2,
41 | } LWZ_NOTIFY_REASON;
42 |
43 |
44 | typedef int32_t LWZHANDLE;
45 |
46 |
47 | typedef struct {
48 | LWZHANDLE handles[LWZ_MAX_DEVICES];
49 | int32_t numdevices;
50 | } LWZDEVICELIST;
51 |
52 |
53 | /************************************************************************************************************************
54 | LWZ_SBA - All Outputs State plus Global Pulse Speed
55 | *************************************************************************************************************************
56 | handle is an idetifier for a specific LED-WIZ device
57 | Values bank0, bank1, bank2, and bank3 equal 8-bit representations of on/off states for banks 1-4.
58 | Value globalPulseSpeed equals Global Pulse Speed setting (1 through 7).
59 | ************************************************************************************************************************/
60 |
61 | void LWZCALL LWZ_SBA(
62 | LWZHANDLE hlwz,
63 | uint8_t bank0,
64 | uint8_t bank1,
65 | uint8_t bank2,
66 | uint8_t bank3,
67 | uint8_t globalPulseSpeed);
68 |
69 |
70 | /************************************************************************************************************************
71 | LWZ_PBA - All Outputs Profile Settings (Most Efficient):
72 | *************************************************************************************************************************
73 | handle is an idetifier for a specific LED-WIZ device
74 | Each of the 32 parameters coincide with outputs 1-32. A value of 1 to 48 sets the brightness of each LED using PWM.
75 | A value of 129-132 indicates an automated pulse mode as follows:
76 | 129 = Ramp Up / Ramp Down
77 | 130 = On / Off
78 | 131 = On / Ramp Down
79 | 132 = Ramp Up / On
80 | The speed is contolled by the Global Pulse Speed parameter.
81 | ************************************************************************************************************************/
82 |
83 | void LWZCALL LWZ_PBA(LWZHANDLE hlwz, uint8_t const *pmode32bytes);
84 |
85 |
86 | /************************************************************************************************************************
87 | LWZ_REGISTER - Register device for plug and play
88 | *************************************************************************************************************************
89 | This must be called with the hwnd that an application uses to process windows messages.
90 | This associates a device with a window message queue so the your application can be notified of plug/unplug events.
91 | In order to unregister, call with hwnd == NULL.
92 | You have to unregister if the library was manually loaded and then is going to be freed with FreeLibrary() while
93 | the window still exists.
94 | ************************************************************************************************************************/
95 |
96 | void LWZCALL LWZ_REGISTER(LWZHANDLE hlwz, void * hwnd);
97 |
98 |
99 | /************************************************************************************************************************
100 | LWZ_SET_NOTIFY - Set notifcation mechanisms for plug/unplug events
101 | LWZ_SET_NOTIFY_EX - same as LWZ_SET_NOTIFY, but provides a user defined pointer in the callback
102 | *************************************************************************************************************************
103 | Set a notification callback for plug/unplug events.
104 | It searches for all connected LED-WIZ devices and then calls the notify callback for it.
105 | The callback will come back directly from this call or later from the windows procedure thread of the caller,
106 | that is as long as you do your stuff from the same windows procedure there will be no need for thread synchronization.
107 | At the same time the notification procedure is called, the LWZDEVICELIST
108 | will be updated with any new device handles that are required.
109 | This function is also used to set a pointer to your applications device list.
110 | ************************************************************************************************************************/
111 |
112 | typedef void (LWZCALLBACK * LWZNOTIFYPROC)(int32_t reason, LWZHANDLE hlwz);
113 | typedef void (LWZCALLBACK * LWZNOTIFYPROC_EX)(void *puser, int32_t reason, LWZHANDLE hlwz);
114 |
115 | void LWZCALL LWZ_SET_NOTIFY(LWZNOTIFYPROC notify_callback, LWZDEVICELIST *plist);
116 | void LWZCALL LWZ_SET_NOTIFY_EX(LWZNOTIFYPROC_EX notify_ex_callback, void *puser, LWZDEVICELIST *plist);
117 |
118 |
119 | /************************************************************************************************************************
120 | LWZ_RAWWRITE - write raw data to the device
121 | *************************************************************************************************************************
122 | return number of bytes written.
123 | ************************************************************************************************************************/
124 |
125 | uint32_t LWZ_RAWWRITE(LWZHANDLE hlwz, uint8_t const *pdata, uint32_t ndata);
126 |
127 | /************************************************************************************************************************
128 | LWZ_RAWREAD - read raw data from the device
129 | *************************************************************************************************************************
130 | return number of bytes read.
131 | ************************************************************************************************************************/
132 |
133 | uint32_t LWZ_RAWREAD(LWZHANDLE hlwz, uint8_t *pdata, uint32_t ndata);
134 |
135 |
136 | #ifdef __cplusplus
137 | }
138 | #endif
139 |
140 | #endif
141 |
--------------------------------------------------------------------------------
/win32/driver/src/ledwiz.def:
--------------------------------------------------------------------------------
1 | EXPORTS
2 | LWZ_SBA
3 | LWZ_PBA
4 | LWZ_RAWWRITE
5 | LWZ_RAWREAD
6 | LWZ_REGISTER
7 | LWZ_SET_NOTIFY
8 | LWZ_SET_NOTIFY_EX
9 |
--------------------------------------------------------------------------------
/win32/driver/src/usbdev.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include "usbdev.h"
20 |
21 |
22 | static void usbdev_close_internal(HUDEV hudev);
23 |
24 | #define USB_READ_TIMOUT_MS 500
25 |
26 |
27 |
28 | struct CAutoLockCS // helper class to lock a critical section, and unlock it automatically
29 | {
30 | CRITICAL_SECTION *m_pcs;
31 | CAutoLockCS(CRITICAL_SECTION *pcs) { m_pcs = pcs; EnterCriticalSection(m_pcs); };
32 | ~CAutoLockCS() { LeaveCriticalSection(m_pcs); };
33 | };
34 |
35 | #define AUTOLOCK(cs) CAutoLockCS lock_##__LINE__##__(&cs) // helper macro for using the helper class
36 |
37 |
38 |
39 | typedef struct {
40 | CRITICAL_SECTION cslock;
41 | HANDLE hrevent;
42 | HANDLE hwevent;
43 | HANDLE hdev;
44 | LONG refcount;
45 | } usbdev_context_t;
46 |
47 |
48 | HUDEV usbdev_create(LPCSTR devicepath)
49 | {
50 | // create context
51 |
52 | usbdev_context_t * const h = (usbdev_context_t*)malloc(sizeof(usbdev_context_t));
53 |
54 | if (h == NULL)
55 | return NULL;
56 |
57 | memset(h, 0x00, sizeof(*h));
58 | h->hdev = INVALID_HANDLE_VALUE;
59 |
60 | InitializeCriticalSection(&h->cslock);
61 |
62 | h->hrevent = CreateEvent(NULL, TRUE, FALSE, NULL);
63 | h->hwevent = CreateEvent(NULL, TRUE, FALSE, NULL);
64 |
65 | if (h->hrevent == NULL ||
66 | h->hwevent == NULL)
67 | {
68 | goto Failed;
69 | }
70 |
71 | // open device
72 |
73 | HANDLE hdev = CreateFileA(
74 | devicepath,
75 | GENERIC_READ | GENERIC_WRITE,
76 | FILE_SHARE_READ | FILE_SHARE_WRITE,
77 | NULL,
78 | OPEN_EXISTING,
79 | FILE_FLAG_OVERLAPPED,
80 | NULL);
81 |
82 | if (hdev != INVALID_HANDLE_VALUE)
83 | {
84 | h->hdev = hdev;
85 | h->refcount = 1;
86 | return h;
87 | }
88 |
89 | Failed:
90 | usbdev_close_internal(h);
91 | return NULL;
92 | }
93 |
94 | static void usbdev_close_internal(HUDEV hudev)
95 | {
96 | usbdev_context_t * const h = (usbdev_context_t*)hudev;
97 |
98 | if (h == NULL)
99 | return;
100 |
101 | if (h->hrevent)
102 | {
103 | CloseHandle(h->hrevent);
104 | h->hrevent = NULL;
105 | }
106 |
107 | if (h->hwevent)
108 | {
109 | CloseHandle(h->hwevent);
110 | h->hwevent = NULL;
111 | }
112 |
113 | if (h->hdev != INVALID_HANDLE_VALUE)
114 | {
115 | CloseHandle(h->hdev);
116 | h->hdev = INVALID_HANDLE_VALUE;
117 | }
118 |
119 | DeleteCriticalSection(&h->cslock);
120 |
121 | free(h);
122 | }
123 |
124 | void usbdev_release(HUDEV hudev)
125 | {
126 | usbdev_context_t * const h = (usbdev_context_t*)hudev;
127 |
128 | if (h != NULL)
129 | {
130 | LONG refcount_new = InterlockedDecrement(&h->refcount);
131 |
132 | if (refcount_new <= 0)
133 | {
134 | usbdev_close_internal(h);
135 | }
136 | }
137 | }
138 |
139 | void usbdev_addref(HUDEV hudev)
140 | {
141 | usbdev_context_t * const h = (usbdev_context_t*)hudev;
142 |
143 | if (h != NULL)
144 | {
145 | InterlockedIncrement(&h->refcount);
146 | }
147 | }
148 |
149 | HANDLE usbdev_handle(HUDEV hudev)
150 | {
151 | usbdev_context_t * const h = (usbdev_context_t*)hudev;
152 |
153 | if (h == NULL)
154 | return INVALID_HANDLE_VALUE;
155 |
156 | return h->hdev;
157 | }
158 |
159 | size_t usbdev_read(HUDEV hudev, void *psrc, size_t ndata)
160 | {
161 | usbdev_context_t * const h = (usbdev_context_t*)hudev;
162 |
163 | if (h == NULL)
164 | return NULL;
165 |
166 | BYTE * pdata = (BYTE*)psrc;
167 |
168 | if (pdata == NULL)
169 | return 0;
170 |
171 | if (ndata > 64)
172 | ndata = 64;
173 |
174 | AUTOLOCK(h->cslock);
175 |
176 | int res = 0;
177 | BYTE buffer[65];
178 | DWORD nread = 0;
179 | BOOL bres = FALSE;
180 |
181 | OVERLAPPED ol = {};
182 | ol.hEvent = h->hrevent;
183 |
184 | bres = ReadFile(h->hdev, buffer, sizeof(buffer), NULL, &ol);
185 |
186 | if (bres != TRUE)
187 | {
188 | DWORD dwerror = GetLastError();
189 |
190 | if (dwerror == ERROR_IO_PENDING)
191 | {
192 | if (WaitForSingleObject(h->hrevent, USB_READ_TIMOUT_MS) != WAIT_OBJECT_0)
193 | {
194 | CancelIo(h->hdev);
195 | }
196 |
197 | bres = TRUE;
198 | }
199 | }
200 |
201 | if (bres == TRUE)
202 | {
203 | bres = GetOverlappedResult(
204 | h->hdev,
205 | &ol,
206 | &nread,
207 | TRUE);
208 | }
209 |
210 | if (bres != TRUE)
211 | {
212 | DWORD dwerror = GetLastError();
213 | _ASSERT(0);
214 | }
215 |
216 | if (nread <= 1 || bres != TRUE)
217 | return 0;
218 |
219 | nread -= 1; // skip report id
220 |
221 | if (ndata > nread)
222 | ndata = nread;
223 |
224 | memcpy(pdata, &buffer[1], ndata);
225 |
226 | return ndata;
227 | }
228 |
229 | size_t usbdev_write(HUDEV hudev, void const *pdst, size_t ndata)
230 | {
231 | usbdev_context_t * const h = (usbdev_context_t*)hudev;
232 |
233 | if (h == NULL)
234 | return NULL;
235 |
236 | BYTE const * pdata = (BYTE const *)pdst;
237 |
238 | if (pdata == NULL || ndata == 0)
239 | return 0;
240 |
241 | if (ndata > 32)
242 | ndata = 32;
243 |
244 | AUTOLOCK(h->cslock);
245 |
246 | int res = 0;
247 | DWORD nbyteswritten = 0;
248 |
249 | BYTE buf[9];
250 | buf[0] = 0; // report id
251 |
252 | while (ndata > 0)
253 | {
254 | int const ncopy = (ndata > 8) ? 8 : ndata;
255 |
256 | memset(&buf[1], 0x00, 8);
257 | memcpy(&buf[1], pdata, ncopy);
258 | pdata += ncopy;
259 | ndata -= ncopy;
260 |
261 | DWORD nwritten = 0;
262 | DWORD const nwrite = 9;
263 |
264 | OVERLAPPED ol = {};
265 | ol.hEvent = h->hwevent;
266 |
267 | BOOL bres = WriteFile(h->hdev, buf, nwrite, NULL, &ol);
268 |
269 | if (bres != TRUE)
270 | {
271 | DWORD dwerror = GetLastError();
272 |
273 | if (dwerror == ERROR_IO_PENDING)
274 | {
275 | if (WaitForSingleObject(h->hwevent, USB_READ_TIMOUT_MS) != WAIT_OBJECT_0)
276 | {
277 | CancelIo(h->hdev);
278 | }
279 |
280 | bres = TRUE;
281 | }
282 | }
283 |
284 | if (bres == TRUE)
285 | {
286 | bres = GetOverlappedResult(
287 | h->hdev,
288 | &ol,
289 | &nwritten,
290 | TRUE);
291 | }
292 |
293 | if (bres != TRUE)
294 | {
295 | DWORD dwerror = GetLastError();
296 | _ASSERT(0);
297 | }
298 |
299 | if (nwritten != nwrite || bres != TRUE) {
300 | break;
301 | }
302 |
303 | nbyteswritten += ncopy;
304 | }
305 |
306 | return nbyteswritten;
307 | }
308 |
309 |
--------------------------------------------------------------------------------
/win32/driver/src/usbdev.h:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #ifndef USBDEV_H__INCLUDED
18 | #define USBDEV_H__INCLUDED
19 |
20 |
21 | typedef void * HUDEV;
22 |
23 | HUDEV usbdev_create(LPCSTR devicepath);
24 | void usbdev_addref(HUDEV hudev);
25 | void usbdev_release(HUDEV hudev);
26 | size_t usbdev_read(HUDEV hudev, void *pdata, size_t ndata);
27 | size_t usbdev_write(HUDEV hudev, void const *pdata, size_t ndata);
28 | HANDLE usbdev_handle(HUDEV hudev);
29 |
30 |
31 |
32 | #endif
33 |
--------------------------------------------------------------------------------
/win32/lwcconfig/build/vs_2008/lwcconfig.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 10.00
3 | # Visual C++ Express 2008
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lwcconfig", "lwcconfig.vcproj", "{591A86C4-AE9B-4839-AE3A-63D22CEEB84D}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Release|Win32 = Release|Win32
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {591A86C4-AE9B-4839-AE3A-63D22CEEB84D}.Debug|Win32.ActiveCfg = Debug|Win32
13 | {591A86C4-AE9B-4839-AE3A-63D22CEEB84D}.Debug|Win32.Build.0 = Debug|Win32
14 | {591A86C4-AE9B-4839-AE3A-63D22CEEB84D}.Release|Win32.ActiveCfg = Release|Win32
15 | {591A86C4-AE9B-4839-AE3A-63D22CEEB84D}.Release|Win32.Build.0 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/win32/lwcconfig/build/vs_2008/lwcconfig.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
53 |
56 |
59 |
62 |
69 |
72 |
75 |
78 |
81 |
84 |
87 |
90 |
91 |
99 |
102 |
105 |
108 |
111 |
114 |
126 |
129 |
132 |
135 |
144 |
147 |
150 |
153 |
156 |
159 |
162 |
165 |
166 |
167 |
168 |
169 |
170 |
175 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
--------------------------------------------------------------------------------
/win32/lwcconfig/src/main.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 | #include
22 |
23 | #include
24 | #include
25 |
26 |
27 | #define LEDWIZ_DLL_NAME "ledwiz.dll"
28 |
29 |
30 | struct {
31 |
32 | struct {
33 | void (LWZCALL * LWZ_SBA) (LWZHANDLE hlwz, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t gps);
34 | void (LWZCALL * LWZ_PBA) (LWZHANDLE hlwz, uint8_t const *pmode32bytes);
35 | int (LWZCALL * LWZ_RAWWRITE) (LWZHANDLE hlwz, uint8_t const *pdata, uint32_t ndata);
36 | void (LWZCALL * LWZ_REGISTER) (LWZHANDLE hlwz, void * hwnd);
37 | void (LWZCALL * LWZ_SET_NOTIFY) (LWZNOTIFYPROC notify_callback, LWZDEVICELIST *plist);
38 | } fn;
39 |
40 | HMODULE hdll;
41 | HWND hwnd;
42 | HANDLE hthread;
43 |
44 | LWZDEVICELIST devlist;
45 |
46 | } g_main = {0};
47 |
48 |
49 | static void CALLBACK notify_cb(int32_t reason, LWZHANDLE hlwz)
50 | {
51 | if (reason == LWZ_REASON_ADD)
52 | {
53 | printf("ledwiz device found, id: %d\n", hlwz);
54 |
55 | g_main.fn.LWZ_REGISTER(hlwz, g_main.hwnd);
56 | }
57 | else if (reason == LWZ_REASON_DELETE)
58 | {
59 | printf("ledwiz device removed, id: %d\n", hlwz);
60 | }
61 | }
62 |
63 |
64 | void usage()
65 | {
66 | printf("\n");
67 | printf("Usage:\n\n");
68 | printf("lwcconfig [-m] [-p ] []\n");
69 | printf(" -h .................... help\n");
70 | printf(" -p ........... program new id\n");
71 | printf(" -m .................... measure I/O bandwidth\n");
72 | printf("\n");
73 | }
74 |
75 |
76 | int main(int argc, char* argv[])
77 | {
78 | // parse arguments
79 |
80 | const char * p_arg = NULL;
81 | const char * id_arg = NULL;
82 | bool do_measure_bandwidth = false;
83 | int err = 0;
84 |
85 | for (int i = 1; i < argc && err == 0; i++)
86 | {
87 | if (argv[i][0] == '-')
88 | {
89 | switch (argv[i][1]) {
90 | case 'm':
91 | {
92 | do_measure_bandwidth = true;
93 | break;
94 | }
95 | case 'h':
96 | {
97 | err = 1;
98 | break;
99 | }
100 | case 'p':
101 | {
102 | p_arg = &argv[i][2];
103 |
104 | if (p_arg[0] == '\0' && (i+1) < argc) {
105 | p_arg = argv[++i];
106 | }
107 |
108 | break;
109 | }
110 | default:
111 | {
112 | err = -4;
113 | }
114 | }
115 | }
116 | else
117 | {
118 | if (id_arg != NULL) {
119 | err = -5;
120 | } else {
121 | id_arg = argv[i];
122 | }
123 | }
124 | }
125 |
126 | printf("\n");
127 |
128 | if (err < 0)
129 | {
130 | printf("invalid argument(s), %d", err);
131 | usage();
132 | goto Failed;
133 | }
134 | else if (err != 0)
135 | {
136 | usage();
137 | goto Failed;
138 | }
139 |
140 | // load the ledwiz.dll
141 |
142 | g_main.hdll = LoadLibraryA(LEDWIZ_DLL_NAME);
143 |
144 | if (g_main.hdll == NULL)
145 | {
146 | printf("loading " LEDWIZ_DLL_NAME " failed!\n");
147 | return -1;
148 | }
149 |
150 | ((void**)&g_main.fn.LWZ_SBA)[0] = GetProcAddress(g_main.hdll, "LWZ_SBA");
151 | ((void**)&g_main.fn.LWZ_PBA)[0] = GetProcAddress(g_main.hdll, "LWZ_PBA");
152 | ((void**)&g_main.fn.LWZ_RAWWRITE)[0] = GetProcAddress(g_main.hdll, "LWZ_RAWWRITE");
153 | ((void**)&g_main.fn.LWZ_REGISTER)[0] = GetProcAddress(g_main.hdll, "LWZ_REGISTER");
154 | ((void**)&g_main.fn.LWZ_SET_NOTIFY)[0] = GetProcAddress(g_main.hdll, "LWZ_SET_NOTIFY");
155 |
156 | if (g_main.fn.LWZ_SBA == NULL ||
157 | g_main.fn.LWZ_PBA == NULL ||
158 | g_main.fn.LWZ_REGISTER == NULL ||
159 | g_main.fn.LWZ_SET_NOTIFY == NULL)
160 | {
161 | printf("getting the function addresses failed!\n");
162 | goto Failed;
163 | }
164 |
165 | // enumerate LED wiz devices
166 |
167 | g_main.fn.LWZ_SET_NOTIFY(notify_cb, &g_main.devlist);
168 |
169 | if (g_main.devlist.numdevices <= 0)
170 | {
171 | printf("no ledwiz devices detected!\n");
172 | goto Failed;
173 | }
174 |
175 | // verify options
176 |
177 | if (!do_measure_bandwidth &&
178 | p_arg == NULL)
179 | {
180 | usage();
181 | goto Failed;
182 | }
183 |
184 | // measure bandwidth
185 |
186 | if (do_measure_bandwidth)
187 | {
188 | printf("measuring bandwidth ...\n");
189 |
190 | int const duration_ms_max = 500;
191 | uint8_t x32bytes[32] = {0};
192 | int nsend = 0;
193 | int nsend_total = 0;
194 | int nduration_ms = 0;
195 | clock_t t0;
196 |
197 | // step 1: send as much data as possible within some fixed time to fill the input buffer
198 |
199 | t0 = clock();
200 |
201 | for (;;)
202 | {
203 | g_main.fn.LWZ_PBA(g_main.devlist.handles[0], &x32bytes[0]);
204 | nsend += 32;
205 |
206 | clock_t t1 = clock();
207 | nduration_ms = ((t1 - t0) * 1000) / CLOCKS_PER_SEC;
208 |
209 | if (nduration_ms > duration_ms_max) {
210 | break;
211 | }
212 | }
213 |
214 | nsend_total += nsend;
215 |
216 | // step 2: measure average throughput
217 |
218 | nsend = 0;
219 | nduration_ms = 0;
220 | t0 = clock();
221 |
222 | for (;;)
223 | {
224 | g_main.fn.LWZ_PBA(g_main.devlist.handles[0], &x32bytes[0]);
225 | nsend += 32;
226 |
227 | clock_t t1 = clock();
228 | nduration_ms = ((t1 - t0) * 1000) / CLOCKS_PER_SEC;
229 |
230 | if (nduration_ms > duration_ms_max) {
231 | break;
232 | }
233 | }
234 |
235 | nsend_total += nsend;
236 | double bps_avg = (double)nsend * 1000.0 / (double)nduration_ms;
237 |
238 | // step 3: measure burst blocksize
239 |
240 | Sleep((int)((double)nsend_total / bps_avg * 1000.0) + 100); // wait some time until the buffer is again free
241 |
242 | nsend = 0;
243 | nduration_ms = 0;
244 | t0 = clock();
245 |
246 | for (;;)
247 | {
248 | g_main.fn.LWZ_PBA(g_main.devlist.handles[0], &x32bytes[0]);
249 | nsend += 32;
250 |
251 | clock_t t1 = clock();
252 | nduration_ms = ((t1 - t0) * 1000) / CLOCKS_PER_SEC;
253 |
254 | if (nduration_ms > duration_ms_max) {
255 | break;
256 | }
257 | }
258 |
259 | int nsend_burst = nsend - (int)((double)nduration_ms * bps_avg / 1000.0);
260 |
261 | if (nsend_burst < 0) {
262 | nsend_burst = 0;
263 | }
264 |
265 | printf("average rate: %0.2f kByte/s, burst blocksize: %d Byte\n", bps_avg / 1024.0, nsend_burst);
266 | }
267 |
268 | // reprogram new id
269 |
270 | if (p_arg && g_main.devlist.numdevices > 0)
271 | {
272 | if (g_main.fn.LWZ_RAWWRITE == NULL) {
273 | printf("invalid or old version ledwiz.dll! please update");
274 | goto Failed;
275 | }
276 |
277 | int const id_old = (id_arg != NULL) ? atoi(id_arg) : g_main.devlist.handles[0];
278 | int const id_new = atoi(p_arg);
279 |
280 | if (id_new < 1 || id_new >= 32 || id_new == id_old)
281 | {
282 | printf("invalid id specified!\n");
283 | goto Failed;
284 | }
285 |
286 | int index = -1;
287 | for (int i = 0; i < g_main.devlist.numdevices; i++)
288 | {
289 | if (g_main.devlist.handles[i] == id_old)
290 | {
291 | index = i;
292 | break;
293 | }
294 | }
295 |
296 | if (index < 0)
297 | {
298 | printf("device with id=%d not found!\n", id_old);
299 | }
300 | else
301 | {
302 | // send change ID command
303 | printf("sending change-id-command to device %d, new id: %d\n", id_old, id_new);
304 |
305 | uint8_t const LWCCONFIG_CMD_SETID = 65;
306 | uint8_t const id = id_new - 1;
307 | uint8_t const check = ~id;
308 |
309 | uint8_t buf[8] = {LWCCONFIG_CMD_SETID, id, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, check};
310 |
311 | g_main.fn.LWZ_RAWWRITE(g_main.devlist.handles[index], buf, sizeof(buf));
312 | }
313 | }
314 |
315 | Failed:
316 | if (g_main.hdll)
317 | {
318 | FreeLibrary(g_main.hdll);
319 | g_main.hdll = NULL;
320 | }
321 |
322 | return 0;
323 | }
324 |
--------------------------------------------------------------------------------
/win32/testapp/build/vs_2008/testapp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 10.00
3 | # Visual C++ Express 2008
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testapp", "testapp.vcproj", "{B56B9055-7ABE-4231-8D9E-DC7ED80739DE}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Release|Win32 = Release|Win32
10 | EndGlobalSection
11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
12 | {B56B9055-7ABE-4231-8D9E-DC7ED80739DE}.Debug|Win32.ActiveCfg = Debug|Win32
13 | {B56B9055-7ABE-4231-8D9E-DC7ED80739DE}.Debug|Win32.Build.0 = Debug|Win32
14 | {B56B9055-7ABE-4231-8D9E-DC7ED80739DE}.Release|Win32.ActiveCfg = Release|Win32
15 | {B56B9055-7ABE-4231-8D9E-DC7ED80739DE}.Release|Win32.Build.0 = Release|Win32
16 | EndGlobalSection
17 | GlobalSection(SolutionProperties) = preSolution
18 | HideSolutionNode = FALSE
19 | EndGlobalSection
20 | EndGlobal
21 |
--------------------------------------------------------------------------------
/win32/testapp/build/vs_2008/testapp.vcproj:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
15 |
16 |
17 |
18 |
19 |
26 |
29 |
32 |
35 |
38 |
41 |
53 |
56 |
59 |
62 |
69 |
72 |
75 |
78 |
81 |
84 |
87 |
90 |
91 |
99 |
102 |
105 |
108 |
111 |
114 |
126 |
129 |
132 |
135 |
144 |
147 |
150 |
153 |
156 |
159 |
162 |
165 |
166 |
167 |
168 |
169 |
170 |
173 |
174 |
175 |
176 |
177 |
178 |
--------------------------------------------------------------------------------
/win32/testapp/build/vs_2012/testapp.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Express 2012 for Windows Desktop
4 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testapp", "testapp.vcxproj", "{2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}"
5 | EndProject
6 | Global
7 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
8 | Debug|Win32 = Debug|Win32
9 | Debug|x64 = Debug|x64
10 | Release|Win32 = Release|Win32
11 | Release|x64 = Release|x64
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Debug|Win32.ActiveCfg = Release|Win32
15 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Debug|Win32.Build.0 = Release|Win32
16 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Debug|x64.ActiveCfg = Release|x64
17 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Debug|x64.Build.0 = Release|x64
18 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Release|Win32.ActiveCfg = Release|Win32
19 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Release|Win32.Build.0 = Release|Win32
20 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Release|x64.ActiveCfg = Release|x64
21 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}.Release|x64.Build.0 = Release|x64
22 | EndGlobalSection
23 | GlobalSection(SolutionProperties) = preSolution
24 | HideSolutionNode = FALSE
25 | EndGlobalSection
26 | EndGlobal
27 |
--------------------------------------------------------------------------------
/win32/testapp/build/vs_2012/testapp.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Debug
10 | x64
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 | Release
18 | x64
19 |
20 |
21 |
22 | {2A6C8427-1CFF-448B-AB3E-0B91BB08FE4A}
23 | Win32Proj
24 | testapp
25 |
26 |
27 |
28 | Application
29 | true
30 | v110
31 | Unicode
32 |
33 |
34 | Application
35 | true
36 | v110
37 | Unicode
38 |
39 |
40 | Application
41 | false
42 | v110
43 | true
44 | Unicode
45 |
46 |
47 | Application
48 | false
49 | v110
50 | true
51 | Unicode
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | true
71 | ..\..\bin\
72 |
73 |
74 | true
75 | ..\..\bin\x64\
76 |
77 |
78 | false
79 | ..\..\bin\
80 |
81 |
82 | false
83 | ..\..\bin\x64\
84 |
85 |
86 |
87 |
88 |
89 | Level3
90 | Disabled
91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
92 | ..\..\..\driver\include
93 |
94 |
95 | Console
96 | true
97 |
98 |
99 |
100 |
101 |
102 |
103 | Level3
104 | Disabled
105 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
106 | ..\..\..\driver\include
107 |
108 |
109 | Console
110 | true
111 |
112 |
113 |
114 |
115 | Level3
116 |
117 |
118 | MaxSpeed
119 | true
120 | true
121 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
122 | ..\..\..\driver\include
123 |
124 |
125 | Console
126 | true
127 | true
128 | true
129 |
130 |
131 |
132 |
133 | Level3
134 |
135 |
136 | MaxSpeed
137 | true
138 | true
139 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
140 | ..\..\..\driver\include
141 |
142 |
143 | Console
144 | true
145 | true
146 | true
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
--------------------------------------------------------------------------------
/win32/testapp/build/vs_2012/testapp.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/win32/testapp/src/main.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * LWCloneU2
3 | * Copyright (C) 2013 Andreas Dittrich
4 | *
5 | * This program is free software; you can redistribute it and/or modify it under the terms of the
6 | * GNU General Public License as published by the Free Software Foundation;
7 | * either version 2 of the License, or (at your option) any later version.
8 | *
9 | * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
10 | * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 | * See the GNU General Public License for more details.
12 | *
13 | * You should have received a copy of the GNU General Public License along with this program;
14 | * if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15 | */
16 |
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include
23 | #include
24 |
25 |
26 | #define LEDWIZ_DLL_NAME "ledwiz.dll"
27 |
28 |
29 | struct {
30 |
31 | struct {
32 | void (LWZCALL * LWZ_SBA) (LWZHANDLE hlwz, uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3, uint8_t gps);
33 | void (LWZCALL * LWZ_PBA) (LWZHANDLE hlwz, uint8_t const *pmode32bytes);
34 | void (LWZCALL * LWZ_REGISTER) (LWZHANDLE hlwz, void * hwnd);
35 | void (LWZCALL * LWZ_SET_NOTIFY) (LWZNOTIFYPROC notify_callback, LWZDEVICELIST *plist);
36 | } fn;
37 |
38 | HMODULE hdll;
39 | HWND hwnd;
40 | HANDLE hthread;
41 |
42 | LWZDEVICELIST devlist;
43 |
44 | } g_main;
45 |
46 |
47 | static void CALLBACK notify_cb(int32_t reason, LWZHANDLE hlwz)
48 | {
49 | if (reason == LWZ_REASON_ADD)
50 | {
51 | printf("ledwiz device found, id: %d\n", hlwz);
52 |
53 | g_main.fn.LWZ_REGISTER(hlwz, g_main.hwnd);
54 |
55 | // switch on all LEDs and set brightness to '30'
56 |
57 | g_main.fn.LWZ_SBA(hlwz, 0xFF, 0xFF, 0xFF, 0xFF, 2);
58 |
59 | uint8_t mode[32];
60 | memset(&mode, 30, sizeof(mode));
61 | g_main.fn.LWZ_PBA(hlwz, mode);
62 | }
63 | else if (reason == LWZ_REASON_DELETE)
64 | {
65 | printf("ledwiz device removed, id: %d\n", hlwz);
66 | }
67 | }
68 |
69 | static LRESULT CALLBACK MyWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
70 | {
71 | switch (message)
72 | {
73 | case WM_CREATE:
74 | {
75 | // save windows handle
76 |
77 | g_main.hwnd = hwnd;
78 |
79 | // enumerate LED wiz devices
80 |
81 | g_main.fn.LWZ_SET_NOTIFY(notify_cb, &g_main.devlist);
82 |
83 | if (g_main.devlist.numdevices <= 0)
84 | {
85 | printf("no ledwiz devices detected!\n");
86 | DestroyWindow(hwnd);
87 | return 0;
88 | }
89 |
90 | break;
91 | }
92 |
93 | case WM_CLOSE:
94 | {
95 | // switch off all LEDs for all devices
96 |
97 | for (int i = 0; i < g_main.devlist.numdevices; i++)
98 | {
99 | g_main.fn.LWZ_SBA(g_main.devlist.handles[i], 0x00, 0x00, 0x00, 0x00, 2);
100 | }
101 |
102 | DestroyWindow(hwnd);
103 | return 0;
104 | }
105 |
106 | case WM_DESTROY:
107 | PostQuitMessage(0);
108 | return 0;
109 | }
110 |
111 | return DefWindowProc(hwnd, message, wParam, lParam);
112 | }
113 |
114 | static BOOL ctrlhandler(DWORD fdwCtrlType)
115 | {
116 | switch(fdwCtrlType)
117 | {
118 | case CTRL_C_EVENT:
119 | case CTRL_CLOSE_EVENT:
120 | PostMessage(g_main.hwnd, WM_CLOSE, 0, 0);
121 | WaitForSingleObject(g_main.hthread, INFINITE);
122 | return TRUE;
123 |
124 | default:
125 | return FALSE;
126 | }
127 | }
128 |
129 | static DWORD WINAPI MyThreadProc(LPVOID lpParameter)
130 | {
131 | // load the ledwiz.dll
132 |
133 | g_main.hdll = LoadLibraryA(LEDWIZ_DLL_NAME);
134 |
135 | if (g_main.hdll == NULL)
136 | {
137 | printf("loading " LEDWIZ_DLL_NAME " failed!\n");
138 | return 0;
139 | }
140 |
141 | ((void**)&g_main.fn.LWZ_SBA)[0] = GetProcAddress(g_main.hdll, "LWZ_SBA");
142 | ((void**)&g_main.fn.LWZ_PBA)[0] = GetProcAddress(g_main.hdll, "LWZ_PBA");
143 | ((void**)&g_main.fn.LWZ_REGISTER)[0] = GetProcAddress(g_main.hdll, "LWZ_REGISTER");
144 | ((void**)&g_main.fn.LWZ_SET_NOTIFY)[0] = GetProcAddress(g_main.hdll, "LWZ_SET_NOTIFY");
145 |
146 | if (g_main.fn.LWZ_SBA == NULL ||
147 | g_main.fn.LWZ_PBA == NULL ||
148 | g_main.fn.LWZ_REGISTER == NULL ||
149 | g_main.fn.LWZ_SET_NOTIFY == NULL)
150 | {
151 | printf("getting the function addresses failed!\n");
152 | goto Failed;
153 | }
154 |
155 | // create a hidden window, so we get a 'HWND' for the ledwiz driver and
156 | // we can do the other stuff from the window proc
157 | {
158 | WNDCLASSEXA wx = {};
159 | wx.cbSize = sizeof(WNDCLASSEXA);
160 | wx.lpfnWndProc = MyWndProc;
161 | wx.hInstance = GetModuleHandle(NULL);
162 | wx.lpszClassName = "LWCloneU2";
163 |
164 | if (!RegisterClassExA(&wx))
165 | goto Failed;
166 |
167 | HWND hwnd = CreateWindowExA(0, wx.lpszClassName, "LWCloneU2 TestApp Hidden Window", 0, 0, 0, 0, 0, HWND_MESSAGE, NULL, NULL, NULL);
168 |
169 | if (hwnd == NULL)
170 | goto Failed;
171 | }
172 |
173 | // set the console handler to handle the crtl-c and exit clicks
174 |
175 | SetConsoleCtrlHandler((PHANDLER_ROUTINE)ctrlhandler, TRUE);
176 |
177 | printf("waiting for device attachment or removal.\n");
178 | printf("press to exit\n");
179 |
180 | // window message loop
181 |
182 | MSG msg;
183 |
184 | while (GetMessage(&msg, NULL, 0, 0))
185 | {
186 | TranslateMessage(&msg);
187 | DispatchMessage(&msg);
188 | }
189 |
190 | Failed:
191 | if (g_main.hdll)
192 | {
193 | FreeLibrary(g_main.hdll);
194 | g_main.hdll = NULL;
195 | }
196 |
197 | return 0;
198 | }
199 |
200 | int main(int argc, char* argv[])
201 | {
202 | // create a worker thread (for creating a hidden window) and wait until it exits
203 |
204 | g_main.hthread = CreateThread(NULL, 0, MyThreadProc, NULL, 0, NULL);
205 |
206 | if (g_main.hthread == NULL)
207 | return -1;
208 |
209 | WaitForSingleObject(g_main.hthread, INFINITE);
210 | CloseHandle(g_main.hthread);
211 | }
212 |
--------------------------------------------------------------------------------