Browse Source

Added source code

Clara Hobbs 7 years ago
parent
commit
6be412f090
5 changed files with 1543 additions and 1 deletions
  1. 1
    1
      LICENSE
  2. 614
    0
      Makefile
  3. 130
    0
      example.c
  4. 592
    0
      usb_keyboard.c
  5. 206
    0
      usb_keyboard.h

+ 1
- 1
LICENSE View File

@@ -1,5 +1,5 @@
1 1
 MIT License
2
-Copyright (c) <year> <copyright holders>
2
+Copyright (c) 2017 Clayton G. Hobbs
3 3
 
4 4
 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
5 5
 

+ 614
- 0
Makefile View File

@@ -0,0 +1,614 @@
1
+# Hey Emacs, this is a -*- makefile -*-
2
+#----------------------------------------------------------------------------
3
+# WinAVR Makefile Template written by Eric B. Weddington, Jörg Wunsch, et al.
4
+#
5
+# Released to the Public Domain
6
+#
7
+# Additional material for this makefile was written by:
8
+# Peter Fleury
9
+# Tim Henigan
10
+# Colin O'Flynn
11
+# Reiner Patommel
12
+# Markus Pfaff
13
+# Sander Pool
14
+# Frederik Rouleau
15
+# Carlos Lamas
16
+#
17
+#----------------------------------------------------------------------------
18
+# On command line:
19
+#
20
+# make all = Make software.
21
+#
22
+# make clean = Clean out built project files.
23
+#
24
+# make coff = Convert ELF to AVR COFF.
25
+#
26
+# make extcoff = Convert ELF to AVR Extended COFF.
27
+#
28
+# make program = Download the hex file to the device, using avrdude.
29
+#                Please customize the avrdude settings below first!
30
+#
31
+# make debug = Start either simulavr or avarice as specified for debugging, 
32
+#              with avr-gdb or avr-insight as the front end for debugging.
33
+#
34
+# make filename.s = Just compile filename.c into the assembler code only.
35
+#
36
+# make filename.i = Create a preprocessed source file for use in submitting
37
+#                   bug reports to the GCC project.
38
+#
39
+# To rebuild project do "make clean" then "make all".
40
+#----------------------------------------------------------------------------
41
+
42
+
43
+# Target file name (without extension).
44
+TARGET = example
45
+
46
+
47
+# List C source files here. (C dependencies are automatically generated.)
48
+SRC =	$(TARGET).c \
49
+	usb_keyboard.c
50
+
51
+
52
+# MCU name, you MUST set this to match the board you are using
53
+# type "make clean" after changing this, so all files will be rebuilt
54
+#
55
+#MCU = at90usb162       # Teensy 1.0
56
+MCU = atmega32u4        # Teensy 2.0
57
+#MCU = at90usb646       # Teensy++ 1.0
58
+#MCU = at90usb1286      # Teensy++ 2.0
59
+
60
+
61
+# Processor frequency.
62
+#   Normally the first thing your program should do is set the clock prescaler,
63
+#   so your program will run at the correct speed.  You should also set this
64
+#   variable to same clock speed.  The _delay_ms() macro uses this, and many
65
+#   examples use this variable to calculate timings.  Do not add a "UL" here.
66
+F_CPU = 16000000
67
+
68
+
69
+# Output format. (can be srec, ihex, binary)
70
+FORMAT = ihex
71
+
72
+
73
+# Object files directory
74
+#     To put object files in current directory, use a dot (.), do NOT make
75
+#     this an empty or blank macro!
76
+OBJDIR = .
77
+
78
+
79
+# List C++ source files here. (C dependencies are automatically generated.)
80
+CPPSRC = 
81
+
82
+
83
+# List Assembler source files here.
84
+#     Make them always end in a capital .S.  Files ending in a lowercase .s
85
+#     will not be considered source files but generated files (assembler
86
+#     output from the compiler), and will be deleted upon "make clean"!
87
+#     Even though the DOS/Win* filesystem matches both .s and .S the same,
88
+#     it will preserve the spelling of the filenames, and gcc itself does
89
+#     care about how the name is spelled on its command-line.
90
+ASRC =
91
+
92
+
93
+# Optimization level, can be [0, 1, 2, 3, s]. 
94
+#     0 = turn off optimization. s = optimize for size.
95
+#     (Note: 3 is not always the best optimization level. See avr-libc FAQ.)
96
+OPT = s
97
+
98
+
99
+# Debugging format.
100
+#     Native formats for AVR-GCC's -g are dwarf-2 [default] or stabs.
101
+#     AVR Studio 4.10 requires dwarf-2.
102
+#     AVR [Extended] COFF format requires stabs, plus an avr-objcopy run.
103
+DEBUG = dwarf-2
104
+
105
+
106
+# List any extra directories to look for include files here.
107
+#     Each directory must be seperated by a space.
108
+#     Use forward slashes for directory separators.
109
+#     For a directory that has spaces, enclose it in quotes.
110
+EXTRAINCDIRS = 
111
+
112
+
113
+# Compiler flag to set the C Standard level.
114
+#     c89   = "ANSI" C
115
+#     gnu89 = c89 plus GCC extensions
116
+#     c99   = ISO C99 standard (not yet fully implemented)
117
+#     gnu99 = c99 plus GCC extensions
118
+CSTANDARD = -std=gnu99
119
+
120
+
121
+# Place -D or -U options here for C sources
122
+CDEFS = -DF_CPU=$(F_CPU)UL
123
+
124
+
125
+# Place -D or -U options here for ASM sources
126
+ADEFS = -DF_CPU=$(F_CPU)
127
+
128
+
129
+# Place -D or -U options here for C++ sources
130
+CPPDEFS = -DF_CPU=$(F_CPU)UL
131
+#CPPDEFS += -D__STDC_LIMIT_MACROS
132
+#CPPDEFS += -D__STDC_CONSTANT_MACROS
133
+
134
+
135
+
136
+#---------------- Compiler Options C ----------------
137
+#  -g*:          generate debugging information
138
+#  -O*:          optimization level
139
+#  -f...:        tuning, see GCC manual and avr-libc documentation
140
+#  -Wall...:     warning level
141
+#  -Wa,...:      tell GCC to pass this to the assembler.
142
+#    -adhlns...: create assembler listing
143
+CFLAGS = -g$(DEBUG)
144
+CFLAGS += $(CDEFS)
145
+CFLAGS += -O$(OPT)
146
+CFLAGS += -funsigned-char
147
+CFLAGS += -funsigned-bitfields
148
+CFLAGS += -ffunction-sections
149
+CFLAGS += -fpack-struct
150
+CFLAGS += -fshort-enums
151
+CFLAGS += -Wall
152
+CFLAGS += -Wstrict-prototypes
153
+#CFLAGS += -mshort-calls
154
+#CFLAGS += -fno-unit-at-a-time
155
+#CFLAGS += -Wundef
156
+#CFLAGS += -Wunreachable-code
157
+#CFLAGS += -Wsign-compare
158
+CFLAGS += -Wa,-adhlns=$(<:%.c=$(OBJDIR)/%.lst)
159
+CFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
160
+CFLAGS += $(CSTANDARD)
161
+
162
+
163
+#---------------- Compiler Options C++ ----------------
164
+#  -g*:          generate debugging information
165
+#  -O*:          optimization level
166
+#  -f...:        tuning, see GCC manual and avr-libc documentation
167
+#  -Wall...:     warning level
168
+#  -Wa,...:      tell GCC to pass this to the assembler.
169
+#    -adhlns...: create assembler listing
170
+CPPFLAGS = -g$(DEBUG)
171
+CPPFLAGS += $(CPPDEFS)
172
+CPPFLAGS += -O$(OPT)
173
+CPPFLAGS += -funsigned-char
174
+CPPFLAGS += -funsigned-bitfields
175
+CPPFLAGS += -fpack-struct
176
+CPPFLAGS += -fshort-enums
177
+CPPFLAGS += -fno-exceptions
178
+CPPFLAGS += -Wall
179
+CPPFLAGS += -Wundef
180
+#CPPFLAGS += -mshort-calls
181
+#CPPFLAGS += -fno-unit-at-a-time
182
+#CPPFLAGS += -Wstrict-prototypes
183
+#CPPFLAGS += -Wunreachable-code
184
+#CPPFLAGS += -Wsign-compare
185
+CPPFLAGS += -Wa,-adhlns=$(<:%.cpp=$(OBJDIR)/%.lst)
186
+CPPFLAGS += $(patsubst %,-I%,$(EXTRAINCDIRS))
187
+#CPPFLAGS += $(CSTANDARD)
188
+
189
+
190
+#---------------- Assembler Options ----------------
191
+#  -Wa,...:   tell GCC to pass this to the assembler.
192
+#  -adhlns:   create listing
193
+#  -gstabs:   have the assembler create line number information; note that
194
+#             for use in COFF files, additional information about filenames
195
+#             and function names needs to be present in the assembler source
196
+#             files -- see avr-libc docs [FIXME: not yet described there]
197
+#  -listing-cont-lines: Sets the maximum number of continuation lines of hex 
198
+#       dump that will be displayed for a given single line of source input.
199
+ASFLAGS = $(ADEFS) -Wa,-adhlns=$(<:%.S=$(OBJDIR)/%.lst),-gstabs,--listing-cont-lines=100
200
+
201
+
202
+#---------------- Library Options ----------------
203
+# Minimalistic printf version
204
+PRINTF_LIB_MIN = -Wl,-u,vfprintf -lprintf_min
205
+
206
+# Floating point printf version (requires MATH_LIB = -lm below)
207
+PRINTF_LIB_FLOAT = -Wl,-u,vfprintf -lprintf_flt
208
+
209
+# If this is left blank, then it will use the Standard printf version.
210
+PRINTF_LIB = 
211
+#PRINTF_LIB = $(PRINTF_LIB_MIN)
212
+#PRINTF_LIB = $(PRINTF_LIB_FLOAT)
213
+
214
+
215
+# Minimalistic scanf version
216
+SCANF_LIB_MIN = -Wl,-u,vfscanf -lscanf_min
217
+
218
+# Floating point + %[ scanf version (requires MATH_LIB = -lm below)
219
+SCANF_LIB_FLOAT = -Wl,-u,vfscanf -lscanf_flt
220
+
221
+# If this is left blank, then it will use the Standard scanf version.
222
+SCANF_LIB = 
223
+#SCANF_LIB = $(SCANF_LIB_MIN)
224
+#SCANF_LIB = $(SCANF_LIB_FLOAT)
225
+
226
+
227
+MATH_LIB = -lm
228
+
229
+
230
+# List any extra directories to look for libraries here.
231
+#     Each directory must be seperated by a space.
232
+#     Use forward slashes for directory separators.
233
+#     For a directory that has spaces, enclose it in quotes.
234
+EXTRALIBDIRS = 
235
+
236
+
237
+
238
+#---------------- External Memory Options ----------------
239
+
240
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
241
+# used for variables (.data/.bss) and heap (malloc()).
242
+#EXTMEMOPTS = -Wl,-Tdata=0x801100,--defsym=__heap_end=0x80ffff
243
+
244
+# 64 KB of external RAM, starting after internal RAM (ATmega128!),
245
+# only used for heap (malloc()).
246
+#EXTMEMOPTS = -Wl,--section-start,.data=0x801100,--defsym=__heap_end=0x80ffff
247
+
248
+EXTMEMOPTS =
249
+
250
+
251
+
252
+#---------------- Linker Options ----------------
253
+#  -Wl,...:     tell GCC to pass this to linker.
254
+#    -Map:      create map file
255
+#    --cref:    add cross reference to  map file
256
+LDFLAGS = -Wl,-Map=$(TARGET).map,--cref
257
+LDFLAGS += -Wl,--relax
258
+LDFLAGS += -Wl,--gc-sections
259
+LDFLAGS += $(EXTMEMOPTS)
260
+LDFLAGS += $(patsubst %,-L%,$(EXTRALIBDIRS))
261
+LDFLAGS += $(PRINTF_LIB) $(SCANF_LIB) $(MATH_LIB)
262
+#LDFLAGS += -T linker_script.x
263
+
264
+
265
+
266
+#---------------- Programming Options (avrdude) ----------------
267
+
268
+# Programming hardware
269
+# Type: avrdude -c ?
270
+# to get a full listing.
271
+#
272
+AVRDUDE_PROGRAMMER = stk500v2
273
+
274
+# com1 = serial port. Use lpt1 to connect to parallel port.
275
+AVRDUDE_PORT = com1    # programmer connected to serial device
276
+
277
+AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex
278
+#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep
279
+
280
+
281
+# Uncomment the following if you want avrdude's erase cycle counter.
282
+# Note that this counter needs to be initialized first using -Yn,
283
+# see avrdude manual.
284
+#AVRDUDE_ERASE_COUNTER = -y
285
+
286
+# Uncomment the following if you do /not/ wish a verification to be
287
+# performed after programming the device.
288
+#AVRDUDE_NO_VERIFY = -V
289
+
290
+# Increase verbosity level.  Please use this when submitting bug
291
+# reports about avrdude. See <http://savannah.nongnu.org/projects/avrdude> 
292
+# to submit bug reports.
293
+#AVRDUDE_VERBOSE = -v -v
294
+
295
+AVRDUDE_FLAGS = -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
296
+AVRDUDE_FLAGS += $(AVRDUDE_NO_VERIFY)
297
+AVRDUDE_FLAGS += $(AVRDUDE_VERBOSE)
298
+AVRDUDE_FLAGS += $(AVRDUDE_ERASE_COUNTER)
299
+
300
+
301
+
302
+#---------------- Debugging Options ----------------
303
+
304
+# For simulavr only - target MCU frequency.
305
+DEBUG_MFREQ = $(F_CPU)
306
+
307
+# Set the DEBUG_UI to either gdb or insight.
308
+# DEBUG_UI = gdb
309
+DEBUG_UI = insight
310
+
311
+# Set the debugging back-end to either avarice, simulavr.
312
+DEBUG_BACKEND = avarice
313
+#DEBUG_BACKEND = simulavr
314
+
315
+# GDB Init Filename.
316
+GDBINIT_FILE = __avr_gdbinit
317
+
318
+# When using avarice settings for the JTAG
319
+JTAG_DEV = /dev/com1
320
+
321
+# Debugging port used to communicate between GDB / avarice / simulavr.
322
+DEBUG_PORT = 4242
323
+
324
+# Debugging host used to communicate between GDB / avarice / simulavr, normally
325
+#     just set to localhost unless doing some sort of crazy debugging when 
326
+#     avarice is running on a different computer.
327
+DEBUG_HOST = localhost
328
+
329
+
330
+
331
+#============================================================================
332
+
333
+
334
+# Define programs and commands.
335
+SHELL = sh
336
+CC = avr-gcc
337
+OBJCOPY = avr-objcopy
338
+OBJDUMP = avr-objdump
339
+SIZE = avr-size
340
+AR = avr-ar rcs
341
+NM = avr-nm
342
+AVRDUDE = avrdude
343
+REMOVE = rm -f
344
+REMOVEDIR = rm -rf
345
+COPY = cp
346
+WINSHELL = cmd
347
+
348
+
349
+# Define Messages
350
+# English
351
+MSG_ERRORS_NONE = Errors: none
352
+MSG_BEGIN = -------- begin --------
353
+MSG_END = --------  end  --------
354
+MSG_SIZE_BEFORE = Size before: 
355
+MSG_SIZE_AFTER = Size after:
356
+MSG_COFF = Converting to AVR COFF:
357
+MSG_EXTENDED_COFF = Converting to AVR Extended COFF:
358
+MSG_FLASH = Creating load file for Flash:
359
+MSG_EEPROM = Creating load file for EEPROM:
360
+MSG_EXTENDED_LISTING = Creating Extended Listing:
361
+MSG_SYMBOL_TABLE = Creating Symbol Table:
362
+MSG_LINKING = Linking:
363
+MSG_COMPILING = Compiling C:
364
+MSG_COMPILING_CPP = Compiling C++:
365
+MSG_ASSEMBLING = Assembling:
366
+MSG_CLEANING = Cleaning project:
367
+MSG_CREATING_LIBRARY = Creating library:
368
+
369
+
370
+
371
+
372
+# Define all object files.
373
+OBJ = $(SRC:%.c=$(OBJDIR)/%.o) $(CPPSRC:%.cpp=$(OBJDIR)/%.o) $(ASRC:%.S=$(OBJDIR)/%.o) 
374
+
375
+# Define all listing files.
376
+LST = $(SRC:%.c=$(OBJDIR)/%.lst) $(CPPSRC:%.cpp=$(OBJDIR)/%.lst) $(ASRC:%.S=$(OBJDIR)/%.lst) 
377
+
378
+
379
+# Compiler flags to generate dependency files.
380
+GENDEPFLAGS = -MMD -MP -MF .dep/$(@F).d
381
+
382
+
383
+# Combine all necessary flags and optional flags.
384
+# Add target processor to flags.
385
+ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS) $(GENDEPFLAGS)
386
+ALL_CPPFLAGS = -mmcu=$(MCU) -I. -x c++ $(CPPFLAGS) $(GENDEPFLAGS)
387
+ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
388
+
389
+
390
+
391
+
392
+
393
+# Default target.
394
+all: begin gccversion sizebefore build sizeafter end
395
+
396
+# Change the build target to build a HEX file or a library.
397
+build: elf hex eep lss sym
398
+#build: lib
399
+
400
+
401
+elf: $(TARGET).elf
402
+hex: $(TARGET).hex
403
+eep: $(TARGET).eep
404
+lss: $(TARGET).lss
405
+sym: $(TARGET).sym
406
+LIBNAME=lib$(TARGET).a
407
+lib: $(LIBNAME)
408
+
409
+
410
+
411
+# Eye candy.
412
+# AVR Studio 3.x does not check make's exit code but relies on
413
+# the following magic strings to be generated by the compile job.
414
+begin:
415
+	@echo
416
+	@echo $(MSG_BEGIN)
417
+
418
+end:
419
+	@echo $(MSG_END)
420
+	@echo
421
+
422
+
423
+# Display size of file.
424
+HEXSIZE = $(SIZE) --target=$(FORMAT) $(TARGET).hex
425
+#ELFSIZE = $(SIZE) --mcu=$(MCU) --format=avr $(TARGET).elf
426
+ELFSIZE = $(SIZE) $(TARGET).elf
427
+
428
+sizebefore:
429
+	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_BEFORE); $(ELFSIZE); \
430
+	2>/dev/null; echo; fi
431
+
432
+sizeafter:
433
+	@if test -f $(TARGET).elf; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); \
434
+	2>/dev/null; echo; fi
435
+
436
+
437
+
438
+# Display compiler version information.
439
+gccversion : 
440
+	@$(CC) --version
441
+
442
+
443
+
444
+# Program the device.  
445
+program: $(TARGET).hex $(TARGET).eep
446
+	$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH) $(AVRDUDE_WRITE_EEPROM)
447
+
448
+
449
+# Generate avr-gdb config/init file which does the following:
450
+#     define the reset signal, load the target file, connect to target, and set 
451
+#     a breakpoint at main().
452
+gdb-config: 
453
+	@$(REMOVE) $(GDBINIT_FILE)
454
+	@echo define reset >> $(GDBINIT_FILE)
455
+	@echo SIGNAL SIGHUP >> $(GDBINIT_FILE)
456
+	@echo end >> $(GDBINIT_FILE)
457
+	@echo file $(TARGET).elf >> $(GDBINIT_FILE)
458
+	@echo target remote $(DEBUG_HOST):$(DEBUG_PORT)  >> $(GDBINIT_FILE)
459
+ifeq ($(DEBUG_BACKEND),simulavr)
460
+	@echo load  >> $(GDBINIT_FILE)
461
+endif
462
+	@echo break main >> $(GDBINIT_FILE)
463
+
464
+debug: gdb-config $(TARGET).elf
465
+ifeq ($(DEBUG_BACKEND), avarice)
466
+	@echo Starting AVaRICE - Press enter when "waiting to connect" message displays.
467
+	@$(WINSHELL) /c start avarice --jtag $(JTAG_DEV) --erase --program --file \
468
+	$(TARGET).elf $(DEBUG_HOST):$(DEBUG_PORT)
469
+	@$(WINSHELL) /c pause
470
+
471
+else
472
+	@$(WINSHELL) /c start simulavr --gdbserver --device $(MCU) --clock-freq \
473
+	$(DEBUG_MFREQ) --port $(DEBUG_PORT)
474
+endif
475
+	@$(WINSHELL) /c start avr-$(DEBUG_UI) --command=$(GDBINIT_FILE)
476
+
477
+
478
+
479
+
480
+# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
481
+COFFCONVERT = $(OBJCOPY) --debugging
482
+COFFCONVERT += --change-section-address .data-0x800000
483
+COFFCONVERT += --change-section-address .bss-0x800000
484
+COFFCONVERT += --change-section-address .noinit-0x800000
485
+COFFCONVERT += --change-section-address .eeprom-0x810000
486
+
487
+
488
+
489
+coff: $(TARGET).elf
490
+	@echo
491
+	@echo $(MSG_COFF) $(TARGET).cof
492
+	$(COFFCONVERT) -O coff-avr $< $(TARGET).cof
493
+
494
+
495
+extcoff: $(TARGET).elf
496
+	@echo
497
+	@echo $(MSG_EXTENDED_COFF) $(TARGET).cof
498
+	$(COFFCONVERT) -O coff-ext-avr $< $(TARGET).cof
499
+
500
+
501
+
502
+# Create final output files (.hex, .eep) from ELF output file.
503
+%.hex: %.elf
504
+	@echo
505
+	@echo $(MSG_FLASH) $@
506
+	$(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature $< $@
507
+
508
+%.eep: %.elf
509
+	@echo
510
+	@echo $(MSG_EEPROM) $@
511
+	-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
512
+	--change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) $< $@ || exit 0
513
+
514
+# Create extended listing file from ELF output file.
515
+%.lss: %.elf
516
+	@echo
517
+	@echo $(MSG_EXTENDED_LISTING) $@
518
+	$(OBJDUMP) -h -S -z $< > $@
519
+
520
+# Create a symbol table from ELF output file.
521
+%.sym: %.elf
522
+	@echo
523
+	@echo $(MSG_SYMBOL_TABLE) $@
524
+	$(NM) -n $< > $@
525
+
526
+
527
+
528
+# Create library from object files.
529
+.SECONDARY : $(TARGET).a
530
+.PRECIOUS : $(OBJ)
531
+%.a: $(OBJ)
532
+	@echo
533
+	@echo $(MSG_CREATING_LIBRARY) $@
534
+	$(AR) $@ $(OBJ)
535
+
536
+
537
+# Link: create ELF output file from object files.
538
+.SECONDARY : $(TARGET).elf
539
+.PRECIOUS : $(OBJ)
540
+%.elf: $(OBJ)
541
+	@echo
542
+	@echo $(MSG_LINKING) $@
543
+	$(CC) $(ALL_CFLAGS) $^ --output $@ $(LDFLAGS)
544
+
545
+
546
+# Compile: create object files from C source files.
547
+$(OBJDIR)/%.o : %.c
548
+	@echo
549
+	@echo $(MSG_COMPILING) $<
550
+	$(CC) -c $(ALL_CFLAGS) $< -o $@ 
551
+
552
+
553
+# Compile: create object files from C++ source files.
554
+$(OBJDIR)/%.o : %.cpp
555
+	@echo
556
+	@echo $(MSG_COMPILING_CPP) $<
557
+	$(CC) -c $(ALL_CPPFLAGS) $< -o $@ 
558
+
559
+
560
+# Compile: create assembler files from C source files.
561
+%.s : %.c
562
+	$(CC) -S $(ALL_CFLAGS) $< -o $@
563
+
564
+
565
+# Compile: create assembler files from C++ source files.
566
+%.s : %.cpp
567
+	$(CC) -S $(ALL_CPPFLAGS) $< -o $@
568
+
569
+
570
+# Assemble: create object files from assembler source files.
571
+$(OBJDIR)/%.o : %.S
572
+	@echo
573
+	@echo $(MSG_ASSEMBLING) $<
574
+	$(CC) -c $(ALL_ASFLAGS) $< -o $@
575
+
576
+
577
+# Create preprocessed source for use in sending a bug report.
578
+%.i : %.c
579
+	$(CC) -E -mmcu=$(MCU) -I. $(CFLAGS) $< -o $@ 
580
+
581
+
582
+# Target: clean project.
583
+clean: begin clean_list end
584
+
585
+clean_list :
586
+	@echo
587
+	@echo $(MSG_CLEANING)
588
+	$(REMOVE) $(TARGET).hex
589
+	$(REMOVE) $(TARGET).eep
590
+	$(REMOVE) $(TARGET).cof
591
+	$(REMOVE) $(TARGET).elf
592
+	$(REMOVE) $(TARGET).map
593
+	$(REMOVE) $(TARGET).sym
594
+	$(REMOVE) $(TARGET).lss
595
+	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.o)
596
+	$(REMOVE) $(SRC:%.c=$(OBJDIR)/%.lst)
597
+	$(REMOVE) $(SRC:.c=.s)
598
+	$(REMOVE) $(SRC:.c=.d)
599
+	$(REMOVE) $(SRC:.c=.i)
600
+	$(REMOVEDIR) .dep
601
+
602
+
603
+# Create object files directory
604
+$(shell mkdir $(OBJDIR) 2>/dev/null)
605
+
606
+
607
+# Include the dependency files.
608
+-include $(shell mkdir .dep 2>/dev/null) $(wildcard .dep/*)
609
+
610
+
611
+# Listing of phony targets.
612
+.PHONY : all begin finish end sizebefore sizeafter gccversion \
613
+build elf hex eep lss sym coff extcoff \
614
+clean clean_list program debug gdb-config

+ 130
- 0
example.c View File

@@ -0,0 +1,130 @@
1
+/* Keyboard example for Teensy USB Development Board
2
+ * http://www.pjrc.com/teensy/usb_keyboard.html
3
+ * Copyright (c) 2008 PJRC.COM, LLC
4
+ * 
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ * 
12
+ * The above copyright notice and this permission notice shall be included in
13
+ * all copies or substantial portions of the Software.
14
+ * 
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ * THE SOFTWARE.
22
+ */
23
+
24
+#include <avr/io.h>
25
+#include <avr/pgmspace.h>
26
+#include <avr/interrupt.h>
27
+#include <util/delay.h>
28
+#include "usb_keyboard.h"
29
+
30
+#define LED_CONFIG	(DDRD |= (1<<6))
31
+#define LED_ON		(PORTD &= ~(1<<6))
32
+#define LED_OFF		(PORTD |= (1<<6))
33
+#define CPU_PRESCALE(n)	(CLKPR = 0x80, CLKPR = (n))
34
+
35
+#undef STR_MANUFACTURER
36
+#undef STR_PRODUCT
37
+
38
+#define STR_MANUFACTURER	L"Clayton G. Hobbs"
39
+#define STR_PRODUCT		L"Music Score Foot Pedal"
40
+
41
+uint16_t idle_count = 0;
42
+uint8_t pressed = 0;
43
+uint8_t last = 0;
44
+
45
+int main(void)
46
+{
47
+	uint8_t d, mask;
48
+	uint8_t d_prev=0xFF;
49
+
50
+	// set for 16 MHz clock
51
+	CPU_PRESCALE(0);
52
+
53
+	// Configure all port B pins as inputs with pullup resistors.
54
+	// See the "Using I/O Pins" page for details.
55
+	// http://www.pjrc.com/teensy/pins.html
56
+	DDRD = 0x00;
57
+	PORTD = 0xFF;
58
+
59
+	// Initialize the USB, and then wait for the host to set configuration.
60
+	// If the Teensy is powered without a PC connected to the USB port,
61
+	// this will wait forever.
62
+	usb_init();
63
+	while (!usb_configured())
64
+        ;
65
+
66
+	// Wait an extra second for the PC's operating system to load drivers
67
+	// and do whatever it does to actually be ready for input
68
+	_delay_ms(1000);
69
+
70
+	// Configure timer 0 to generate a timer overflow interrupt every
71
+	// 256*1024 clock cycles, or approx 61 Hz when using 16 MHz clock
72
+	// This demonstrates how to use interrupts to implement a simple
73
+	// inactivity timeout.
74
+	TCCR0A = 0x00;
75
+	TCCR0B = 0x05;
76
+	TIMSK0 = (1<<TOIE0);
77
+
78
+	while (1) {
79
+		// read all port B and port D pins
80
+		d = PIND;
81
+		// check if any pins are low, but were high previously
82
+		mask = 1 << 5;
83
+		if (((d & mask) == 0) && (d_prev & mask) != 0) {
84
+            cli();
85
+            pressed += 1;
86
+            idle_count = 0;
87
+            sei();
88
+		}
89
+		// now the current pins will be the previous, and
90
+		// wait a short delay so we're not highly sensitive
91
+		// to mechanical "bounce".
92
+		d_prev = d;
93
+		_delay_ms(2);
94
+	}
95
+}
96
+
97
+// This interrupt routine is run approx 61 times per second.
98
+// All keypresses are sent here.  When a single press occurred with nothing
99
+// else for a whole second, send a page down.  Further presses less than a
100
+// second apart following that timeout send more page downs.  If after a period
101
+// of inactivity, two presses occur within one second, send a page up.  Further
102
+// presses less than a second apart send more page ups.
103
+ISR(TIMER0_OVF_vect)
104
+{
105
+	idle_count++;
106
+	if (idle_count > 30 && pressed > 0 && last != KEY_PAGE_UP) {
107
+        usb_keyboard_press(KEY_PAGE_DOWN, 0);
108
+        pressed -= 1;
109
+		idle_count = 0;
110
+        last = KEY_PAGE_DOWN;
111
+	} else if (idle_count <= 30 && pressed == 2 && last != KEY_PAGE_DOWN) {
112
+        usb_keyboard_press(KEY_PAGE_UP, 0);
113
+        pressed -= 1;
114
+        idle_count = 0;
115
+        last = KEY_PAGE_UP;
116
+    } else if (idle_count <= 30 && pressed > 0 && last == KEY_PAGE_DOWN) {
117
+        usb_keyboard_press(KEY_PAGE_DOWN, 0);
118
+        pressed -= 1;
119
+		idle_count = 0;
120
+        last = KEY_PAGE_DOWN;
121
+    } else if (idle_count > 30 && pressed == 0) {
122
+        last = 0;
123
+        pressed = 0;
124
+        idle_count = 0;
125
+    } else if (idle_count > 30 && pressed > 0 && last == KEY_PAGE_UP) {
126
+        last = 0;
127
+        pressed = 0;
128
+        idle_count = 0;
129
+    }
130
+}

+ 592
- 0
usb_keyboard.c View File

@@ -0,0 +1,592 @@
1
+/* USB Keyboard Example for Teensy USB Development Board
2
+ * http://www.pjrc.com/teensy/usb_keyboard.html
3
+ * Copyright (c) 2009 PJRC.COM, LLC
4
+ * 
5
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ * of this software and associated documentation files (the "Software"), to deal
7
+ * in the Software without restriction, including without limitation the rights
8
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ * copies of the Software, and to permit persons to whom the Software is
10
+ * furnished to do so, subject to the following conditions:
11
+ * 
12
+ * The above copyright notice and this permission notice shall be included in
13
+ * all copies or substantial portions of the Software.
14
+ * 
15
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ * THE SOFTWARE.
22
+ */
23
+
24
+// Version 1.0: Initial Release
25
+// Version 1.1: Add support for Teensy 2.0
26
+
27
+#define USB_SERIAL_PRIVATE_INCLUDE
28
+#include "usb_keyboard.h"
29
+
30
+/**************************************************************************
31
+ *
32
+ *  Configurable Options
33
+ *
34
+ **************************************************************************/
35
+
36
+// You can change these to give your code its own name.
37
+#define STR_MANUFACTURER	L"Clayton G. Hobbs"
38
+#define STR_PRODUCT		L"Music Score Foot Pedal"
39
+
40
+
41
+// Mac OS-X and Linux automatically load the correct drivers.  On
42
+// Windows, even though the driver is supplied by Microsoft, an
43
+// INF file is needed to load the driver.  These numbers need to
44
+// match the INF file.
45
+#define VENDOR_ID		0x16C0
46
+#define PRODUCT_ID		0x047C
47
+
48
+
49
+// USB devices are supposed to implment a halt feature, which is
50
+// rarely (if ever) used.  If you comment this line out, the halt
51
+// code will be removed, saving 102 bytes of space (gcc 4.3.0).
52
+// This is not strictly USB compliant, but works with all major
53
+// operating systems.
54
+#define SUPPORT_ENDPOINT_HALT
55
+
56
+
57
+
58
+/**************************************************************************
59
+ *
60
+ *  Endpoint Buffer Configuration
61
+ *
62
+ **************************************************************************/
63
+
64
+#define ENDPOINT0_SIZE		32
65
+
66
+#define KEYBOARD_INTERFACE	0
67
+#define KEYBOARD_ENDPOINT	3
68
+#define KEYBOARD_SIZE		8
69
+#define KEYBOARD_BUFFER		EP_DOUBLE_BUFFER
70
+
71
+static const uint8_t PROGMEM endpoint_config_table[] = {
72
+	0,
73
+	0,
74
+	1, EP_TYPE_INTERRUPT_IN,  EP_SIZE(KEYBOARD_SIZE) | KEYBOARD_BUFFER,
75
+	0
76
+};
77
+
78
+
79
+/**************************************************************************
80
+ *
81
+ *  Descriptor Data
82
+ *
83
+ **************************************************************************/
84
+
85
+// Descriptors are the data that your computer reads when it auto-detects
86
+// this USB device (called "enumeration" in USB lingo).  The most commonly
87
+// changed items are editable at the top of this file.  Changing things
88
+// in here should only be done by those who've read chapter 9 of the USB
89
+// spec and relevant portions of any USB class specifications!
90
+
91
+
92
+static const uint8_t PROGMEM device_descriptor[] = {
93
+	18,					// bLength
94
+	1,					// bDescriptorType
95
+	0x00, 0x02,				// bcdUSB
96
+	0,					// bDeviceClass
97
+	0,					// bDeviceSubClass
98
+	0,					// bDeviceProtocol
99
+	ENDPOINT0_SIZE,				// bMaxPacketSize0
100
+	LSB(VENDOR_ID), MSB(VENDOR_ID),		// idVendor
101
+	LSB(PRODUCT_ID), MSB(PRODUCT_ID),	// idProduct
102
+	0x00, 0x01,				// bcdDevice
103
+	1,					// iManufacturer
104
+	2,					// iProduct
105
+	0,					// iSerialNumber
106
+	1					// bNumConfigurations
107
+};
108
+
109
+// Keyboard Protocol 1, HID 1.11 spec, Appendix B, page 59-60
110
+static const uint8_t PROGMEM keyboard_hid_report_desc[] = {
111
+        0x05, 0x01,          // Usage Page (Generic Desktop),
112
+        0x09, 0x06,          // Usage (Keyboard),
113
+        0xA1, 0x01,          // Collection (Application),
114
+        0x75, 0x01,          //   Report Size (1),
115
+        0x95, 0x08,          //   Report Count (8),
116
+        0x05, 0x07,          //   Usage Page (Key Codes),
117
+        0x19, 0xE0,          //   Usage Minimum (224),
118
+        0x29, 0xE7,          //   Usage Maximum (231),
119
+        0x15, 0x00,          //   Logical Minimum (0),
120
+        0x25, 0x01,          //   Logical Maximum (1),
121
+        0x81, 0x02,          //   Input (Data, Variable, Absolute), ;Modifier byte
122
+        0x95, 0x01,          //   Report Count (1),
123
+        0x75, 0x08,          //   Report Size (8),
124
+        0x81, 0x03,          //   Input (Constant),                 ;Reserved byte
125
+        0x95, 0x05,          //   Report Count (5),
126
+        0x75, 0x01,          //   Report Size (1),
127
+        0x05, 0x08,          //   Usage Page (LEDs),
128
+        0x19, 0x01,          //   Usage Minimum (1),
129
+        0x29, 0x05,          //   Usage Maximum (5),
130
+        0x91, 0x02,          //   Output (Data, Variable, Absolute), ;LED report
131
+        0x95, 0x01,          //   Report Count (1),
132
+        0x75, 0x03,          //   Report Size (3),
133
+        0x91, 0x03,          //   Output (Constant),                 ;LED report padding
134
+        0x95, 0x06,          //   Report Count (6),
135
+        0x75, 0x08,          //   Report Size (8),
136
+        0x15, 0x00,          //   Logical Minimum (0),
137
+        0x25, 0x68,          //   Logical Maximum(104),
138
+        0x05, 0x07,          //   Usage Page (Key Codes),
139
+        0x19, 0x00,          //   Usage Minimum (0),
140
+        0x29, 0x68,          //   Usage Maximum (104),
141
+        0x81, 0x00,          //   Input (Data, Array),
142
+        0xc0                 // End Collection
143
+};
144
+
145
+#define CONFIG1_DESC_SIZE        (9+9+9+7)
146
+#define KEYBOARD_HID_DESC_OFFSET (9+9)
147
+static const uint8_t PROGMEM config1_descriptor[CONFIG1_DESC_SIZE] = {
148
+	// configuration descriptor, USB spec 9.6.3, page 264-266, Table 9-10
149
+	9, 					// bLength;
150
+	2,					// bDescriptorType;
151
+	LSB(CONFIG1_DESC_SIZE),			// wTotalLength
152
+	MSB(CONFIG1_DESC_SIZE),
153
+	1,					// bNumInterfaces
154
+	1,					// bConfigurationValue
155
+	0,					// iConfiguration
156
+	0xC0,					// bmAttributes
157
+	50,					// bMaxPower
158
+	// interface descriptor, USB spec 9.6.5, page 267-269, Table 9-12
159
+	9,					// bLength
160
+	4,					// bDescriptorType
161
+	KEYBOARD_INTERFACE,			// bInterfaceNumber
162
+	0,					// bAlternateSetting
163
+	1,					// bNumEndpoints
164
+	0x03,					// bInterfaceClass (0x03 = HID)
165
+	0x01,					// bInterfaceSubClass (0x01 = Boot)
166
+	0x01,					// bInterfaceProtocol (0x01 = Keyboard)
167
+	0,					// iInterface
168
+	// HID interface descriptor, HID 1.11 spec, section 6.2.1
169
+	9,					// bLength
170
+	0x21,					// bDescriptorType
171
+	0x11, 0x01,				// bcdHID
172
+	0,					// bCountryCode
173
+	1,					// bNumDescriptors
174
+	0x22,					// bDescriptorType
175
+	sizeof(keyboard_hid_report_desc),	// wDescriptorLength
176
+	0,
177
+	// endpoint descriptor, USB spec 9.6.6, page 269-271, Table 9-13
178
+	7,					// bLength
179
+	5,					// bDescriptorType
180
+	KEYBOARD_ENDPOINT | 0x80,		// bEndpointAddress
181
+	0x03,					// bmAttributes (0x03=intr)
182
+	KEYBOARD_SIZE, 0,			// wMaxPacketSize
183
+	1					// bInterval
184
+};
185
+
186
+// If you're desperate for a little extra code memory, these strings
187
+// can be completely removed if iManufacturer, iProduct, iSerialNumber
188
+// in the device desciptor are changed to zeros.
189
+struct usb_string_descriptor_struct {
190
+	uint8_t bLength;
191
+	uint8_t bDescriptorType;
192
+	int16_t wString[];
193
+};
194
+static const struct usb_string_descriptor_struct PROGMEM string0 = {
195
+	4,
196
+	3,
197
+	{0x0409}
198
+};
199
+static const struct usb_string_descriptor_struct PROGMEM string1 = {
200
+	sizeof(STR_MANUFACTURER),
201
+	3,
202
+	STR_MANUFACTURER
203
+};
204
+static const struct usb_string_descriptor_struct PROGMEM string2 = {
205
+	sizeof(STR_PRODUCT),
206
+	3,
207
+	STR_PRODUCT
208
+};
209
+
210
+// This table defines which descriptor data is sent for each specific
211
+// request from the host (in wValue and wIndex).
212
+static struct descriptor_list_struct {
213
+	uint16_t	wValue;
214
+	uint16_t	wIndex;
215
+	const uint8_t	*addr;
216
+	uint8_t		length;
217
+} const PROGMEM descriptor_list[] = {
218
+	{0x0100, 0x0000, device_descriptor, sizeof(device_descriptor)},
219
+	{0x0200, 0x0000, config1_descriptor, sizeof(config1_descriptor)},
220
+	{0x2200, KEYBOARD_INTERFACE, keyboard_hid_report_desc, sizeof(keyboard_hid_report_desc)},
221
+	{0x2100, KEYBOARD_INTERFACE, config1_descriptor+KEYBOARD_HID_DESC_OFFSET, 9},
222
+	{0x0300, 0x0000, (const uint8_t *)&string0, 4},
223
+	{0x0301, 0x0409, (const uint8_t *)&string1, sizeof(STR_MANUFACTURER)},
224
+	{0x0302, 0x0409, (const uint8_t *)&string2, sizeof(STR_PRODUCT)}
225
+};
226
+#define NUM_DESC_LIST (sizeof(descriptor_list)/sizeof(struct descriptor_list_struct))
227
+
228
+
229
+/**************************************************************************
230
+ *
231
+ *  Variables - these are the only non-stack RAM usage
232
+ *
233
+ **************************************************************************/
234
+
235
+// zero when we are not configured, non-zero when enumerated
236
+static volatile uint8_t usb_configuration=0;
237
+
238
+// which modifier keys are currently pressed
239
+// 1=left ctrl,    2=left shift,   4=left alt,    8=left gui
240
+// 16=right ctrl, 32=right shift, 64=right alt, 128=right gui
241
+uint8_t keyboard_modifier_keys=0;
242
+
243
+// which keys are currently pressed, up to 6 keys may be down at once
244
+uint8_t keyboard_keys[6]={0,0,0,0,0,0};
245
+
246
+// protocol setting from the host.  We use exactly the same report
247
+// either way, so this variable only stores the setting since we
248
+// are required to be able to report which setting is in use.
249
+static uint8_t keyboard_protocol=1;
250
+
251
+// the idle configuration, how often we send the report to the
252
+// host (ms * 4) even when it hasn't changed
253
+static uint8_t keyboard_idle_config=125;
254
+
255
+// count until idle timeout
256
+static uint8_t keyboard_idle_count=0;
257
+
258
+// 1=num lock, 2=caps lock, 4=scroll lock, 8=compose, 16=kana
259
+volatile uint8_t keyboard_leds=0;
260
+
261
+
262
+/**************************************************************************
263
+ *
264
+ *  Public Functions - these are the API intended for the user
265
+ *
266
+ **************************************************************************/
267
+
268
+
269
+// initialize USB
270
+void usb_init(void)
271
+{
272
+	HW_CONFIG();
273
+	USB_FREEZE();	// enable USB
274
+	PLL_CONFIG();				// config PLL
275
+        while (!(PLLCSR & (1<<PLOCK))) ;	// wait for PLL lock
276
+        USB_CONFIG();				// start USB clock
277
+        UDCON = 0;				// enable attach resistor
278
+	usb_configuration = 0;
279
+        UDIEN = (1<<EORSTE)|(1<<SOFE);
280
+	sei();
281
+}
282
+
283
+// return 0 if the USB is not configured, or the configuration
284
+// number selected by the HOST
285
+uint8_t usb_configured(void)
286
+{
287
+	return usb_configuration;
288
+}
289
+
290
+
291
+// perform a single keystroke
292
+int8_t usb_keyboard_press(uint8_t key, uint8_t modifier)
293
+{
294
+	int8_t r;
295
+
296
+	keyboard_modifier_keys = modifier;
297
+	keyboard_keys[0] = key;
298
+	r = usb_keyboard_send();
299
+	if (r) return r;
300
+	keyboard_modifier_keys = 0;
301
+	keyboard_keys[0] = 0;
302
+	return usb_keyboard_send();
303
+}
304
+
305
+// send the contents of keyboard_keys and keyboard_modifier_keys
306
+int8_t usb_keyboard_send(void)
307
+{
308
+	uint8_t i, intr_state, timeout;
309
+
310
+	if (!usb_configuration) return -1;
311
+	intr_state = SREG;
312
+	cli();
313
+	UENUM = KEYBOARD_ENDPOINT;
314
+	timeout = UDFNUML + 50;
315
+	while (1) {
316
+		// are we ready to transmit?
317
+		if (UEINTX & (1<<RWAL)) break;
318
+		SREG = intr_state;
319
+		// has the USB gone offline?
320
+		if (!usb_configuration) return -1;
321
+		// have we waited too long?
322
+		if (UDFNUML == timeout) return -1;
323
+		// get ready to try checking again
324
+		intr_state = SREG;
325
+		cli();
326
+		UENUM = KEYBOARD_ENDPOINT;
327
+	}
328
+	UEDATX = keyboard_modifier_keys;
329
+	UEDATX = 0;
330
+	for (i=0; i<6; i++) {
331
+		UEDATX = keyboard_keys[i];
332
+	}
333
+	UEINTX = 0x3A;
334
+	keyboard_idle_count = 0;
335
+	SREG = intr_state;
336
+	return 0;
337
+}
338
+
339
+/**************************************************************************
340
+ *
341
+ *  Private Functions - not intended for general user consumption....
342
+ *
343
+ **************************************************************************/
344
+
345
+
346
+
347
+// USB Device Interrupt - handle all device-level events
348
+// the transmit buffer flushing is triggered by the start of frame
349
+//
350
+ISR(USB_GEN_vect)
351
+{
352
+	uint8_t intbits, t, i;
353
+	static uint8_t div4=0;
354
+
355
+        intbits = UDINT;
356
+        UDINT = 0;
357
+        if (intbits & (1<<EORSTI)) {
358
+		UENUM = 0;
359
+		UECONX = 1;
360
+		UECFG0X = EP_TYPE_CONTROL;
361
+		UECFG1X = EP_SIZE(ENDPOINT0_SIZE) | EP_SINGLE_BUFFER;
362
+		UEIENX = (1<<RXSTPE);
363
+		usb_configuration = 0;
364
+        }
365
+	if ((intbits & (1<<SOFI)) && usb_configuration) {
366
+		if (keyboard_idle_config && (++div4 & 3) == 0) {
367
+			UENUM = KEYBOARD_ENDPOINT;
368
+			if (UEINTX & (1<<RWAL)) {
369
+				keyboard_idle_count++;
370
+				if (keyboard_idle_count == keyboard_idle_config) {
371
+					keyboard_idle_count = 0;
372
+					UEDATX = keyboard_modifier_keys;
373
+					UEDATX = 0;
374
+					for (i=0; i<6; i++) {
375
+						UEDATX = keyboard_keys[i];
376
+					}
377
+					UEINTX = 0x3A;
378
+				}
379
+			}
380
+		}
381
+	}
382
+}
383
+
384
+
385
+
386
+// Misc functions to wait for ready and send/receive packets
387
+static inline void usb_wait_in_ready(void)
388
+{
389
+	while (!(UEINTX & (1<<TXINI))) ;
390
+}
391
+static inline void usb_send_in(void)
392
+{
393
+	UEINTX = ~(1<<TXINI);
394
+}
395
+static inline void usb_wait_receive_out(void)
396
+{
397
+	while (!(UEINTX & (1<<RXOUTI))) ;
398
+}
399
+static inline void usb_ack_out(void)
400
+{
401
+	UEINTX = ~(1<<RXOUTI);
402
+}
403
+
404
+
405
+
406
+// USB Endpoint Interrupt - endpoint 0 is handled here.  The
407
+// other endpoints are manipulated by the user-callable
408
+// functions, and the start-of-frame interrupt.
409
+//
410
+ISR(USB_COM_vect)
411
+{
412
+        uint8_t intbits;
413
+	const uint8_t *list;
414
+        const uint8_t *cfg;
415
+	uint8_t i, n, len, en;
416
+	uint8_t bmRequestType;
417
+	uint8_t bRequest;
418
+	uint16_t wValue;
419
+	uint16_t wIndex;
420
+	uint16_t wLength;
421
+	uint16_t desc_val;
422
+	const uint8_t *desc_addr;
423
+	uint8_t	desc_length;
424
+
425
+        UENUM = 0;
426
+	intbits = UEINTX;
427
+        if (intbits & (1<<RXSTPI)) {
428
+                bmRequestType = UEDATX;
429
+                bRequest = UEDATX;
430
+                wValue = UEDATX;
431
+                wValue |= (UEDATX << 8);
432
+                wIndex = UEDATX;
433
+                wIndex |= (UEDATX << 8);
434
+                wLength = UEDATX;
435
+                wLength |= (UEDATX << 8);
436
+                UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
437
+                if (bRequest == GET_DESCRIPTOR) {
438
+			list = (const uint8_t *)descriptor_list;
439
+			for (i=0; ; i++) {
440
+				if (i >= NUM_DESC_LIST) {
441
+					UECONX = (1<<STALLRQ)|(1<<EPEN);  //stall
442
+					return;
443
+				}
444
+				desc_val = pgm_read_word(list);
445
+				if (desc_val != wValue) {
446
+					list += sizeof(struct descriptor_list_struct);
447
+					continue;
448
+				}
449
+				list += 2;
450
+				desc_val = pgm_read_word(list);
451
+				if (desc_val != wIndex) {
452
+					list += sizeof(struct descriptor_list_struct)-2;
453
+					continue;
454
+				}
455
+				list += 2;
456
+				desc_addr = (const uint8_t *)pgm_read_word(list);
457
+				list += 2;
458
+				desc_length = pgm_read_byte(list);
459
+				break;
460
+			}
461
+			len = (wLength < 256) ? wLength : 255;
462
+			if (len > desc_length) len = desc_length;
463
+			do {
464
+				// wait for host ready for IN packet
465
+				do {
466
+					i = UEINTX;
467
+				} while (!(i & ((1<<TXINI)|(1<<RXOUTI))));
468
+				if (i & (1<<RXOUTI)) return;	// abort
469
+				// send IN packet
470
+				n = len < ENDPOINT0_SIZE ? len : ENDPOINT0_SIZE;
471
+				for (i = n; i; i--) {
472
+					UEDATX = pgm_read_byte(desc_addr++);
473
+				}
474
+				len -= n;
475
+				usb_send_in();
476
+			} while (len || n == ENDPOINT0_SIZE);
477
+			return;
478
+                }
479
+		if (bRequest == SET_ADDRESS) {
480
+			usb_send_in();
481
+			usb_wait_in_ready();
482
+			UDADDR = wValue | (1<<ADDEN);
483
+			return;
484
+		}
485
+		if (bRequest == SET_CONFIGURATION && bmRequestType == 0) {
486
+			usb_configuration = wValue;
487
+			usb_send_in();
488
+			cfg = endpoint_config_table;
489
+			for (i=1; i<5; i++) {
490
+				UENUM = i;
491
+				en = pgm_read_byte(cfg++);
492
+				UECONX = en;
493
+				if (en) {
494
+					UECFG0X = pgm_read_byte(cfg++);
495
+					UECFG1X = pgm_read_byte(cfg++);
496
+				}
497
+			}
498
+        		UERST = 0x1E;
499
+        		UERST = 0;
500
+			return;
501
+		}
502
+		if (bRequest == GET_CONFIGURATION && bmRequestType == 0x80) {
503
+			usb_wait_in_ready();
504
+			UEDATX = usb_configuration;
505
+			usb_send_in();
506
+			return;
507
+		}
508
+
509
+		if (bRequest == GET_STATUS) {
510
+			usb_wait_in_ready();
511
+			i = 0;
512
+			#ifdef SUPPORT_ENDPOINT_HALT
513
+			if (bmRequestType == 0x82) {
514
+				UENUM = wIndex;
515
+				if (UECONX & (1<<STALLRQ)) i = 1;
516
+				UENUM = 0;
517
+			}
518
+			#endif
519
+			UEDATX = i;
520
+			UEDATX = 0;
521
+			usb_send_in();
522
+			return;
523
+		}
524
+		#ifdef SUPPORT_ENDPOINT_HALT
525
+		if ((bRequest == CLEAR_FEATURE || bRequest == SET_FEATURE)
526
+		  && bmRequestType == 0x02 && wValue == 0) {
527
+			i = wIndex & 0x7F;
528
+			if (i >= 1 && i <= MAX_ENDPOINT) {
529
+				usb_send_in();
530
+				UENUM = i;
531
+				if (bRequest == SET_FEATURE) {
532
+					UECONX = (1<<STALLRQ)|(1<<EPEN);
533
+				} else {
534
+					UECONX = (1<<STALLRQC)|(1<<RSTDT)|(1<<EPEN);
535
+					UERST = (1 << i);
536
+					UERST = 0;
537
+				}
538
+				return;
539
+			}
540
+		}
541
+		#endif
542
+		if (wIndex == KEYBOARD_INTERFACE) {
543
+			if (bmRequestType == 0xA1) {
544
+				if (bRequest == HID_GET_REPORT) {
545
+					usb_wait_in_ready();
546
+					UEDATX = keyboard_modifier_keys;
547
+					UEDATX = 0;
548
+					for (i=0; i<6; i++) {
549
+						UEDATX = keyboard_keys[i];
550
+					}
551
+					usb_send_in();
552
+					return;
553
+				}
554
+				if (bRequest == HID_GET_IDLE) {
555
+					usb_wait_in_ready();
556
+					UEDATX = keyboard_idle_config;
557
+					usb_send_in();
558
+					return;
559
+				}
560
+				if (bRequest == HID_GET_PROTOCOL) {
561
+					usb_wait_in_ready();
562
+					UEDATX = keyboard_protocol;
563
+					usb_send_in();
564
+					return;
565
+				}
566
+			}
567
+			if (bmRequestType == 0x21) {
568
+				if (bRequest == HID_SET_REPORT) {
569
+					usb_wait_receive_out();
570
+					keyboard_leds = UEDATX;
571
+					usb_ack_out();
572
+					usb_send_in();
573
+					return;
574
+				}
575
+				if (bRequest == HID_SET_IDLE) {
576
+					keyboard_idle_config = (wValue >> 8);
577
+					keyboard_idle_count = 0;
578
+					usb_send_in();
579
+					return;
580
+				}
581
+				if (bRequest == HID_SET_PROTOCOL) {
582
+					keyboard_protocol = wValue;
583
+					usb_send_in();
584
+					return;
585
+				}
586
+			}
587
+		}
588
+	}
589
+	UECONX = (1<<STALLRQ) | (1<<EPEN);	// stall
590
+}
591
+
592
+

+ 206
- 0
usb_keyboard.h View File

@@ -0,0 +1,206 @@
1
+#ifndef usb_serial_h__
2
+#define usb_serial_h__
3
+
4
+#include <stdint.h>
5
+
6
+void usb_init(void);			// initialize everything
7
+uint8_t usb_configured(void);		// is the USB port configured
8
+
9
+int8_t usb_keyboard_press(uint8_t key, uint8_t modifier);
10
+int8_t usb_keyboard_send(void);
11
+extern uint8_t keyboard_modifier_keys;
12
+extern uint8_t keyboard_keys[6];
13
+extern volatile uint8_t keyboard_leds;
14
+
15
+// This file does not include the HID debug functions, so these empty
16
+// macros replace them with nothing, so users can compile code that
17
+// has calls to these functions.
18
+#define usb_debug_putchar(c)
19
+#define usb_debug_flush_output()
20
+
21
+
22
+#define KEY_CTRL	0x01
23
+#define KEY_SHIFT	0x02
24
+#define KEY_ALT		0x04
25
+#define KEY_GUI		0x08
26
+#define KEY_LEFT_CTRL	0x01
27
+#define KEY_LEFT_SHIFT	0x02
28
+#define KEY_LEFT_ALT	0x04
29
+#define KEY_LEFT_GUI	0x08
30
+#define KEY_RIGHT_CTRL	0x10
31
+#define KEY_RIGHT_SHIFT	0x20
32
+#define KEY_RIGHT_ALT	0x40
33
+#define KEY_RIGHT_GUI	0x80
34
+
35
+#define KEY_A		4
36
+#define KEY_B		5
37
+#define KEY_C		6
38
+#define KEY_D		7
39
+#define KEY_E		8
40
+#define KEY_F		9
41
+#define KEY_G		10
42
+#define KEY_H		11
43
+#define KEY_I		12
44
+#define KEY_J		13
45
+#define KEY_K		14
46
+#define KEY_L		15
47
+#define KEY_M		16
48
+#define KEY_N		17
49
+#define KEY_O		18
50
+#define KEY_P		19
51
+#define KEY_Q		20
52
+#define KEY_R		21
53
+#define KEY_S		22
54
+#define KEY_T		23
55
+#define KEY_U		24
56
+#define KEY_V		25
57
+#define KEY_W		26
58
+#define KEY_X		27
59
+#define KEY_Y		28
60
+#define KEY_Z		29
61
+#define KEY_1		30
62
+#define KEY_2		31
63
+#define KEY_3		32
64
+#define KEY_4		33
65
+#define KEY_5		34
66
+#define KEY_6		35
67
+#define KEY_7		36
68
+#define KEY_8		37
69
+#define KEY_9		38
70
+#define KEY_0		39
71
+#define KEY_ENTER	40	
72
+#define KEY_ESC		41
73
+#define KEY_BACKSPACE	42	
74
+#define KEY_TAB		43
75
+#define KEY_SPACE	44	
76
+#define KEY_MINUS	45
77
+#define KEY_EQUAL	46
78
+#define KEY_LEFT_BRACE	47
79
+#define KEY_RIGHT_BRACE	48
80
+#define KEY_BACKSLASH	49
81
+#define KEY_NUMBER	50
82
+#define KEY_SEMICOLON	51
83
+#define KEY_QUOTE	52
84
+#define KEY_TILDE	53
85
+#define KEY_COMMA	54
86
+#define KEY_PERIOD	55
87
+#define KEY_SLASH	56
88
+#define KEY_CAPS_LOCK	57
89
+#define KEY_F1		58
90
+#define KEY_F2		59
91
+#define KEY_F3		60
92
+#define KEY_F4		61
93
+#define KEY_F5		62
94
+#define KEY_F6		63
95
+#define KEY_F7		64
96
+#define KEY_F8		65
97
+#define KEY_F9		66
98
+#define KEY_F10		67
99
+#define KEY_F11		68
100
+#define KEY_F12		69
101
+#define KEY_PRINTSCREEN	70		
102
+#define KEY_SCROLL_LOCK	71		
103
+#define KEY_PAUSE	72
104
+#define KEY_INSERT	73	
105
+#define KEY_HOME	74
106
+#define KEY_PAGE_UP	75
107
+#define KEY_DELETE	76
108
+#define KEY_END		77
109
+#define KEY_PAGE_DOWN	78	
110
+#define KEY_RIGHT	79
111
+#define KEY_LEFT	80
112
+#define KEY_DOWN	81
113
+#define KEY_UP		82
114
+#define KEY_NUM_LOCK	83
115
+#define KEYPAD_SLASH	84	
116
+#define KEYPAD_ASTERIX	85	
117
+#define KEYPAD_MINUS	86	
118
+#define KEYPAD_PLUS	87	
119
+#define KEYPAD_ENTER	88	
120
+#define KEYPAD_1	89
121
+#define KEYPAD_2	90
122
+#define KEYPAD_3	91	
123
+#define KEYPAD_4	92	
124
+#define KEYPAD_5	93	
125
+#define KEYPAD_6	94	
126
+#define KEYPAD_7	95	
127
+#define KEYPAD_8	96	
128
+#define KEYPAD_9	97	
129
+#define KEYPAD_0	98		
130
+#define KEYPAD_PERIOD	99		
131
+
132
+
133
+
134
+
135
+// Everything below this point is only intended for usb_serial.c
136
+#ifdef USB_SERIAL_PRIVATE_INCLUDE
137
+#include <avr/io.h>
138
+#include <avr/pgmspace.h>
139
+#include <avr/interrupt.h>
140
+
141
+#define EP_TYPE_CONTROL			0x00
142
+#define EP_TYPE_BULK_IN			0x81
143
+#define EP_TYPE_BULK_OUT		0x80
144
+#define EP_TYPE_INTERRUPT_IN		0xC1
145
+#define EP_TYPE_INTERRUPT_OUT		0xC0
146
+#define EP_TYPE_ISOCHRONOUS_IN		0x41
147
+#define EP_TYPE_ISOCHRONOUS_OUT		0x40
148
+
149
+#define EP_SINGLE_BUFFER		0x02
150
+#define EP_DOUBLE_BUFFER		0x06
151
+
152
+#define EP_SIZE(s)	((s) == 64 ? 0x30 :	\
153
+			((s) == 32 ? 0x20 :	\
154
+			((s) == 16 ? 0x10 :	\
155
+			             0x00)))
156
+
157
+#define MAX_ENDPOINT		4
158
+
159
+#define LSB(n) (n & 255)
160
+#define MSB(n) ((n >> 8) & 255)
161
+
162
+#if defined(__AVR_AT90USB162__)
163
+#define HW_CONFIG() 
164
+#define PLL_CONFIG() (PLLCSR = ((1<<PLLE)|(1<<PLLP0)))
165
+#define USB_CONFIG() (USBCON = (1<<USBE))
166
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
167
+#elif defined(__AVR_ATmega32U4__)
168
+#define HW_CONFIG() (UHWCON = 0x01)
169
+#define PLL_CONFIG() (PLLCSR = 0x12)
170
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
171
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
172
+#elif defined(__AVR_AT90USB646__)
173
+#define HW_CONFIG() (UHWCON = 0x81)
174
+#define PLL_CONFIG() (PLLCSR = 0x1A)
175
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
176
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
177
+#elif defined(__AVR_AT90USB1286__)
178
+#define HW_CONFIG() (UHWCON = 0x81)
179
+#define PLL_CONFIG() (PLLCSR = 0x16)
180
+#define USB_CONFIG() (USBCON = ((1<<USBE)|(1<<OTGPADE)))
181
+#define USB_FREEZE() (USBCON = ((1<<USBE)|(1<<FRZCLK)))
182
+#endif
183
+
184
+// standard control endpoint request types
185
+#define GET_STATUS			0
186
+#define CLEAR_FEATURE			1
187
+#define SET_FEATURE			3
188
+#define SET_ADDRESS			5
189
+#define GET_DESCRIPTOR			6
190
+#define GET_CONFIGURATION		8
191
+#define SET_CONFIGURATION		9
192
+#define GET_INTERFACE			10
193
+#define SET_INTERFACE			11
194
+// HID (human interface device)
195
+#define HID_GET_REPORT			1
196
+#define HID_GET_IDLE			2
197
+#define HID_GET_PROTOCOL		3
198
+#define HID_SET_REPORT			9
199
+#define HID_SET_IDLE			10
200
+#define HID_SET_PROTOCOL		11
201
+// CDC (communication class device)
202
+#define CDC_SET_LINE_CODING		0x20
203
+#define CDC_GET_LINE_CODING		0x21
204
+#define CDC_SET_CONTROL_LINE_STATE	0x22
205
+#endif
206
+#endif

Loading…
Cancel
Save