Compare commits

...

69 Commits

Author SHA1 Message Date
optixx
a1e3ef36b4 Make bootloader 1 work 2016-08-20 18:13:08 +02:00
optixx
f8bd7384b5 Integrate fastlz 2016-08-07 20:55:43 +00:00
optixx
2532119248 Prepar fastlz integration 2016-07-16 17:16:04 +02:00
optixx
d5560260b3 Cleanup 2016-07-16 17:15:16 +02:00
optixx
8a190c9f10 Make ringbuffer work 2016-05-22 17:49:07 +02:00
optixx
f6a15f0f4a Remove neginf 2016-05-22 15:20:03 +02:00
optixx
9479d2b1ff Merge branch 'master' of github.com:optixx/quickdev16 2016-05-22 15:15:17 +02:00
optixx
a616e7ce9b Add fastlz poc 2016-05-22 15:15:04 +02:00
optixx
ca61ddd7ac Add new ucon64 version 2016-05-22 15:14:14 +02:00
optixx
15abd671fe Build current firmware with rle compression 2016-05-22 15:13:49 +02:00
optixx
f8db20fccb Cleanup 2016-05-22 15:13:27 +02:00
optixx
ed77542227 Delete how2code.txt 2016-05-15 13:16:46 +02:00
optixx
fd6d31d5ba Delete pilotwings.pdf 2016-05-15 13:16:15 +02:00
optixx
6c496e5818 Delete board_cpld_01.png 2016-05-15 13:16:03 +02:00
optixx
2722c94be4 Rename snes_cart1.txt to Snes_cart_hacking.txt 2016-05-15 13:15:44 +02:00
optixx
0f54fd946a Rename SNES.DOC to SNES Documentation v1.3 2016-05-15 13:14:44 +02:00
optixx
d13609aaed Delete SNES-ROM.TXT 2016-05-15 13:14:27 +02:00
optixx
39e7e980f8 Rename Sneskart.txt to Sneskart_v1.6.txt 2016-05-15 13:14:10 +02:00
optixx
6c2f39b958 Delete SNESROM.PIN 2016-05-15 13:13:52 +02:00
optixx
681dbb20d0 Rename Snesrom.txt to Snesrom_v1.5.txt 2016-05-15 13:13:37 +02:00
optixx
8012584ade Delete Architektur des SNES - Final.doc 2016-05-15 13:12:09 +02:00
optixx
896fb09230 Delete SNESKART.doc 2016-05-15 13:11:29 +02:00
optixx
77e391a829 Add stuff from inflate branch 2016-02-21 20:22:59 +01:00
optixx
b30acd54d2 Add fastlz 2016-02-21 16:32:43 +01:00
optixx
dad06d8ae9 Add pcb files 2016-02-15 17:47:10 +01:00
optixx
f743bf5ea9 Add missing docs 2016-02-15 17:42:39 +01:00
optixx
7270dac4c8 Merge branch 'master' of github.com:optixx/quickdev16 2016-02-14 21:34:33 +01:00
optixx
ac8485aaca Transfer files from assembla 2016-02-14 21:14:15 +01:00
optixx
aa79e81ff6 Update README.md 2016-02-13 21:18:09 +01:00
optixx
c0a1a3e2a1 Update README.md 2016-02-13 21:17:40 +01:00
optixx
8051c9e81f Update and rename README to README.md 2016-02-13 21:16:42 +01:00
optixx
ff3588a7f9 Add images 2016-02-13 20:59:56 +01:00
optixx
ce32aff421 Add firmware 2016-02-13 20:45:17 +01:00
optixx
9fc469a42f Add images 2016-02-13 20:41:49 +01:00
optixx
1170d1ce73 Add ucon64 image 2016-02-13 19:55:41 +01:00
optixx
4e17d3daee Move files from assembla to the github repo 2016-02-13 19:46:40 +01:00
optixx
ce8042c926 PEP Cleanup and remove abs paths 2016-02-09 22:16:01 +01:00
optixx
69616740eb Update osx project 2016-02-09 21:59:51 +01:00
optixx
b09aa72e38 Update software version 2016-02-09 21:39:36 +01:00
optixx
123ca226ab Remove old ucon64 2016-02-09 21:36:15 +01:00
optixx
cf41986ccc Make bootload compile with latest avr-gcc 2016-02-09 12:32:32 +01:00
optixx
a0e072da2a Switch to new vusb 2016-02-09 12:30:47 +01:00
optixx
c8d91b4bbf Switch to new vusb 2016-02-09 12:30:31 +01:00
optixx
08b4654b5c Backup old vusb version used by bootloaser and usbload 2016-02-09 12:29:59 +01:00
optixx
31ab89bbae Add new vusb package 2016-02-09 12:29:43 +01:00
optixx
8fe9e51889 Add latest ucon64 version 2016-02-09 12:29:30 +01:00
optixx
a27d555590 Remove obsolete files 2016-02-09 12:28:43 +01:00
optixx
d435901077 Cleanup 2016-02-09 12:01:48 +01:00
optixx
c09d1a1918 indent cleanup 2010-07-19 16:35:47 +02:00
optixx
0f0c6eb409 remove compiler warnings 2010-07-19 16:33:55 +02:00
optixx
2ebdf15efa remove debug 2010-07-19 16:25:16 +02:00
optixx
b9bc6ff728 enable globals 2009-11-17 12:49:48 +01:00
optixx
f10da9afed Merge branch 'master' of git://github.com/gilligan/quickdev16 2009-11-17 12:46:45 +01:00
Tobias Pflug
7739b59bb8 o Minor cleanup including command line argument fix 2009-11-13 16:05:04 +01:00
Tobias Pflug
72b0e1e667 Added rle encoded ips chunk support 2009-11-13 16:05:04 +01:00
Tobias Pflug
0a9a87f3bd changed bank count to 5 2009-11-13 16:05:04 +01:00
Tobias Pflug
b927fbf93b - qdips: patch chunk upload working but fw transfer bug remains
usb bulk transfers copy the last byte of the chunk to SRAM twice.
2009-11-13 16:05:03 +01:00
Tobias Pflug
297b10ccf7 o Added qdips - still nonworking so far 2009-11-13 16:05:03 +01:00
Tobias Pflug
d7c767dbc7 - double write fix 2009-11-13 16:01:27 +01:00
optixx
f12c8d811f Merge branch 'master' of github.com:optixx/quickdev16 2009-11-02 07:55:22 +01:00
optixx
c263264706 fix double write 2009-11-02 07:55:02 +01:00
Tobias Pflug
c520e850b4 Merge branch 'master' of git://github.com/optixx/quickdev16 2009-11-01 11:27:00 +01:00
optixx
6751aec407 update AVR_BTLDR_SWITCH_ENABLE handling 2009-10-30 17:52:36 +01:00
Tobias Pflug
e0dd846013 Switched to getopt, fixed minor issues and some cleanups. 2009-10-24 17:51:00 +02:00
optixx
d471173fcc loader reload timing bug 2009-10-24 17:49:27 +02:00
optixx
2701270e05 cleanup 2009-10-24 16:45:36 +02:00
optixx
9d72708064 fix minor race with qdinc 2009-10-24 16:43:49 +02:00
optixx
fe0df3430b patch avrdude timeout 2009-10-24 13:23:54 +02:00
Tobias Pflug
62c6e22ae6 Switched to getopt, fixed minor issues and some cleanups. 2009-10-21 20:28:33 +02:00
1371 changed files with 206793 additions and 111265 deletions

5
.gitignore vendored
View File

@ -34,5 +34,10 @@ tmtags
bsnes
web
ucon64.exe
project
huffman-decode
huffman-encode
unpack
pack

View File

@ -1,3 +1,4 @@
```
________ .__ __ ________ ____ ________
\_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
/ / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
@ -5,4 +6,6 @@
\_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
\__> \/ \/ \/ \/ \/
www.optixx.org
```
[Go to the Documentation](../../wiki)

View File

@ -471,13 +471,12 @@ int __attribute__ ((noreturn, OS_main)) main(void)
jump_to_app();
}
#ifdef AVR_BTLDR_SWITCH ENABLE
#if AVR_BTLDR_SWITCH_ENABLE
if ((AVR_BTLDR_EN_IN & ( 1 << AVR_BTLDR_EN_PIN)) == 0){
banner();
uart_puts("Bootloader flashing is disabled\n\r");
MCUSR = 0;
leave_bootloader();
}
#endif

View File

@ -20,3 +20,4 @@
#define DEBUG 1
#define DEBUG_USB 2
#define AVR_BTLDR_SWITCH_ENABLE 1

View File

@ -231,3 +231,99 @@ Scroll down to the bottom to see the most recent changes.
- Added 20 MHz module contributed by Jeroen Benschop.
* Release 2008-05-13
- Fixed bug in libs-host/hiddata.c function usbhidGetReport(): length
was not incremented, pointer to length was incremented instead.
- Added code to command line tool(s) which claims an interface. This code
is disabled by default, but may be necessary on newer Linux kernels.
- Added usbconfig.h option "USB_CFG_CHECK_DATA_TOGGLING".
- New header "usbportability.h" prepares ports to other development
environments.
- Long transfers (above 254 bytes) did not work when usbFunctionRead() was
used to supply the data. Fixed this bug. [Thanks to Alexander Neumann!]
- In hiddata.c (example code for sending/receiving data over HID), use
USB_RECIP_DEVICE instead of USB_RECIP_INTERFACE for control transfers so
that we need not claim the interface.
- in usbPoll() loop 20 times polling for RESET state instead of 10 times.
This accounts for the higher clock rates we now support.
- Added a module for 12.8 MHz RC oscillator with PLL in receiver loop.
- Added hook to SOF code so that oscillator can be tuned to USB frame clock.
- Added timeout to waitForJ loop. Helps preventing unexpected hangs.
- Added example code for oscillator tuning to libs-device (thanks to
Henrik Haftmann for the idea to this routine).
- Implemented option USB_CFG_SUPPRESS_INTR_CODE.
* Release 2008-10-22
- Fixed libs-device/osctune.h: OSCCAL is memory address on ATMega88 and
similar, not offset of 0x20 needs to be added.
- Allow distribution under GPLv3 for those who have to link against other
code distributed under GPLv3.
* Release 2008-11-26
- Removed libusb-win32 dependency for hid-data example in Makefile.windows.
It was never required and confused many people.
- Added extern uchar usbRxToken to usbdrv.h.
- Integrated a module with CRC checks at 18 MHz by Lukas Schrittwieser.
* Release 2009-03-23
- Hid-mouse example used settings from hid-data example, fixed that.
- Renamed project to V-USB due to a trademark issue with Atmel(r).
- Changed CommercialLicense.txt and USBID-License.txt to make the
background of USB ID registration clearer.
* Release 2009-04-15
- Changed CommercialLicense.txt to reflect the new range of PIDs from
Jason Kotzin.
- Removed USBID-License.txt in favor of USB-IDs-for-free.txt and
USB-ID-FAQ.txt
- Fixed a bug in the 12.8 MHz module: End Of Packet decection was made in
the center between bit 0 and 1 of each byte. This is where the data lines
are expected to change and the sampled data may therefore be nonsense.
We therefore check EOP ONLY if bits 0 AND 1 have both been read as 0 on D-.
- Fixed a bitstuffing problem in the 16 MHz module: If bit 6 was stuffed,
the unstuffing code in the receiver routine was 1 cycle too long. If
multiple bytes had the unstuffing in bit 6, the error summed up until the
receiver was out of sync.
- Included option for faster CRC routine.
Thanks to Slawomir Fras (BoskiDialer) for this code!
- Updated bits in Configuration Descriptor's bmAttributes according to
USB 1.1 (in particular bit 7, it is a must-be-set bit now).
* Release 2009-08-22
- Moved first DBG1() after odDebugInit() in all examples.
- Use vector INT0_vect instead of SIG_INTERRUPT0 if defined. This makes
V-USB compatible with the new "p" suffix devices (e.g. ATMega328p).
- USB_CFG_CLOCK_KHZ setting is now required in usbconfig.h (no default any
more).
- New option USB_CFG_DRIVER_FLASH_PAGE allows boot loaders on devices with
more than 64 kB flash.
- Built-in configuration descriptor allows custom definition for second
endpoint now.
* Release 2010-07-15
- Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255
bytes.
- Avoid a compiler warning for unused parameter in usbHandleResetHook() when
compiler option -Wextra is enabled.
- Fixed wrong hex value for some IDs in USB-IDs-for-free.txt.
- Keep a define for USBATTR_BUSPOWER, although the flag does not exist
in USB 1.1 any more. Set it to 0. This is for backward compatibility.
* Release 2012-01-09
- Define a separate (defined) type for usbMsgPtr so that projects using a
tiny memory model can define it to an 8 bit type in usbconfig.h. This
change also saves a couple of bytes when using a scalar 16 bit type.
- Inserted "const" keyword for all PROGMEM declarations because new GCC
requires it.
- Fixed problem with dependence of usbportability.h on usbconfig.h. This
problem occurred with IAR CC only.
- Prepared repository for github.com.
* Release 2012-12-06

View File

@ -1,5 +1,5 @@
AVR-USB Driver Software License Agreement
Version 2008-04-15
V-USB Driver Software License Agreement
Version 2012-07-09
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
@ -13,8 +13,8 @@ Grosse Schiffgasse 1A/7, 1020 Wien, AUSTRIA.
1.2 "You" shall mean the Licensee.
1.3 "AVR-USB" shall mean all files included in the package distributed under
the name "avrusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/avrusb/)
1.3 "V-USB" shall mean all files included in the package distributed under
the name "vusb" by OBJECTIVE DEVELOPMENT (http://www.obdev.at/vusb/)
unless otherwise noted. This includes the firmware-only USB device
implementation for Atmel AVR microcontrollers, some simple device examples
and host side software examples and libraries.
@ -23,21 +23,31 @@ and host side software examples and libraries.
2 LICENSE GRANTS
2.1 Source Code. OBJECTIVE DEVELOPMENT shall furnish you with the source
code of AVR-USB.
code of V-USB.
2.2 Distribution and Use. OBJECTIVE DEVELOPMENT grants you the
non-exclusive right to use and distribute AVR-USB with your hardware
non-exclusive right to use, copy and distribute V-USB with your hardware
product(s), restricted by the limitations in section 3 below.
2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify
your copy of AVR-USB according to your needs.
the source code and your copy of V-USB according to your needs.
2.4 USB IDs. OBJECTIVE DEVELOPMENT grants you the exclusive rights to use
USB Product ID(s) sent to you in e-mail after receiving your payment in
conjunction with USB Vendor ID 5824. OBJECTIVE DEVELOPMENT has acquired an
exclusive license for this pair of USB identifiers from Wouter van Ooijen
(www.voti.nl), who has licensed the VID from the USB Implementers Forum,
Inc. (www.usb.org).
2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB
Product ID(s), sent to you in e-mail. These Product IDs are reserved
exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID
ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen
Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from
Jason Kotzin (now flirc.tv, Inc.). Both owners of the Vendor IDs have
obtained these IDs from the USB Implementers Forum, Inc. (www.usb.org).
OBJECTIVE DEVELOPMENT disclaims all liability which might arise from the
assignment of USB IDs.
2.5 USB Certification. Although not part of this agreement, we want to make
it clear that you cannot become USB certified when you use V-USB or a USB
Product ID assigned by OBJECTIVE DEVELOPMENT. AVR microcontrollers don't
meet the electrical specifications required by the USB specification and
the USB Implementers Forum certifies only members who bought a Vendor ID of
their own.
3 LICENSE RESTRICTIONS
@ -46,21 +56,21 @@ Inc. (www.usb.org).
applicable. Which one is determined by the amount you pay to OBJECTIVE
DEVELOPMENT, see section 4 ("Payment") below.
Hobby License: You may use AVR-USB according to section 2 above in no more
Hobby License: You may use V-USB according to section 2 above in no more
than 5 hardware units. These units must not be sold for profit.
Entry Level License: You may use AVR-USB according to section 2 above in no
Entry Level License: You may use V-USB according to section 2 above in no
more than 150 hardware units.
Professional License: You may use AVR-USB according to section 2 above in
Professional License: You may use V-USB according to section 2 above in
any number of hardware units, except for large scale production ("unlimited
fair use"). Quantities below 10,000 units are not considered large scale
production. If your reach quantities which are obviously large scale
production, you must pay a license fee of 0.10 EUR per unit for all units
above 10,000.
3.2 Rental. You may not rent, lease, or lend AVR-USB or otherwise encumber
any copy of AVR-USB, or any of the rights granted herein.
3.2 Rental. You may not rent, lease, or lend V-USB or otherwise encumber
any copy of V-USB, or any of the rights granted herein.
3.3 Transfer. You may not transfer your rights under this Agreement to
another party without OBJECTIVE DEVELOPMENT's prior written consent. If
@ -78,7 +88,7 @@ non-exclusive.
by third parties. In particular, you are not allowed to use the USB logo or
other trademarks owned by the USB Implementers Forum, Inc. without their
consent. Since such consent depends on USB certification, it should be
noted that AVR-USB will not pass certification because it does not
noted that V-USB will not pass certification because it does not
implement checksum verification and the microcontroller ports do not meet
the electrical specifications.
@ -88,15 +98,15 @@ the electrical specifications.
The payment amount depends on the variation of this agreement (according to
section 3.1) into which you want to enter. Concrete prices are listed on
OBJECTIVE DEVELOPMENT's web site, usually at
http://www.obdev.at/avrusb/license.html. You agree to pay the amount listed
http://www.obdev.at/vusb/license.html. You agree to pay the amount listed
there to OBJECTIVE DEVELOPMENT or OBJECTIVE DEVELOPMENT's payment processor
or reseller.
5 COPYRIGHT AND OWNERSHIP
AVR-USB is protected by copyright laws and international copyright
treaties, as well as other intellectual property laws and treaties. AVR-USB
V-USB is protected by copyright laws and international copyright
treaties, as well as other intellectual property laws and treaties. V-USB
is licensed, not sold.
@ -112,12 +122,12 @@ and limitation of liability shall survive termination of this agreement.
7 DISCLAIMER OF WARRANTY AND LIABILITY
LIMITED WARRANTY. AVR-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
LIMITED WARRANTY. V-USB IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, OBJECTIVE
DEVELOPMENT AND ITS SUPPLIERS HEREBY DISCLAIM ALL WARRANTIES, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
NON-INFRINGEMENT, WITH REGARD TO AVR-USB, AND THE PROVISION OF OR FAILURE
NON-INFRINGEMENT, WITH REGARD TO V-USB, AND THE PROVISION OF OR FAILURE
TO PROVIDE SUPPORT SERVICES. THIS LIMITED WARRANTY GIVES YOU SPECIFIC LEGAL
RIGHTS. YOU MAY HAVE OTHERS, WHICH VARY FROM STATE/JURISDICTION TO
STATE/JURISDICTION.
@ -127,11 +137,11 @@ IN NO EVENT SHALL OBJECTIVE DEVELOPMENT OR ITS SUPPLIERS BE LIABLE FOR ANY
SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES WHATSOEVER
(INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS,
BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR ANY OTHER PECUNIARY
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE AVR-USB OR THE
LOSS) ARISING OUT OF THE USE OF OR INABILITY TO USE V-USB OR THE
PROVISION OF OR FAILURE TO PROVIDE SUPPORT SERVICES, EVEN IF OBJECTIVE
DEVELOPMENT HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IN ANY
CASE, OBJECTIVE DEVELOPMENT'S ENTIRE LIABILITY UNDER ANY PROVISION OF THIS
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR AVR-USB.
AGREEMENT SHALL BE LIMITED TO THE AMOUNT ACTUALLY PAID BY YOU FOR V-USB.
8 MISCELLANEOUS TERMS

View File

@ -1,16 +1,18 @@
OBJECTIVE DEVELOPMENT GmbH's AVR-USB driver software is distributed under the
terms and conditions of the GNU GPL version 2, see the text below. In addition
to the requirements in the GPL, we STRONGLY ENCOURAGE you to do the following:
OBJECTIVE DEVELOPMENT GmbH's V-USB driver software is distributed under the
terms and conditions of the GNU GPL version 2 or the GNU GPL version 3. It is
your choice whether you apply the terms of version 2 or version 3. The full
text of GPLv2 is included below. In addition to the requirements in the GPL,
we STRONGLY ENCOURAGE you to do the following:
(1) Publish your entire project on a web site and drop us a note with the URL.
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
(2) Adhere to minimum publication standards. Please include AT LEAST:
- a circuit diagram in PDF, PNG or GIF format
- full source code for the host software
- a Readme.txt file in ASCII format which describes the purpose of the
project and what can be found in which directories and which files
- a reference to http://www.obdev.at/avrusb/
- a reference to http://www.obdev.at/vusb/
(3) If you improve the driver firmware itself, please give us a free license
to your modifications for our commercial license offerings.

View File

@ -1,6 +1,6 @@
This is the Readme file to Objective Development's firmware-only USB driver
for Atmel AVR microcontrollers. For more information please visit
http://www.obdev.at/avrusb/
http://www.obdev.at/vusb/
This directory contains the USB firmware only. Copy it as-is to your own
project and add all .c and .S files to your project (these files are marked
@ -33,26 +33,26 @@ The driver consists of the following files:
defined to a value greater than 0. Link this module
to your code!
oddebug.h .............. Interface definitions of the debug module.
iarcompat.h ............ Compatibility definitions for IAR C-compiler.
usbportability.h ....... Header with compiler-dependent stuff.
usbdrvasm.asm .......... Compatibility stub for IAR-C-compiler. Use this
module instead of usbdrvasm.S when you assembler
with IAR's tools.
License.txt ............ Open Source license for this driver.
CommercialLicense.txt .. Optional commercial license for this driver.
USBID-License.txt ...... Terms and conditions for using particular USB ID
values for particular purposes.
USB-ID-FAQ.txt ......... General infos about USB Product- and Vendor-IDs.
USB-IDs-for-free.txt ... List and terms of use for free shared PIDs.
(*) ... These files should be linked to your project.
CPU CORE CLOCK FREQUENCY
========================
We supply assembler modules for clock frequencies of 12 MHz, 15 MHz, 16 MHz and
16.5 MHz. Other clock rates are not supported. The actual clock rate must be
configured in usbdrv.h unless you use the default 12 MHz.
We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz,
16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The
actual clock rate must be configured in usbconfig.h.
12 MHz Clock
This is the traditional clock rate of AVR-USB because it's the lowest clock
This is the traditional clock rate of V-USB because it's the lowest clock
rate where the timing constraints of the USB spec can be met.
15 MHz Clock
@ -67,19 +67,29 @@ if you need the slightly higher clock rate for performance reasons. Since
16 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
is somewhat tricky and has to insert a leap cycle every third byte.
16.5 MHz Clock
The assembler module for this clock rate differs from the other modules because
it has been built for an RC oscillator with only 1% precision. The receiver
code inserts leap cycles to compensate for clock deviations. 1% is also the
precision which can be achieved by calibrating the internal RC oscillator of
the AVR. Please note that only AVRs with internal 64 MHz PLL oscillator can be
used since the 8 MHz RC oscillator cannot be trimmed up to 16.5 MHz. This
includes the very popular ATTiny25, ATTiny45, ATTiny85 series as well as the
ATTiny26.
12.8 MHz and 16.5 MHz Clock
The assembler modules for these clock rates differ from the other modules
because they have been built for an RC oscillator with only 1% precision. The
receiver code inserts leap cycles to compensate for clock deviations. 1% is
also the precision which can be achieved by calibrating the internal RC
oscillator of the AVR. Please note that only AVRs with internal 64 MHz PLL
oscillator can reach 16.5 MHz with the RC oscillator. This includes the very
popular ATTiny25, ATTiny45, ATTiny85 series as well as the ATTiny26. Almost
all AVRs can reach 12.8 MHz, although this is outside the specified range.
See the EasyLogger example at http://www.obdev.at/avrusb/easylogger.html for
See the EasyLogger example at http://www.obdev.at/vusb/easylogger.html for
code which calibrates the RC oscillator based on the USB frame clock.
18 MHz Clock
This module is closer to the USB specification because it performs an on the
fly CRC check for incoming packets. Packets with invalid checksum are
discarded as required by the spec. If you also implement checks for data
PID toggling on application level (see option USB_CFG_CHECK_DATA_TOGGLING
in usbconfig.h for more info), this ensures data integrity. Due to the CRC
tables and alignment requirements, this code is bigger than modules for other
clock rates. To activate this module, you must define USB_CFG_CHECK_CRC to 1
and USB_CFG_CLOCK_KHZ to 18000 in usbconfig.h.
20 MHz Clock
This module is for people who won't do it with less than the maximum. Since
20 MHz is not divisible by the USB low speed bit clock of 1.5 MHz, the code
@ -94,53 +104,69 @@ can assign PIDs at will.
Since an entry level cost of 1,500 USD is too high for most small companies
and hobbyists, we provide some VID/PID pairs for free. See the file
USBID-License.txt for details.
USB-IDs-for-free.txt for details.
Objective Development also has some license offerings which include product
IDs. See http://www.obdev.at/avrusb/ for details.
IDs. See http://www.obdev.at/vusb/ for details.
DEVELOPMENT SYSTEM
==================
This driver has been developed and optimized for the GNU compiler version 3
(gcc 3). It does work well with gcc 4, but with bigger code size. We recommend
that you use the GNU compiler suite because it is freely available. AVR-USB
has also been ported to the IAR compiler and assembler. It has been tested
with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the "small" and "tiny"
memory model. Not every release is tested with IAR CC and the driver may
therefore fail to compile with IAR. Please note that gcc is more efficient for
usbdrv.c because this module has been deliberately optimized for gcc.
and 4. We recommend that you use the GNU compiler suite because it is freely
available. V-USB has also been ported to the IAR compiler and assembler. It
has been tested with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the
"small" and "tiny" memory model. Not every release is tested with IAR CC and
the driver may therefore fail to compile with IAR. Please note that gcc is
more efficient for usbdrv.c because this module has been deliberately
optimized for gcc.
Gcc version 3 produces smaller code than version 4 due to new optimizing
capabilities which don't always improve things on 8 bit CPUs. The code size
generated by gcc 4 can be reduced with the compiler options
-fno-move-loop-invariants, -fno-tree-scev-cprop and
-fno-inline-small-functions in addition to -Os. On devices with more than
8k of flash memory, we also recommend the linker option --relax (written as
-Wl,--relax for gcc) to convert absolute calls into relative where possible.
For more information about optimizing options see:
http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html
These optimizations are good for gcc 4.x. Version 3.x of gcc does not support
most of these options and produces good code anyway.
USING AVR-USB FOR FREE
======================
USING V-USB FOR FREE
====================
The AVR firmware driver is published under the GNU General Public License
Version 2 (GPL2). See the file "License.txt" for details.
Version 2 (GPL2) and the GNU General Public License Version 3 (GPL3). It is
your choice whether you apply the terms of version 2 or version 3.
If you decide for the free GPL2, we STRONGLY ENCOURAGE you to do the following
things IN ADDITION to the obligations from the GPL2:
If you decide for the free GPL2 or GPL3, we STRONGLY ENCOURAGE you to do the
following things IN ADDITION to the obligations from the GPL:
(1) Publish your entire project on a web site and drop us a note with the URL.
Use the form at http://www.obdev.at/avrusb/feedback.html for your submission.
Use the form at http://www.obdev.at/vusb/feedback.html for your submission.
If you don't have a web site, you can publish the project in obdev's
documentation wiki at
http://www.obdev.at/goto.php?t=avrusb-wiki&p=hosted-projects.
http://www.obdev.at/goto.php?t=vusb-wiki&p=hosted-projects.
(2) Adhere to minimum publication standards. Please include AT LEAST:
- a circuit diagram in PDF, PNG or GIF format
- full source code for the host software
- a Readme.txt file in ASCII format which describes the purpose of the
project and what can be found in which directories and which files
- a reference to http://www.obdev.at/avrusb/
- a reference to http://www.obdev.at/vusb/
(3) If you improve the driver firmware itself, please give us a free license
to your modifications for our commercial license offerings.
COMMERCIAL LICENSES FOR AVR-USB
===============================
If you don't want to publish your source code under the terms of the GPL2,
you can simply pay money for AVR-USB. As an additional benefit you get
USB PIDs for free, licensed exclusively to you. See the file
COMMERCIAL LICENSES FOR V-USB
=============================
If you don't want to publish your source code under the terms of the GPL,
you can simply pay money for V-USB. As an additional benefit you get
USB PIDs for free, reserved exclusively to you. See the file
"CommercialLicense.txt" for details.

View File

@ -1,11 +1,10 @@
/* Name: asmcommon.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-11-05
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id$
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -103,8 +102,11 @@ sofError:
reti
handleData:
lds token, usbCurrentTok;[18]
tst token ;[20]
#if USB_CFG_CHECK_CRC
CRC_CLEANUP_AND_CHECK ; jumps to ignorePacket if CRC error
#endif
lds shift, usbCurrentTok;[18]
tst shift ;[20]
breq doReturn ;[21]
lds x2, usbRxLen ;[22]
tst x2 ;[24]
@ -113,8 +115,11 @@ handleData:
; recognized if usbPoll() was called less frequently than once every 4 ms.
cpi cnt, 4 ;[26] zero sized data packets are status phase only -- ignore and ack
brmi sendAckAndReti ;[27] keep rx buffer clean -- we must not NAK next SETUP
#if USB_CFG_CHECK_DATA_TOGGLING
sts usbCurrentDataToken, token ; store for checking by C code
#endif
sts usbRxLen, cnt ;[28] store received data, swap buffers
sts usbRxToken, token ;[30]
sts usbRxToken, shift ;[30]
lds x2, usbInputBufOffset;[32] swap buffers
ldi cnt, USB_BUFSIZE ;[34]
sub cnt, x2 ;[35]
@ -131,7 +136,11 @@ handleIn:
ldi x1, USBPID_NAK ;[34] prepare value for usbTxLen
#if USB_CFG_HAVE_INTRIN_ENDPOINT
andi x3, 0xf ;[35] x3 contains endpoint
#if USB_CFG_SUPPRESS_INTR_CODE
brne sendNakAndReti ;[36]
#else
brne handleIn1 ;[36]
#endif
#endif
lds cnt, usbTxLen ;[37]
sbrc cnt, 4 ;[39] all handshake tokens have bit 4 set
@ -150,7 +159,7 @@ handleIn:
; RAM this way and avoid potential problems with endless retries. The rest of
; the driver assumes error-free transfers anyway.
#if USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
#if !USB_CFG_SUPPRESS_INTR_CODE && USB_CFG_HAVE_INTRIN_ENDPOINT /* placed here due to relative jump range */
handleIn1: ;[38]
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
; 2006-06-10 as suggested by O.Tamura: support second INTR IN / BULK IN endpoint
@ -164,9 +173,8 @@ handleIn1: ;[38]
ldi YL, lo8(usbTxBuf1) ;[46]
ldi YH, hi8(usbTxBuf1) ;[47]
rjmp usbSendAndReti ;[48] 50 + 12 = 62 until SOP
#endif
#if USB_CFG_HAVE_INTRIN_ENDPOINT && USB_CFG_HAVE_INTRIN_ENDPOINT3
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
handleIn3:
lds cnt, usbTxLen3 ;[41]
sbrc cnt, 4 ;[43]
@ -176,3 +184,4 @@ handleIn3:
ldi YH, hi8(usbTxBuf3) ;[48]
rjmp usbSendAndReti ;[49] 51 + 12 = 63 until SOP
#endif
#endif

View File

@ -4,8 +4,7 @@
* Creation Date: 2005-01-16
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: oddebug.c 275 2007-03-20 09:58:28Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
#include "oddebug.h"

View File

@ -4,8 +4,7 @@
* Creation Date: 2005-01-16
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: oddebug.h 275 2007-03-20 09:58:28Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
#ifndef __oddebug_h_included__
@ -29,10 +28,7 @@ the output and a memory block to dump in hex ('data' and 'len').
#endif
/* make sure we have the UART defines: */
#include "iarcompat.h"
#ifndef __IAR_SYSTEMS_ICC__
# include <avr/io.h>
#endif
#include "usbportability.h"
#ifndef uchar
# define uchar unsigned char

View File

@ -1,11 +1,10 @@
/* Name: usbconfig.h
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2005-04-01
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbconfig-prototype.h 600 2008-05-13 10:34:56Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
#ifndef __usbconfig_h_included__
@ -14,7 +13,7 @@
/*
General Description:
This file is an example configuration (with inline documentation) for the USB
driver. It configures AVR-USB for USB D+ connected to Port D bit 2 (which is
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
other hardware interrupt, as long as it is the highest level interrupt, see
@ -44,11 +43,19 @@ section at the end of this file).
* markers every millisecond.]
*/
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
/* Clock rate of the AVR in MHz. Legal values are 12000, 15000, 16000, 16500
* and 20000. The 16.5 MHz version of the code requires no crystal, it
* tolerates +/- 1% deviation from the nominal frequency. All other rates
* require a precision of 2000 ppm and thus a crystal!
* Default if not specified: 12 MHz
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code
* require no crystal, they tolerate +/- 1% deviation from the nominal
* frequency. All other rates require a precision of 2000 ppm and thus a
* crystal!
* Since F_CPU should be defined to your actual clock rate anyway, you should
* not need to modify this setting.
*/
#define USB_CFG_CHECK_CRC 0
/* Define this to 1 if you want that the driver checks integrity of incoming
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
* currently only available for 18 MHz crystal clock. You must choose
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
*/
/* ----------------------- Optional Hardware Config ------------------------ */
@ -94,6 +101,14 @@ section at the end of this file).
* it is required by the standard. We have made it a config option because it
* bloats the code considerably.
*/
#define USB_CFG_SUPPRESS_INTR_CODE 0
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
* want to send any data over them. If this macro is defined to 1, functions
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
* you need the interrupt-in endpoints in order to comply to an interface
* (e.g. HID), but never want to send any data. This option saves a couple
* of bytes in flash memory and the transmit buffers in RAM.
*/
#define USB_CFG_INTR_POLL_INTERVAL 10
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
* interval. The value is in milliseconds and must not be less than 10 ms for
@ -130,6 +145,11 @@ section at the end of this file).
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
* usbdrv.h.
*/
#define USB_CFG_DRIVER_FLASH_PAGE 0
/* If the device has more than 64 kBytes of flash, define this to the 64 k page
* where the driver's constants (descriptors) are located. Or in other words:
* Define this to 1 for boot loaders on the ATMega128.
*/
#define USB_CFG_LONG_TRANSFERS 0
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
* in a single control-in or control-out transfer. Note that the capability
@ -156,28 +176,67 @@ section at the end of this file).
* counts SOF packets. This feature requires that the hardware interrupt is
* connected to D- instead of D+.
*/
/* #ifdef __ASSEMBLER__
* macro myAssemblerMacro
* in YL, TCNT0
* sts timer0Snapshot, YL
* endm
* #endif
* #define USB_SOF_HOOK myAssemblerMacro
* This macro (if defined) is executed in the assembler module when a
* Start Of Frame condition is detected. It is recommended to define it to
* the name of an assembler macro which is defined here as well so that more
* than one assembler instruction can be used. The macro may use the register
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
* immediately after an SOF pulse may be lost and must be retried by the host.
* What can you do with this hook? Since the SOF signal occurs exactly every
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
* designs running on the internal RC oscillator.
* Please note that Start Of Frame detection works only if D- is wired to the
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
*/
#define USB_CFG_CHECK_DATA_TOGGLING 0
/* define this macro to 1 if you want to filter out duplicate data packets
* sent by the host. Duplicates occur only as a consequence of communication
* errors, when the host does not receive an ACK. Please note that you need to
* implement the filtering yourself in usbFunctionWriteOut() and
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
* for each control- and out-endpoint to check for duplicate packets.
*/
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
*/
#define USB_USE_FAST_CRC 0
/* The assembler module has two implementations for the CRC algorithm. One is
* faster, the other is smaller. This CRC routine is only used for transmitted
* messages where timing is not critical. The faster routine needs 31 cycles
* per byte while the smaller one needs 61 to 69 cycles. The faster routine
* may be worth the 32 bytes bigger code size if you transmit lots of data and
* run the AVR close to its limit.
*/
/* -------------------------- Device Description --------------------------- */
#define USB_CFG_VENDOR_ID 0xc0, 0x16
#define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
/* USB vendor ID for the device, low byte first. If you have registered your
* own Vendor ID, define it here. Otherwise you use one of obdev's free shared
* VID/PID pairs. Be sure to read USBID-License.txt for rules!
* + This template uses obdev's shared VID/PID pair: 0x16c0/0x5dc.
* + Use this VID/PID pair ONLY if you understand the implications!
* own Vendor ID, define it here. Otherwise you may use one of obdev's free
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
* *** IMPORTANT NOTE ***
* This template uses obdev's shared VID/PID pair for Vendor Class devices
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
* the implications!
*/
#define USB_CFG_DEVICE_ID 0xdc, 0x05
#define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x05dc = 1500 */
/* This is the ID of the product, low byte first. It is interpreted in the
* scope of the vendor ID. If you have registered your own VID with usb.org
* or if you have licensed a PID from somebody else, define it here. Otherwise
* you use obdev's free shared VID/PID pair. Be sure to read the rules in
* USBID-License.txt!
* + This template uses obdev's shared VID/PID pair: 0x16c0/0x5dc.
* + Use this VID/PID pair ONLY if you understand the implications!
* you may use one of obdev's free shared VID/PID pairs. See the file
* USB-IDs-for-free.txt for details!
* *** IMPORTANT NOTE ***
* This template uses obdev's shared VID/PID pair for Vendor Class devices
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
* the implications!
*/
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
/* Version number of the device: Minor number first, then major number.
@ -189,14 +248,14 @@ section at the end of this file).
* are interpreted as Unicode (UTF-16) entities.
* If you don't want a vendor name string, undefine these macros.
* ALWAYS define a vendor name containing your Internet domain name if you use
* obdev's free shared VID/PID pair. See the file USBID-License.txt for
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
* details.
*/
#define USB_CFG_DEVICE_NAME 'T', 'e', 'm', 'p', 'l', 'a', 't', 'e'
#define USB_CFG_DEVICE_NAME_LEN 8
/* Same as above for the device name. If you don't want a device name, undefine
* the macros. See the file USBID-License.txt before you assign a name if you
* use a shared VID/PID.
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
* you use a shared VID/PID.
*/
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
@ -243,7 +302,9 @@ section at the end of this file).
* no properties are defined or if they are 0, the default descriptor is used.
* Possible properties are:
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
* at runtime via usbFunctionDescriptor().
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
* you want RAM pointers.
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
* in static memory is in RAM, not in flash memory.
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
@ -275,6 +336,12 @@ section at the end of this file).
* USB_CFG_DESCR_PROPS_HID_REPORT
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
*
* Note about string descriptors: String descriptors are not just strings, they
* are Unicode strings prefixed with a 2 byte header. Example:
* int serialNumberDescriptor[] = {
* USB_STRING_DESCRIPTOR_HEADER(6),
* 'S', 'e', 'r', 'i', 'a', 'l'
* };
*/
#define USB_CFG_DESCR_PROPS_DEVICE 0
@ -288,6 +355,15 @@ section at the end of this file).
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
#define usbMsgPtr_t unsigned short
/* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We define it to
* a scalar type here because gcc generates slightly shorter code for scalar
* arithmetics than for pointer arithmetics. Remove this define for backward
* type compatibility or define it to an 8 bit type if you use data in RAM only
* and all RAM is below 256 bytes (tiny memory model in IAR CC).
*/
/* ----------------------- Optional MCU Description ------------------------ */
/* The following configurations have working defaults in usbdrv.h. You
@ -303,6 +379,6 @@ section at the end of this file).
/* #define USB_INTR_ENABLE_BIT INT0 */
/* #define USB_INTR_PENDING GIFR */
/* #define USB_INTR_PENDING_BIT INTF0 */
/* #define USB_INTR_VECTOR SIG_INTERRUPT0 */
/* #define USB_INTR_VECTOR INT0_vect */
#endif /* __usbconfig_h_included__ */

View File

@ -1,18 +1,12 @@
/* Name: usbdrv.c
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.c 591 2008-05-03 20:21:19Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
#include "iarcompat.h"
#ifndef __IAR_SYSTEMS_ICC__
# include <avr/io.h>
# include <avr/pgmspace.h>
#endif
#include "usbdrv.h"
#include "oddebug.h"
@ -38,15 +32,18 @@ uchar usbTxBuf[USB_BUFSIZE];/* data to transmit with next IN, free if usbT
#if USB_COUNT_SOF
volatile uchar usbSofCount; /* incremented by assembler module every SOF */
#endif
#if USB_CFG_HAVE_INTRIN_ENDPOINT
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
usbTxStatus_t usbTxStatus1;
# if USB_CFG_HAVE_INTRIN_ENDPOINT3
usbTxStatus_t usbTxStatus3;
# endif
#endif
#if USB_CFG_CHECK_DATA_TOGGLING
uchar usbCurrentDataToken;/* when we check data toggling to ignore duplicate packets */
#endif
/* USB status registers / not shared with asm code */
uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
usbMsgPtr_t usbMsgPtr; /* data to transmit next -- ROM or RAM address */
static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */
static uchar usbMsgFlags; /* flag values see below */
@ -56,7 +53,7 @@ static uchar usbMsgFlags; /* flag values see below */
/*
optimizing hints:
- do not post/pre inc/dec integer values in operations
- assign value of PRG_RDB() to register variables and don't use side effects in arg
- assign value of USB_READ_FLASH() to register variables and don't use side effects in arg
- use narrow scope for variables which should be in X/Y/Z register
- assign char sized expressions to variables to force 8 bit arithmetics
*/
@ -68,7 +65,7 @@ optimizing hints:
#if USB_CFG_DESCR_PROPS_STRING_0 == 0
#undef USB_CFG_DESCR_PROPS_STRING_0
#define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0)
PROGMEM char usbDescriptorString0[] = { /* language descriptor */
PROGMEM const char usbDescriptorString0[] = { /* language descriptor */
4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */
3, /* descriptor type */
0x09, 0x04, /* language index (0x0409 = US-English) */
@ -78,7 +75,7 @@ PROGMEM char usbDescriptorString0[] = { /* language descriptor */
#if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN
#undef USB_CFG_DESCR_PROPS_STRING_VENDOR
#define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor)
PROGMEM int usbDescriptorStringVendor[] = {
PROGMEM const int usbDescriptorStringVendor[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN),
USB_CFG_VENDOR_NAME
};
@ -87,7 +84,7 @@ PROGMEM int usbDescriptorStringVendor[] = {
#if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN
#undef USB_CFG_DESCR_PROPS_STRING_PRODUCT
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT sizeof(usbDescriptorStringDevice)
PROGMEM int usbDescriptorStringDevice[] = {
PROGMEM const int usbDescriptorStringDevice[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN),
USB_CFG_DEVICE_NAME
};
@ -96,7 +93,7 @@ PROGMEM int usbDescriptorStringDevice[] = {
#if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN
#undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber)
PROGMEM int usbDescriptorStringSerialNumber[] = {
PROGMEM const int usbDescriptorStringSerialNumber[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
USB_CFG_SERIAL_NUMBER
};
@ -109,7 +106,7 @@ PROGMEM int usbDescriptorStringSerialNumber[] = {
#if USB_CFG_DESCR_PROPS_DEVICE == 0
#undef USB_CFG_DESCR_PROPS_DEVICE
#define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice)
PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
PROGMEM const char usbDescriptorDevice[] = { /* USB device descriptor */
18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
USBDESCR_DEVICE, /* descriptor type */
0x10, 0x01, /* USB version supported */
@ -140,7 +137,7 @@ PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
#undef USB_CFG_DESCR_PROPS_CONFIGURATION
#define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration)
PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
PROGMEM const char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
USBDESCR_CONFIG, /* descriptor type */
18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 +
@ -150,9 +147,9 @@ PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor
1, /* index of this configuration */
0, /* configuration name string index */
#if USB_CFG_IS_SELF_POWERED
USBATTR_SELFPOWER, /* attributes */
(1 << 7) | USBATTR_SELFPOWER, /* attributes */
#else
(char)USBATTR_BUSPOWER, /* attributes */
(1 << 7), /* attributes */
#endif
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
/* interface descriptor follows inline: */
@ -185,7 +182,7 @@ PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
7, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
(char)0x83, /* IN endpoint number 1 */
(char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
0x03, /* attrib: Interrupt endpoint */
8, 0, /* maximum packet size */
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
@ -195,18 +192,9 @@ PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor
/* ------------------------------------------------------------------------- */
/* We don't use prog_int or prog_int16_t for compatibility with various libc
* versions. Here's an other compatibility hack:
*/
#ifndef PRG_RDB
#define PRG_RDB(addr) pgm_read_byte(addr)
#endif
/* ------------------------------------------------------------------------- */
static inline void usbResetDataToggling(void)
{
#if USB_CFG_HAVE_INTRIN_ENDPOINT
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
USB_SET_DATATOKEN1(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
# if USB_CFG_HAVE_INTRIN_ENDPOINT3
USB_SET_DATATOKEN3(USB_INITIAL_DATATOKEN); /* reset data toggling for interrupt endpoint */
@ -226,6 +214,7 @@ static inline void usbResetStall(void)
/* ------------------------------------------------------------------------- */
#if !USB_CFG_SUPPRESS_INTR_CODE
#if USB_CFG_HAVE_INTRIN_ENDPOINT
static void usbGenericSetInterrupt(uchar *data, uchar len, usbTxStatus_t *txStatus)
{
@ -263,6 +252,7 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
usbGenericSetInterrupt(data, len, &usbTxStatus3);
}
#endif
#endif /* USB_CFG_SUPPRESS_INTR_CODE */
/* ------------------ utilities for code following below ------------------- */
@ -309,7 +299,7 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
len = usbFunctionDescriptor(rq); \
}else{ \
len = USB_PROP_LENGTH(cfgProp); \
usbMsgPtr = (uchar *)(staticName); \
usbMsgPtr = (usbMsgPtr_t)(staticName); \
} \
}
@ -369,7 +359,8 @@ uchar flags = USB_FLG_MSGPTR_IS_ROM;
*/
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
{
uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
usbMsgLen_t len = 0;
uchar *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
uchar value = rq->wValue.bytes[0];
#if USB_CFG_IMPLEMENT_HALT
uchar index = rq->wIndex.bytes[0];
@ -408,7 +399,7 @@ uchar index = rq->wIndex.bytes[0];
usbResetStall();
SWITCH_CASE(USBRQ_GET_INTERFACE) /* 10 */
len = 1;
#if USB_CFG_HAVE_INTRIN_ENDPOINT
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
SWITCH_CASE(USBRQ_SET_INTERFACE) /* 11 */
usbResetDataToggling();
usbResetStall();
@ -416,7 +407,7 @@ uchar index = rq->wIndex.bytes[0];
SWITCH_DEFAULT /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */
/* Should we add an optional hook here? */
SWITCH_END
usbMsgPtr = dataPtr;
usbMsgPtr = (usbMsgPtr_t)dataPtr;
skipMsgPtrAssignment:
return len;
}
@ -436,7 +427,7 @@ usbRequest_t *rq = (void *)data;
* 0xe1 11100001 (USBPID_OUT: data phase of setup transfer)
* 0...0x0f for OUT on endpoint X
*/
DBG2(0x10 + (usbRxToken & 0xf), data, len); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
DBG2(0x10 + (usbRxToken & 0xf), data, len + 2); /* SETUP=1d, SETUP-DATA=11, OUTx=1x */
USB_RX_USER_HOOK(data, len)
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
if(usbRxToken < 0x10){ /* OUT to endpoint != 0: endpoint number in usbRxToken */
@ -459,9 +450,13 @@ usbRequest_t *rq = (void *)data;
}
#if USB_CFG_IMPLEMENT_FN_READ || USB_CFG_IMPLEMENT_FN_WRITE
if(replyLen == USB_NO_MSG){ /* use user-supplied read/write function */
/* do some conditioning on replyLen */
/* do some conditioning on replyLen, but on IN transfers only */
if((rq->bmRequestType & USBRQ_DIR_MASK) != USBRQ_DIR_HOST_TO_DEVICE){
replyLen = rq->wLength.bytes[0]; /* IN transfers only */
if(sizeof(replyLen) < sizeof(rq->wLength.word)){ /* help compiler with optimizing */
replyLen = rq->wLength.bytes[0];
}else{
replyLen = rq->wLength.word;
}
}
usbMsgFlags = USB_FLG_USE_USER_RW;
}else /* The 'else' prevents that we limit a replyLen of USB_NO_MSG to the maximum transfer len. */
@ -502,16 +497,18 @@ static uchar usbDeviceRead(uchar *data, uchar len)
}else
#endif
{
uchar i = len, *r = usbMsgPtr;
uchar i = len;
usbMsgPtr_t r = usbMsgPtr;
if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
do{
uchar c = PRG_RDB(r); /* assign to char size variable to enforce byte ops */
uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */
*data++ = c;
r++;
}while(--i);
}else{ /* RAM data */
do{
*data++ = *r++;
*data++ = *((uchar *)r);
r++;
}while(--i);
}
usbMsgPtr = r;
@ -561,6 +558,8 @@ uchar isReset = !notResetState;
USB_RESET_HOOK(isReset);
wasReset = isReset;
}
#else
notResetState = notResetState; // avoid compiler warning
#endif
}
@ -592,17 +591,17 @@ uchar i;
usbBuildTxBlock();
}
}
for(i = 10; i > 0; i--){
for(i = 20; i > 0; i--){
uchar usbLineStatus = USBIN & USBMASK;
if(usbLineStatus != 0) /* SE0 has ended */
break;
goto isNotReset;
}
if(i == 0){ /* RESET condition, called multiple times during reset */
/* RESET condition, called multiple times during reset */
usbNewDeviceAddr = 0;
usbDeviceAddr = 0;
usbResetStall();
DBG1(0xff, 0, 0);
}
isNotReset:
usbHandleResetHook(i);
}
@ -618,7 +617,7 @@ USB_PUBLIC void usbInit(void)
#endif
USB_INTR_ENABLE |= (1 << USB_INTR_ENABLE_BIT);
usbResetDataToggling();
#if USB_CFG_HAVE_INTRIN_ENDPOINT
#if USB_CFG_HAVE_INTRIN_ENDPOINT && !USB_CFG_SUPPRESS_INTR_CODE
usbTxLen1 = USBPID_NAK;
#if USB_CFG_HAVE_INTRIN_ENDPOINT3
usbTxLen3 = USBPID_NAK;

View File

@ -1,17 +1,16 @@
/* Name: usbdrv.h
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.h 607 2008-05-13 15:57:28Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
#ifndef __usbdrv_h_included__
#define __usbdrv_h_included__
#include "usbconfig.h"
#include "iarcompat.h"
#include "usbportability.h"
/*
Hardware Prerequisites:
@ -34,8 +33,8 @@ usbDeviceConnect() and usbDeviceDisconnect() further down in this file.
Please adapt the values in usbconfig.h according to your hardware!
The device MUST be clocked at exactly 12 MHz, 15 MHz or 16 MHz
or at 16.5 MHz +/- 1%. See usbconfig-prototype.h for details.
The device MUST be clocked at exactly 12 MHz, 15 MHz, 16 MHz or 20 MHz
or at 12.8 MHz resp. 16.5 MHz +/- 1%. See usbconfig-prototype.h for details.
Limitations:
@ -105,9 +104,9 @@ interrupt routine.
Interrupt latency:
The application must ensure that the USB interrupt is not disabled for more
than 25 cycles (this is for 12 MHz, faster clocks allow longer latency).
This implies that all interrupt routines must either be declared as "INTERRUPT"
instead of "SIGNAL" (see "avr/signal.h") or that they are written in assembler
with "sei" as the first instruction.
This implies that all interrupt routines must either have the "ISR_NOBLOCK"
attribute set (see "avr/interrupt.h") or be written in assembler with "sei"
as the first instruction.
Maximum interrupt duration / CPU cycle consumption:
The driver handles all USB communication during the interrupt service
@ -122,7 +121,7 @@ USB messages, even if they address another (low-speed) device on the same bus.
/* --------------------------- Module Interface ---------------------------- */
/* ------------------------------------------------------------------------- */
#define USBDRV_VERSION 20080513
#define USBDRV_VERSION 20121206
/* This define uniquely identifies a driver version. It is a decimal number
* constructed from the driver's release date in the form YYYYMMDD. If the
* driver's behavior or interface changes, you can use this constant to
@ -163,11 +162,24 @@ USB messages, even if they address another (low-speed) device on the same bus.
*/
#define USB_NO_MSG ((usbMsgLen_t)-1) /* constant meaning "no message" */
#ifndef usbMsgPtr_t
#define usbMsgPtr_t uchar *
#endif
/* Making usbMsgPtr_t a define allows the user of this library to define it to
* an 8 bit type on tiny devices. This reduces code size, especially if the
* compiler supports a tiny memory model.
* The type can be a pointer or scalar type, casts are made where necessary.
* Although it's paradoxical, Gcc 4 generates slightly better code for scalar
* types than for pointers.
*/
struct usbRequest; /* forward declaration */
USB_PUBLIC void usbInit(void);
/* This function must be called before interrupts are enabled and the main
* loop is entered.
* loop is entered. We exepct that the PORT and DDR bits for D+ and D- have
* not been changed from their default status (which is 0). If you have changed
* them, set both back to 0 (configure them as input with no internal pull-up).
*/
USB_PUBLIC void usbPoll(void);
/* This function must be called at regular intervals from the main loop.
@ -176,7 +188,7 @@ USB_PUBLIC void usbPoll(void);
* Please note that debug outputs through the UART take ~ 0.5ms per byte
* at 19200 bps.
*/
extern uchar *usbMsgPtr;
extern usbMsgPtr_t usbMsgPtr;
/* This variable may be used to pass transmit data to the driver from the
* implementation of usbFunctionWrite(). It is also used internally by the
* driver for standard control requests.
@ -273,6 +285,8 @@ USB_PUBLIC uchar usbFunctionRead(uchar *data, uchar len);
* to 1 in usbconfig.h and return 0xff in usbFunctionSetup()..
*/
#endif /* USB_CFG_IMPLEMENT_FN_READ */
extern uchar usbRxToken; /* may be used in usbFunctionWriteOut() below */
#if USB_CFG_IMPLEMENT_FN_WRITEOUT
USB_PUBLIC void usbFunctionWriteOut(uchar *data, uchar len);
/* This function is called by the driver when data is received on an interrupt-
@ -339,6 +353,12 @@ extern volatile uchar usbSofCount;
* the macro USB_COUNT_SOF is defined to a value != 0.
*/
#endif
#if USB_CFG_CHECK_DATA_TOGGLING
extern uchar usbCurrentDataToken;
/* This variable can be checked in usbFunctionWrite() and usbFunctionWriteOut()
* to ignore duplicate packets.
*/
#endif
#define USB_STRING_DESCRIPTOR_HEADER(stringLength) ((2*(stringLength)+2) | (3<<8))
/* This macro builds a descriptor header for a string descriptor given the
@ -380,11 +400,13 @@ extern volatile schar usbRxLen;
* about the various methods to define USB descriptors. If you do nothing,
* the default descriptors will be used.
*/
#define USB_PROP_IS_DYNAMIC (1 << 14)
#define USB_PROP_IS_DYNAMIC (1u << 14)
/* If this property is set for a descriptor, usbFunctionDescriptor() will be
* used to obtain the particular descriptor.
* used to obtain the particular descriptor. Data directly returned via
* usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to
* return RAM data.
*/
#define USB_PROP_IS_RAM (1 << 15)
#define USB_PROP_IS_RAM (1u << 15)
/* If this property is set for a descriptor, the data is read from RAM
* memory instead of Flash. The property is used for all methods to provide
* external descriptors.
@ -438,43 +460,43 @@ extern volatile schar usbRxLen;
#ifndef __ASSEMBLER__
extern
#if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorDevice[];
extern
#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorConfiguration[];
extern
#if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorHidReport[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorString0[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
int usbDescriptorStringVendor[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
int usbDescriptorStringDevice[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
int usbDescriptorStringSerialNumber[];
@ -501,22 +523,22 @@ int usbDescriptorStringSerialNumber[];
#if !defined __ASSEMBLER__ && (!defined USB_CFG_VENDOR_ID || !defined USB_CFG_DEVICE_ID)
#warning "You should define USB_CFG_VENDOR_ID and USB_CFG_DEVICE_ID in usbconfig.h"
/* If the user has not defined IDs, we default to obdev's free IDs.
* See USBID-License.txt for details.
* See USB-IDs-for-free.txt for details.
*/
#endif
/* make sure we have a VID and PID defined, byte order is lowbyte, highbyte */
#ifndef USB_CFG_VENDOR_ID
# define USB_CFG_VENDOR_ID 0xc0, 0x16 /* 5824 in dec, stands for VOTI */
# define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
#endif
#ifndef USB_CFG_DEVICE_ID
# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
# define USB_CFG_DEVICE_ID 0xdf, 0x05 /* 1503 in dec, shared PID for HIDs */
# define USB_CFG_DEVICE_ID 0xdf, 0x05 /* = 0x5df = 1503, shared PID for HIDs */
# elif USB_CFG_INTERFACE_CLASS == 2
# define USB_CFG_DEVICE_ID 0xe1, 0x05 /* 1505 in dec, shared PID for CDC Modems */
# define USB_CFG_DEVICE_ID 0xe1, 0x05 /* = 0x5e1 = 1505, shared PID for CDC Modems */
# else
# define USB_CFG_DEVICE_ID 0xdc, 0x05 /* 1500 in dec, obdev's free PID */
# define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x5dc = 1500, obdev's free PID */
# endif
#endif
@ -546,6 +568,10 @@ int usbDescriptorStringSerialNumber[];
#define USB_CFG_EP3_NUMBER 3
#endif
#ifndef USB_CFG_HAVE_INTRIN_ENDPOINT3
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
#endif
#define USB_BUFSIZE 11 /* PID, 8 bytes data, 2 bytes CRC */
/* ----- Try to find registers and bits responsible for ext interrupt 0 ----- */
@ -558,8 +584,15 @@ int usbDescriptorStringSerialNumber[];
# endif
#endif
#ifndef USB_INTR_CFG_SET /* allow user to override our default */
# if defined(USB_COUNT_SOF) || defined(USB_SOF_HOOK)
# define USB_INTR_CFG_SET (1 << ISC01) /* cfg for falling edge */
/* If any SOF logic is used, the interrupt must be wired to D- where
* we better trigger on falling edge
*/
# else
# define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) /* cfg for rising edge */
# endif
#endif
#ifndef USB_INTR_CFG_CLR /* allow user to override our default */
# define USB_INTR_CFG_CLR 0 /* no bits to clear */
#endif
@ -695,7 +728,8 @@ typedef struct usbRequest{
#define USBDESCR_HID_REPORT 0x22
#define USBDESCR_HID_PHYS 0x23
#define USBATTR_BUSPOWER 0x80
//#define USBATTR_BUSPOWER 0x80 // USB 1.1 does not define this value any more
#define USBATTR_BUSPOWER 0
#define USBATTR_SELFPOWER 0x40
#define USBATTR_REMOTEWAKE 0x20

View File

@ -1,11 +1,10 @@
/* Name: usbdrvasm.S
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-06-13
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id$
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/*
@ -15,15 +14,8 @@ general code (preprocessor acrobatics and CRC computation) and then includes
the file appropriate for the given clock rate.
*/
#include "iarcompat.h"
#ifndef __IAR_SYSTEMS_ASM__
/* configs for io.h */
# define __SFR_OFFSET 0
# define _VECTOR(N) __vector_ ## N /* io.h does not define this for asm */
# include <avr/io.h> /* for CPU I/O register definitions and vectors */
# define macro .macro /* GNU Assembler macro definition */
# define endm .endm /* End of GNU Assembler macro definition */
#endif /* __IAR_SYSTEMS_ASM__ */
#define __SFR_OFFSET 0 /* used by avr-libc's register definitions */
#include "usbportability.h"
#include "usbdrv.h" /* for common defs */
/* register names */
@ -33,24 +25,14 @@ the file appropriate for the given clock rate.
#define cnt r19
#define x3 r20
#define x4 r21
#define bitcnt r22
#define x5 r22
#define bitcnt x5
#define phase x4
#define leap x4
/* Some assembler dependent definitions and declarations: */
#ifdef __IAR_SYSTEMS_ASM__
# define nop2 rjmp $+2 /* jump to next instruction */
# define XL r26
# define XH r27
# define YL r28
# define YH r29
# define ZL r30
# define ZH r31
# define lo8(x) LOW(x)
# define hi8(x) (((x)>>8) & 0xff) /* not HIGH to allow XLINK to make a proper range check */
extern usbRxBuf, usbDeviceAddr, usbNewDeviceAddr, usbInputBufOffset
extern usbCurrentTok, usbRxLen, usbRxToken, usbTxLen
extern usbTxBuf, usbTxStatus1, usbTxStatus3
@ -73,10 +55,12 @@ the file appropriate for the given clock rate.
#else /* __IAR_SYSTEMS_ASM__ */
# define nop2 rjmp .+0 /* jump to next instruction */
# ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
# define USB_INTR_VECTOR SIG_INTERRUPT0
# ifdef INT0_vect
# define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector
# else
# define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector
# endif
# endif
.text
.global USB_INTR_VECTOR
@ -158,16 +142,93 @@ RTMODEL "__rt_version", "3"
#endif
; extern unsigned usbCrc16(unsigned char *data, unsigned char len);
; data: r24/25
; len: r22
#if USB_USE_FAST_CRC
; This implementation is faster, but has bigger code size
; Thanks to Slawomir Fras (BoskiDialer) for this code!
; It implements the following C pseudo-code:
; unsigned table(unsigned char x)
; {
; unsigned value;
;
; value = (unsigned)x << 6;
; value ^= (unsigned)x << 7;
; if(parity(x))
; value ^= 0xc001;
; return value;
; }
; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
; {
; unsigned crc = 0xffff;
;
; while(argLen--)
; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
; return ~crc;
; }
; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
; argPtr r24+25 / r16+r17
; argLen r22 / r18
; temp variables:
; r18: data byte
; r19: bit counter
; r20/21: polynomial
; r23: scratch
; r24/25: crc-sum
; r26/27=X: ptr
; byte r18 / r22
; scratch r23
; resCrc r24+r25 / r16+r17
; ptr X / Z
usbCrc16:
mov ptrL, argPtrL
mov ptrH, argPtrH
ldi resCrcL, 0xFF
ldi resCrcH, 0xFF
rjmp usbCrc16LoopTest
usbCrc16ByteLoop:
ld byte, ptr+
eor resCrcL, byte ; resCrcL is now 'x' in table()
mov byte, resCrcL ; compute parity of 'x'
swap byte
eor byte, resCrcL
mov scratch, byte
lsr byte
lsr byte
eor byte, scratch
inc byte
lsr byte
andi byte, 1 ; byte is now parity(x)
mov scratch, resCrcL
mov resCrcL, resCrcH
eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
neg byte
andi byte, 0xc0
mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
clr byte
lsr scratch
ror byte
eor resCrcH, scratch
eor resCrcL, byte
lsr scratch
ror byte
eor resCrcH, scratch
eor resCrcL, byte
usbCrc16LoopTest:
subi argLen, 1
brsh usbCrc16ByteLoop
com resCrcL
com resCrcH
ret
#else /* USB_USE_FAST_CRC */
; This implementation is slower, but has less code size
;
; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
; argPtr r24+25 / r16+r17
; argLen r22 / r18
; temp variables:
; byte r18 / r22
; bitCnt r19
; poly r20+r21
; scratch r23
; resCrc r24+r25 / r16+r17
; ptr X / Z
usbCrc16:
mov ptrL, argPtrL
mov ptrH, argPtrH
@ -175,27 +236,30 @@ usbCrc16:
ldi resCrcH, 0
ldi polyL, lo8(0xa001)
ldi polyH, hi8(0xa001)
com argLen ; argLen = -argLen - 1
crcByteLoop:
subi argLen, -1
brcc crcReady ; modified loop to ensure that carry is set below
com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set
ldi bitCnt, 0 ; loop counter with starnd condition = end condition
rjmp usbCrcLoopEntry
usbCrcByteLoop:
ld byte, ptr+
ldi bitCnt, -8 ; strange loop counter to ensure that carry is set where we need it
eor resCrcL, byte
crcBitLoop:
ror resCrcH ; carry is always set here
usbCrcBitLoop:
ror resCrcH ; carry is always set here (see brcs jumps to here)
ror resCrcL
brcs crcNoXor
brcs usbCrcNoXor
eor resCrcL, polyL
eor resCrcH, polyH
crcNoXor:
subi bitCnt, -1
brcs crcBitLoop
rjmp crcByteLoop
crcReady:
usbCrcNoXor:
subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
brcs usbCrcBitLoop
usbCrcLoopEntry:
subi argLen, -1
brcs usbCrcByteLoop
usbCrcReady:
ret
; Thanks to Reimar Doeffinger for optimizing this CRC routine!
#endif /* USB_USE_FAST_CRC */
; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
usbCrc16Append:
rcall usbCrc16
@ -296,11 +360,24 @@ usbMFTimeout:
;----------------------------------------------------------------------------
#ifndef USB_CFG_CLOCK_KHZ
# define USB_CFG_CLOCK_KHZ 12000
# ifdef F_CPU
# define USB_CFG_CLOCK_KHZ (F_CPU/1000)
# else
# error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!"
# endif
#endif
#if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */
# if USB_CFG_CLOCK_KHZ == 18000
# include "usbdrvasm18-crc.inc"
# else
# error "USB_CFG_CLOCK_KHZ is not one of the supported crc-rates!"
# endif
#else /* USB_CFG_CHECK_CRC */
# if USB_CFG_CLOCK_KHZ == 12000
# include "usbdrvasm12.inc"
# elif USB_CFG_CLOCK_KHZ == 12800
# include "usbdrvasm128.inc"
# elif USB_CFG_CLOCK_KHZ == 15000
# include "usbdrvasm15.inc"
# elif USB_CFG_CLOCK_KHZ == 16000
@ -310,5 +387,6 @@ usbMFTimeout:
# elif USB_CFG_CLOCK_KHZ == 20000
# include "usbdrvasm20.inc"
# else
# error "USB_CFG_CLOCK_KHZ is not one of the supported rates!"
# error "USB_CFG_CLOCK_KHZ is not one of the supported non-crc-rates!"
# endif
#endif /* USB_CFG_CHECK_CRC */

View File

@ -1,11 +1,10 @@
/* Name: usbdrvasm.asm
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2006-03-01
* Tabsize: 4
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id$
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/*

View File

@ -1,11 +1,10 @@
/* Name: usbdrvasm12.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2004-12-29
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm12.inc 483 2008-02-05 15:05:32Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -48,10 +47,13 @@ USB_INTR_VECTOR:
;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ:
sbis USBIN, USBMINUS ;1 [40] wait for D- == 1
rjmp waitForJ ;2
inc YL
sbis USBIN, USBMINUS
brne waitForJ ; just make sure we have ANY timeout
waitForK:
;The following code results in a sampling window of 1/4 bit which meets the spec.
sbis USBIN, USBMINUS
@ -69,6 +71,9 @@ waitForK:
inc YL
sts usbSofCount, YL
#endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError
foundK:
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 4 for center sampling]
@ -263,25 +268,16 @@ endm
; Transmitting data
;----------------------------------------------------------------------------
bitstuff0: ;1 (for branch taken)
eor x1, x4 ;1
ldi x2, 0 ;1
out USBOUT, x1 ;1 <-- out
rjmp didStuff0 ;2 branch back 2 cycles earlier
bitstuff1: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff1 ;2 we know that C is clear, jump back to do OUT and ror 0 into x2
bitstuff2: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff2 ;2 jump back 4 cycles earlier and do out and ror 0 into x2
bitstuff3: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff3 ;2 jump back earlier and ror 0 into x2
bitstuff4: ;1 (for branch taken)
eor x1, x4 ;1
ldi x2, 0 ;1
out USBOUT, x1 ;1 <-- out
rjmp didStuff4 ;2 jump back 2 cycles earlier
txByteLoop:
txBitloop:
stuffN1Delay: ; [03]
ror shift ;[-5] [11] [59]
brcc doExorN1 ;[-4] [60]
subi x4, 1 ;[-3]
brne commonN1 ;[-2]
lsl shift ;[-1] compensate ror after rjmp stuffDelay
nop ;[00] stuffing consists of just waiting 8 cycles
rjmp stuffN1Delay ;[01] after ror, C bit is reliably clear
sendNakAndReti: ;0 [-19] 19 cycles until SOP
ldi x3, USBPID_NAK ;1 [-18]
@ -306,122 +302,91 @@ usbSendX3: ;0 [-16]
;usbSend:
;pointer to data in 'Y'
;number of bytes in 'cnt' -- including sync byte
;uses: x1...x4, shift, cnt, Y
;Numbers in brackets are time since first bit of sync pattern is sent
usbSendAndReti: ;0 [-13] timing: 13 cycles until SOP
in x2, USBDDR ;1 [-12]
ori x2, USBMASK ;1 [-11]
sbi USBOUT, USBMINUS;2 [-9] prepare idle state; D+ and D- must have been 0 (no pullups)
in x1, USBOUT ;1 [-8] port mirror for tx loop
out USBDDR, x2 ;1 [-7] <- acquire bus
; need not init x2 (bitstuff history) because sync starts with 0
push x4 ;2 [-5]
ldi x4, USBMASK ;1 [-4] exor mask
ldi shift, 0x80 ;1 [-3] sync byte is first byte sent
txLoop: ; [62]
sbrs shift, 0 ;1 [-2] [62]
eor x1, x4 ;1 [-1] [63]
out USBOUT, x1 ;1 [0] <-- out bit 0
ror shift ;1 [1]
ror x2 ;1 [2]
didStuff0:
cpi x2, 0xfc ;1 [3]
brsh bitstuff0 ;1 [4]
sbrs shift, 0 ;1 [5]
eor x1, x4 ;1 [6]
ror shift ;1 [7]
didStuff1:
out USBOUT, x1 ;1 [8] <-- out bit 1
ror x2 ;1 [9]
cpi x2, 0xfc ;1 [10]
brsh bitstuff1 ;1 [11]
sbrs shift, 0 ;1 [12]
eor x1, x4 ;1 [13]
ror shift ;1 [14]
didStuff2:
ror x2 ;1 [15]
out USBOUT, x1 ;1 [16] <-- out bit 2
cpi x2, 0xfc ;1 [17]
brsh bitstuff2 ;1 [18]
sbrs shift, 0 ;1 [19]
eor x1, x4 ;1 [20]
ror shift ;1 [21]
didStuff3:
ror x2 ;1 [22]
cpi x2, 0xfc ;1 [23]
out USBOUT, x1 ;1 [24] <-- out bit 3
brsh bitstuff3 ;1 [25]
nop2 ;2 [27]
ld x3, y+ ;2 [29]
sbrs shift, 0 ;1 [30]
eor x1, x4 ;1 [31]
out USBOUT, x1 ;1 [32] <-- out bit 4
ror shift ;1 [33]
ror x2 ;1 [34]
didStuff4:
cpi x2, 0xfc ;1 [35]
brsh bitstuff4 ;1 [36]
sbrs shift, 0 ;1 [37]
eor x1, x4 ;1 [38]
ror shift ;1 [39]
didStuff5:
out USBOUT, x1 ;1 [40] <-- out bit 5
ror x2 ;1 [41]
cpi x2, 0xfc ;1 [42]
brsh bitstuff5 ;1 [43]
sbrs shift, 0 ;1 [44]
eor x1, x4 ;1 [45]
ror shift ;1 [46]
didStuff6:
ror x2 ;1 [47]
out USBOUT, x1 ;1 [48] <-- out bit 6
cpi x2, 0xfc ;1 [49]
brsh bitstuff6 ;1 [50]
sbrs shift, 0 ;1 [51]
eor x1, x4 ;1 [52]
ror shift ;1 [53]
didStuff7:
ror x2 ;1 [54]
cpi x2, 0xfc ;1 [55]
out USBOUT, x1 ;1 [56] <-- out bit 7
brsh bitstuff7 ;1 [57]
mov shift, x3 ;1 [58]
dec cnt ;1 [59]
brne txLoop ;1/2 [60/61]
;uses: x1...x2, x4, shift, cnt, Y [x1 = mirror USBOUT, x2 = USBMASK, x4 = bitstuff cnt]
;Numbers in brackets are time since first bit of sync pattern is sent (start of instruction)
usbSendAndReti:
in x2, USBDDR ;[-12] 12 cycles until SOP
ori x2, USBMASK ;[-11]
sbi USBOUT, USBMINUS ;[-10] prepare idle state; D+ and D- must have been 0 (no pullups)
out USBDDR, x2 ;[-8] <--- acquire bus
in x1, USBOUT ;[-7] port mirror for tx loop
ldi shift, 0x40 ;[-6] sync byte is first byte sent (we enter loop after ror)
ldi x2, USBMASK ;[-5]
push x4 ;[-4]
doExorN1:
eor x1, x2 ;[-2] [06] [62]
ldi x4, 6 ;[-1] [07] [63]
commonN1:
stuffN2Delay:
out USBOUT, x1 ;[00] [08] [64] <--- set bit
ror shift ;[01]
brcc doExorN2 ;[02]
subi x4, 1 ;[03]
brne commonN2 ;[04]
lsl shift ;[05] compensate ror after rjmp stuffDelay
rjmp stuffN2Delay ;[06] after ror, C bit is reliably clear
doExorN2:
eor x1, x2 ;[04] [12]
ldi x4, 6 ;[05] [13]
commonN2:
nop ;[06] [14]
subi cnt, 171 ;[07] [15] trick: (3 * 171) & 0xff = 1
out USBOUT, x1 ;[08] [16] <--- set bit
brcs txBitloop ;[09] [25] [41]
stuff6Delay:
ror shift ;[42] [50]
brcc doExor6 ;[43]
subi x4, 1 ;[44]
brne common6 ;[45]
lsl shift ;[46] compensate ror after rjmp stuffDelay
nop ;[47] stuffing consists of just waiting 8 cycles
rjmp stuff6Delay ;[48] after ror, C bit is reliably clear
doExor6:
eor x1, x2 ;[45] [53]
ldi x4, 6 ;[46]
common6:
stuff7Delay:
ror shift ;[47] [55]
out USBOUT, x1 ;[48] <--- set bit
brcc doExor7 ;[49]
subi x4, 1 ;[50]
brne common7 ;[51]
lsl shift ;[52] compensate ror after rjmp stuffDelay
rjmp stuff7Delay ;[53] after ror, C bit is reliably clear
doExor7:
eor x1, x2 ;[51] [59]
ldi x4, 6 ;[52]
common7:
ld shift, y+ ;[53]
tst cnt ;[55]
out USBOUT, x1 ;[56] <--- set bit
brne txByteLoop ;[57]
;make SE0:
cbr x1, USBMASK ;1 [61] prepare SE0 [spec says EOP may be 15 to 18 cycles]
pop x4 ;2 [63]
;brackets are cycles from start of SE0 now
out USBOUT, x1 ;1 [0] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
cbr x1, USBMASK ;[58] prepare SE0 [spec says EOP may be 15 to 18 cycles]
lds x2, usbNewDeviceAddr;[59]
lsl x2 ;[61] we compare with left shifted address
subi YL, 2 + 20 ;[62] Only assign address on data packets, not ACK/NAK in x3
sbci YH, 0 ;[63]
out USBOUT, x1 ;[00] <-- out SE0 -- from now 2 bits = 16 cycles until bus idle
;2006-03-06: moved transfer of new address to usbDeviceAddr from C-Code to asm:
;set address only after data packet was sent, not after handshake
lds x2, usbNewDeviceAddr;2 [2]
lsl x2; ;1 [3] we compare with left shifted address
subi YL, 20 + 2 ;1 [4] Only assign address on data packets, not ACK/NAK in x3
sbci YH, 0 ;1 [5]
breq skipAddrAssign ;2 [7]
breq skipAddrAssign ;[01]
sts usbDeviceAddr, x2 ; if not skipped: SE0 is one cycle longer
skipAddrAssign:
;end of usbDeviceAddress transfer
ldi x2, 1<<USB_INTR_PENDING_BIT;1 [8] int0 occurred during TX -- clear pending flag
USB_STORE_PENDING(x2) ;1 [9]
ori x1, USBIDLE ;1 [10]
in x2, USBDDR ;1 [11]
cbr x2, USBMASK ;1 [12] set both pins to input
mov x3, x1 ;1 [13]
cbr x3, USBMASK ;1 [14] configure no pullup on both pins
out USBOUT, x1 ;1 [15] <-- out J (idle) -- end of SE0 (EOP signal)
out USBDDR, x2 ;1 [16] <-- release bus now
out USBOUT, x3 ;1 [17] <-- ensure no pull-up resistors are active
ldi x2, 1<<USB_INTR_PENDING_BIT;[03] int0 occurred during TX -- clear pending flag
USB_STORE_PENDING(x2) ;[04]
ori x1, USBIDLE ;[05]
in x2, USBDDR ;[06]
cbr x2, USBMASK ;[07] set both pins to input
mov x3, x1 ;[08]
cbr x3, USBMASK ;[09] configure no pullup on both pins
pop x4 ;[10]
nop2 ;[12]
nop2 ;[14]
out USBOUT, x1 ;[16] <-- out J (idle) -- end of SE0 (EOP signal)
out USBDDR, x2 ;[17] <-- release bus now
out USBOUT, x3 ;[18] <-- ensure no pull-up resistors are active
rjmp doReturn
bitstuff5: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff5 ;2 same trick as in bitstuff1...
bitstuff6: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff6 ;2 same trick as above...
bitstuff7: ;1 (for branch taken)
eor x1, x4 ;1
rjmp didStuff7 ;2 same trick as above...

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm128.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -31,8 +30,9 @@ limitations:
They typical range is 14.5 MHz and most AVRs can actually reach this rate.
(2) Writing EEPROM and Flash may be unreliable (short data lifetime) since
the write procedure is timed from the RC oscillator.
(3) End Of Packet detection is between bit 0 and bit 1 where the EOP condition
may not be reliable when a hub is used. It should be in bit 1.
(3) End Of Packet detection (SE0) should be in bit 1, bit it is only checked
if bits 0 and 1 both read as 0 on D- and D+ read as 0 in the middle. This may
cause problems with old hubs which delay SE0 by up to one cycle.
(4) Code size is much larger than that of the other modules.
Since almost all of this code is timing critical, don't change unless you
@ -217,8 +217,10 @@ unstuff0s:
ifioclr USBIN, USBMINUS ;[00]
ifioset USBIN, USBPLUS ;[01]
rjmp bit0IsClr ;[02] executed if first expr false or second true
jumpToSe0AndStore:
rjmp se0AndStore ;[03] executed only if both bits 0
se0AndStore: ; executed only if both bits 0
st y+, x1 ;[15/17] cycles after start of byte
rjmp se0 ;[17/19]
bit0IsClr:
ifrset phase, USBMINUS ;[04] check phase only if D- changed
lpm ;[05]
@ -228,7 +230,7 @@ bit1AfterClr:
andi phase, USBMASK ;[08]
ifioset USBIN, USBMINUS ;[09] <--- sample 1
rjmp bit1IsSet ;[10]
breq jumpToSe0AndStore ;[11]
breq se0AndStore ;[11] if D- was 0 in bits 0 AND 1 and D+ was 0 in between, we have SE0
andi shift, ~(7 << 1) ;[12]
in phase, USBIN ;[13] <- phase
breq unstuff1c ;[14]
@ -355,10 +357,6 @@ unstuff7c:
nop ;[59]
rjmp bit7IsSet ;[60]
se0AndStore:
st y+, x1 ;[15/17] cycles after start of byte
rjmp se0 ;[17/19]
bit7IsClr:
ifrset phase, USBMINUS ;[62] check phase only if D- changed
lpm ;[63]
@ -391,25 +389,24 @@ bit0IsSet:
in phase, USBIN ;[06] <- phase (one cycle too late)
ori shift, 1 << 0 ;[07]
bit1AfterSet:
andi phase, USBMASK ;[08]
andi shift, ~(7 << 1) ;[08] compensated by "ori shift, 1<<1" if bit1IsClr
ifioclr USBIN, USBMINUS ;[09] <--- sample 1
rjmp bit1IsClr ;[10]
andi shift, ~(7 << 1) ;[11]
breq unstuff1s ;[12]
in phase, USBIN ;[13] <- phase
nop ;[14]
breq unstuff1s ;[11]
nop2 ;[12] do not check for SE0 if bit 0 was 1
in phase, USBIN ;[14] <- phase (one cycle too late)
rjmp bit2AfterSet ;[15]
unstuff1s:
in phase, USBIN ;[14] <- phase (one cycle too late)
andi fix, ~(1 << 1) ;[15]
nop2 ;[08]
in phase, USBIN ;[13] <- phase
andi fix, ~(1 << 1) ;[14]
lpm ;[07]
nop2 ;[10]
bit1IsClr:
ifrset phase, USBMINUS ;[12] check phase only if D- changed
lpm ;[13]
in phase, USBIN ;[14] <- phase (one cycle too late)
breq se0AndStore ;[15] if we come from unstuff1s, Z bit is never set
ori shift, 1 << 1 ;[16]
ori shift, 1 << 1 ;[15]
nop ;[16]
bit2AfterClr:
ifioset USBIN, USBMINUS ;[17] <--- sample 2
rjmp bit2IsSet ;[18]

View File

@ -1,11 +1,10 @@
/* Name: usbdrvasm15.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: contributed by V. Bosch
* Creation Date: 2007-08-06
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm15.inc 607 2008-05-13 15:57:28Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -43,11 +42,13 @@ USB_INTR_VECTOR:
;
; sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
; sync up with J to K edge during sync pattern -- use fastest possible loops
; first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;-------------------------------------------------------------------------------
waitForJ: ;-
sbis USBIN, USBMINUS ;1 <-- sample: wait for D- == 1
rjmp waitForJ ;2
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ:
inc YL
sbis USBIN, USBMINUS
brne waitForJ ; just make sure we have ANY timeout
;-------------------------------------------------------------------------------
; The following code results in a sampling window of < 1/4 bit
; which meets the spec.
@ -70,6 +71,9 @@ waitForK: ;-
inc YL
sts usbSofCount, YL
#endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError
;------------------------------------------------------------------------------
; {3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for

View File

@ -1,11 +1,10 @@
/* Name: usbdrvasm16.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-06-15
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm16.inc 607 2008-05-13 15:57:28Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -41,10 +40,13 @@ USB_INTR_VECTOR:
;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ:
sbis USBIN, USBMINUS ;[-18] wait for D- == 1
rjmp waitForJ
inc YL
sbis USBIN, USBMINUS
brne waitForJ ; just make sure we have ANY timeout
waitForK:
;The following code results in a sampling window of < 1/4 bit which meets the spec.
sbis USBIN, USBMINUS ;[-15]
@ -64,6 +66,9 @@ waitForK:
inc YL
sts usbSofCount, YL
#endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError
foundK: ;[-12]
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]
@ -111,12 +116,15 @@ haveTwoBitsK:
; Receiver loop (numbers in brackets are cycles within byte after instr)
;----------------------------------------------------------------------------
; duration of unstuffing code should be 10.66666667 cycles. We adjust "leap"
; accordingly to approximate this value in the long run.
unstuff6:
andi x2, USBMASK ;[03]
ori x3, 1<<6 ;[04] will not be shifted any more
andi shift, ~0x80;[05]
mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6
subi leap, 3 ;[07] since this is a short (10 cycle) bit, enforce leap bit
subi leap, -1 ;[07] total duration = 11 bits -> subtract 1/3
rjmp didUnstuff6 ;[08]
unstuff7:
@ -124,7 +132,7 @@ unstuff7:
in x2, USBIN ;[00] [10] re-sample bit 7
andi x2, USBMASK ;[01]
andi shift, ~0x80;[02]
subi leap, 3 ;[03] since this is a short (10 cycle) bit, enforce leap bit
subi leap, 2 ;[03] total duration = 10 bits -> add 1/3
rjmp didUnstuff7 ;[04]
unstuffEven:
@ -133,8 +141,8 @@ unstuffEven:
andi shift, ~0x80;[01]
andi x1, USBMASK ;[02]
breq se0 ;[03]
subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
nop ;[05]
subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3
nop2 ;[05]
rjmp didUnstuffE ;[06]
unstuffOdd:
@ -143,8 +151,8 @@ unstuffOdd:
andi shift, ~0x80;[01]
andi x2, USBMASK ;[02]
breq se0 ;[03]
subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
nop ;[05]
subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3
nop2 ;[05]
rjmp didUnstuffO ;[06]
rxByteLoop:

View File

@ -1,11 +1,10 @@
/* Name: usbdrvasm165.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2007-04-22
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm165.inc 607 2008-05-13 15:57:28Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -46,10 +45,13 @@ USB_INTR_VECTOR:
;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ:
sbis USBIN, USBMINUS ;[-18] wait for D- == 1
rjmp waitForJ
inc YL
sbis USBIN, USBMINUS
brne waitForJ ; just make sure we have ANY timeout
waitForK:
;The following code results in a sampling window of < 1/4 bit which meets the spec.
sbis USBIN, USBMINUS ;[-15]
@ -69,6 +71,9 @@ waitForK:
inc YL
sts usbSofCount, YL
#endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError
foundK: ;[-12]
;{3, 5} after falling D- edge, average delay: 4 cycles [we want 5 for center sampling]

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm18-crc.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@ -1,12 +1,11 @@
/* Name: usbdrvasm20.inc
* Project: AVR USB driver
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Jeroen Benschop
* Based on usbdrvasm16.inc from Christian Starkjohann
* Creation Date: 2008-03-05
* Tabsize: 4
* Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt) or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm20.inc 607 2008-05-13 15:57:28Z cs $
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -57,10 +56,13 @@ USB_INTR_VECTOR:
;----------------------------------------------------------------------------
;sync byte (D-) pattern LSb to MSb: 01010100 [1 = idle = J, 0 = K]
;sync up with J to K edge during sync pattern -- use fastest possible loops
;first part has no timeout because it waits for IDLE or SE1 (== disconnected)
;The first part waits at most 1 bit long since we must be in sync pattern.
;YL is guarenteed to be < 0x80 because I flag is clear. When we jump to
;waitForJ, ensure that this prerequisite is met.
waitForJ:
sbis USBIN, USBMINUS ;[-21] wait for D- == 1
rjmp waitForJ
inc YL
sbis USBIN, USBMINUS
brne waitForJ ; just make sure we have ANY timeout
waitForK:
;The following code results in a sampling window of < 1/4 bit which meets the spec.
sbis USBIN, USBMINUS ;[-19]
@ -86,6 +88,9 @@ waitForK:
inc YL
sts usbSofCount, YL
#endif /* USB_COUNT_SOF */
#ifdef USB_SOF_HOOK
USB_SOF_HOOK
#endif
rjmp sofError
foundK: ;[-16]
;{3, 5} after falling D- edge, average delay: 4 cycles

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbportability.h 740 2009-04-13 18:23:31Z cs $
*/
/*
@ -125,7 +124,11 @@ static inline void sei(void)
# include <avr/pgmspace.h>
#endif
#if USB_CFG_DRIVER_FLASH_PAGE
# define USB_READ_FLASH(addr) pgm_read_byte_far(((long)USB_CFG_DRIVER_FLASH_PAGE << 16) | (long)(addr))
#else
# define USB_READ_FLASH(addr) pgm_read_byte(addr)
#endif
#define macro .macro
#define endm .endm

View File

@ -23,29 +23,54 @@ F_CPU = 20000000
TARGET = main
AVRDUDE = avrdude -c usbasp -p $(DEVICE)
SIZE = avr-size
BOOT_ROM01 = ../../roms/qd16boot01.smc
BOOT_ROM02 = ../../roms/qd16boot02.smc
CONVERT_RLE = ../../scripts/conv_rle.py
CONVERT_ZIP = ../../scripts/conv_zip.py
BOOT_LOADER = 1
BOOT_COMPRESS = rle
BOOT_ROM01 = ../../roms/qd16boot_ver01.smc
BOOT_ROM02 = ../../roms/qd16boot_ver02.smc
ifeq ($(DEBUG),1)
LDFLAGS =-Wl,-u,vfprintf -lprintf_flt
BOOT_DEBUG = debug
LDFLAGS =-Wl,-u,vfprintf
CFLAGS =-Iusbdrv -I. -DDEBUG_LEVEL=0
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o \
main.o usb_bulk.o uart.o fifo.o sram.o crc.o debug.o \
dump.o timer.o watchdog.o rle.c loader.o info.o shared_memory.o \
system.o pwm.o util.o shell.o irq.o command.o testing.o
main.o usb_bulk.o uart.o fifo.o sram.o debug.o \
dump.o timer.o watchdog.o loader.o info.o shared_memory.o crc.o \
system.o pwm.o util.o shell.o irq.o command.o
else
LDFLAGS =-Wl,-u
BOOT_DEBUG = nodebug
LDFLAGS =
CFLAGS =-Iusbdrv -I. -DDEBUG_LEVEL=0 -DNO_DEBUG -DNO_INFO
OBJECTS = usbdrv/usbdrv.o usbdrv/usbdrvasm.o usbdrv/oddebug.o main.o usb_bulk.o \
sram.o crc.o debug.o dump.o rle.c loader.o \
sram.o crc.o debug.o dump.o loader.o \
system.o util.o info.o shared_memory.o command.o irq.o \
pwm.o
endif
ifeq ($(BOOT_LOADER), 1)
BOOT_ROM = $(BOOT_ROM01)
else
BOOT_ROM = $(BOOT_ROM02)
endif
ifeq ($(BOOT_COMPRESS), rle)
BOOT_CONVERTER = python ../../scripts/conv_rle.py
CFLAGS += -DBOOT_COMPRESS_RLE
OBJECTS += rle.o
endif
ifeq ($(BOOT_COMPRESS), zip)
BOOT_CONVERTER = python ../../scripts/conv_zip.py
CFLAGS += -DBOOT_COMPRESS_ZIP
OBJECTS += neginf/neginf.o
endif
ifeq ($(BOOT_COMPRESS), fastlz)
BOOT_CONVERTER = python ../../scripts/conv_fastlz.py
CFLAGS += -DBOOT_COMPRESS_FASTLZ
OBJECTS += fastlz.o
endif
COMPILE = avr-gcc -Wall -Os -DF_CPU=$(F_CPU) $(CFLAGS) -mmcu=$(DEVICE)
##############################################################################
@ -60,7 +85,6 @@ all: hex
help:
@echo "This Makefile has no default rule. Use one of the following:"
@echo "make hex ....... to build main.hex"
@echo "make program ... to flash fuses and firmware"
@echo "make fuse ...... to flash the fuses"
@echo "make flash ..... to flash the firmware (use this on metaboard)"
@echo "make clean ..... to delete objects and hex file"
@ -69,8 +93,6 @@ hex: main.hex
@echo "$(TARGET) compiled for: $(DEVICE)"
@./checksize $(TARGET).elf
program: flash fuse
# rule for programming fuse bits:
fuse:
@[ "$(FUSE_H)" != "" -a "$(FUSE_L)" != "" ] || \
@ -80,11 +102,11 @@ fuse:
flash: main.hex
$(AVRDUDE) -U flash:w:main.hex:i
loader01:
python $(CONVERT_RLE) $(BOOT_ROM01)
convert-boot-rom:
$(BOOT_CONVERTER) $(BOOT_ROM)
loader02:
python $(CONVERT_ZIP) $(BOOT_ROM02)
release: main.hex
cp -v main.hex ../../files/firmware/firmware-loader0$(BOOT_LOADER)-$(BOOT_COMPRESS)-$(BOOT_DEBUG)-$$(date +%Y%m%d).hex
.c.o:
$(COMPILE) -c $< -o $@

View File

@ -18,7 +18,6 @@
* =====================================================================================
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
@ -29,13 +28,26 @@
#include "info.h"
#include "irq.h"
#include "usbdrv.h"
#if defined(BOOT_COMPRESS_RLE)
#include "rle.h"
#endif
#if defined(BOOT_COMPRESS_ZIP)
#include "neginf/neginf.h"
#include "inflate.h"
#endif
#if defined(BOOT_COMPRESS_FASTLZ)
#include "fastlz.h"
#endif
#include "loader.h"
#include "system.h"
extern usb_transaction_t usb_trans;
extern system_t system;
extern system_t my_system;
extern const char *_rom[];
extern const char _rom01[];
@ -58,47 +70,26 @@ void usb_connect()
}
void send_reset()
{
info_P(PSTR("Reset SNES\n"));
cli();
snes_reset_on();
snes_reset_lo();
_delay_ms(2);
snes_reset_hi();
snes_reset_off();
sei();
}
void send_irq()
{
snes_irq_on();
snes_irq_lo();
_delay_us(20);
snes_irq_hi();
snes_irq_off();
}
void set_rom_mode()
{
if (usb_trans.req_bank_size == 0x8000) {
snes_lorom();
info_P(PSTR("Set SNES lowrom \n"));
} else {
snes_hirom();
info_P(PSTR("Set SNES hirom \n"));
}
}
void boot_startup_rom(uint16_t init_delay)
{
uint8_t i;
#if defined(BOOT_COMPRESS_RLE)
uint32_t addr = 0x000000;
info_P(PSTR("Fetch loader rom\n"));
#endif
#if defined(BOOT_COMPRESS_ZIP)
uint8_t c;
uint16_t j;
PGM_VOID_P p_addr;
#endif
info_P(PSTR("Fetch Loader: %s from AVR PROGMEM\n"), LOADER_NAME);
system_set_bus_avr();
snes_irq_lo();
system_snes_irq_off();
// snes_irq_lo();
// system_snes_irq_off();
system_set_rom_lorom();
// info_P(PSTR("Activate AVR bus\n"));
@ -108,11 +99,35 @@ void boot_startup_rom(uint16_t init_delay)
// snes_irq_off();
// snes_lorom();
info_P(PSTR("Unpack Loader with using method: %s\n"), LOADER_COMPRESS);
#if defined(BOOT_COMPRESS_RLE)
for (i = 0; i < ROM_BUFFER_CNT; i++) {
addr += rle_decode(_rom[i], _rom_size[i], addr);
}
#endif
#if defined(BOOT_COMPRESS_ZIP)
//inflate_init();
neginf_init(0);
for (i=0; i<ROM_BUFFER_CNT; i++){
p_addr = _rom[i];
info_P(PSTR("idx=%i addr=%lx %s\n"), i, p_addr);
for (j=0; j<_rom_size[i]; j++){
c = pgm_read_byte((PGM_VOID_P)p_addr++);
neginf_process_byte(c);
}
}
#endif
#if defined(BOOT_COMPRESS_FASTLZ)
uint32_t rlen = _rom_size[0]+ _rom_size[1];
fastlz_decompress2(_rom[0], _rom[0], rlen);
#endif
info_P(PSTR("\n"));
#if DO_CRC_CHECK_LOADER
dump_memory(0x010000 - 0x100, 0x010000);
uint16_t crc;
@ -138,27 +153,40 @@ void boot_startup_rom(uint16_t init_delay)
system_send_snes_reset();
_delay_ms(init_delay);
info_P(PSTR("Move Loader to wram"));
for (i = 0; i < 30; i++) {
_delay_ms(20);
info_P(PSTR("."));
}
info_P(PSTR("\n"));
}
void banner(){
void banner()
{
uint8_t i;
for (i = 0; i < 40; i++)
info_P(PSTR("\n"));
info_P(PSTR(" ________ .__ __ ________ ____ ________\n"));
info_P(PSTR(" \\_____ \\ __ __|__| ____ | | __\\______ \\ _______ _/_ |/ _____/\n"));
info_P(PSTR(" / / \\ \\| | \\ |/ ___\\| |/ / | | \\_/ __ \\ \\/ /| / __ \\ \n"));
info_P(PSTR(" / \\_/. \\ | / \\ \\___| < | ` \\ ___/\\ / | \\ |__\\ \\ \n"));
info_P(PSTR(" \\_____\\ \\_/____/|__|\\___ >__|_ \\/_______ /\\___ >\\_/ |___|\\_____ / \n"));
info_P(PSTR(" \\__> \\/ \\/ \\/ \\/ \\/ \n"));
info_P(PSTR
(" ________ .__ __ ________ ____ ________\n"));
info_P(PSTR
(" \\_____ \\ __ __|__| ____ | | __\\______ \\ _______ _/_ |/ _____/\n"));
info_P(PSTR
(" / / \\ \\| | \\ |/ ___\\| |/ / | | \\_/ __ \\ \\/ /| / __ \\ \n"));
info_P(PSTR
(" / \\_/. \\ | / \\ \\___| < | ` \\ ___/\\ / | \\ |__\\ \\ \n"));
info_P(PSTR
(" \\_____\\ \\_/____/|__|\\___ >__|_ \\/_______ /\\___ >\\_/ |___|\\_____ / \n"));
info_P(PSTR
(" \\__> \\/ \\/ \\/ \\/ \\/ \n"));
info_P(PSTR("\n"));
info_P(PSTR(" www.optixx.org\n"));
info_P(PSTR("\n"));
info_P(PSTR("System Hw: %s Sw: %s\n"),HW_VERSION,SW_VERSION);
info_P(PSTR("Hardware Version: %s Software Version: %s Build Date: %s \n"), HW_VERSION, SW_VERSION, __DATE__ );
}
void transaction_status(){
void transaction_status()
{
info_P(PSTR("\nAddr 0x%06lx\n"), usb_trans.req_addr);
info_P(PSTR("Bank 0x%02x\n"), usb_trans.req_bank);
info_P(PSTR("Banksize 0x%06lx\n"), usb_trans.req_bank_size);
@ -169,4 +197,3 @@ void transaction_status(){
info_P(PSTR("RX buffer %02i\n"), usb_trans.rx_remaining);
info_P(PSTR("Syncerr %02i\n"), usb_trans.sync_errors);
}

View File

@ -46,12 +46,13 @@
#define FORMAT_BUFFER_LEN 0x080
#define RECEIVE_BUF_LEN 0x030
#define HW_VERSION "2.6"
#define SW_VERSION "1.0"
#define SW_VERSION "1.2"
#define DO_CRC_CHECK_LOADER 0
#define DO_CRC_CHECK 0
#define DO_CRC_CHECK 1
#define DO_SHM_SCRATCHPAD 0
#define DO_SHM 0
#define DO_TIMER 0
#define DO_TIMER 1
#define DO_SHELL 1
#endif

View File

@ -65,18 +65,23 @@ uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size)
}
uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t top_addr, uint32_t bank_size)
uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t top_addr,
uint32_t bank_size)
{
uint16_t crc = 0;
uint32_t addr = 0;
uint8_t req_bank = 0;
sram_bulk_read_start(bottom_addr);
debug_P(DEBUG_CRC, PSTR("crc_check_bulk_memory: bottom_addr=0x%08lx top_addr=0x%08lx\n"),
debug_P(DEBUG_CRC,
PSTR
("crc_check_bulk_memory: bottom_addr=0x%08lx top_addr=0x%08lx\n"),
bottom_addr, top_addr);
for (addr = bottom_addr; addr < top_addr; addr++) {
if (addr && ((addr % bank_size) == 0)) {
debug_P(DEBUG_CRC, PSTR("crc_check_bulk_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n"),
debug_P(DEBUG_CRC,
PSTR
("crc_check_bulk_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n"),
req_bank, addr, crc);
req_bank++;
crc = 0;
@ -85,7 +90,9 @@ uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t top_addr, uint32_t
sram_bulk_read_next();
}
if (addr % 0x8000 == 0)
debug_P(DEBUG_CRC, PSTR("crc_check_bulk_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n"),
debug_P(DEBUG_CRC,
PSTR
("crc_check_bulk_memory: bank=0x%02x addr=0x%08lx crc=0x%04x\n"),
req_bank, addr, crc);
sram_bulk_read_end();
return crc;
@ -94,11 +101,13 @@ uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t top_addr, uint32_t
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer)
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,
uint8_t * buffer)
{
uint16_t crc = 0;
uint32_t addr;
for (addr = start_addr; addr < start_addr + size; addr += TRANSFER_BUFFER_SIZE) {
for (addr = start_addr; addr < start_addr + size;
addr += TRANSFER_BUFFER_SIZE) {
sram_bulk_copy_into_buffer(addr, buffer, TRANSFER_BUFFER_SIZE);
crc = do_crc_update(crc, buffer, TRANSFER_BUFFER_SIZE);
}

View File

@ -29,7 +29,9 @@
uint16_t crc_xmodem_update(uint16_t crc, uint8_t data);
uint16_t do_crc(uint8_t * data, uint16_t size);
uint16_t do_crc_update(uint16_t crc, uint8_t * data, uint16_t size);
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,uint8_t *buffer);
uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t bank_size,uint32_t top_addr);
uint16_t crc_check_memory_range(uint32_t start_addr, uint32_t size,
uint8_t * buffer);
uint16_t crc_check_bulk_memory(uint32_t bottom_addr, uint32_t bank_size,
uint32_t top_addr);
#endif

View File

@ -32,7 +32,8 @@ extern int debug_level; /* the higher, the more messages... */
#if defined(NO_DEBUG) && defined(__GNUC__)
#else
void debug(int level, char* format, ...) {
void debug(int level, char *format, ...)
{
#ifdef NO_DEBUG
#else
@ -52,7 +53,8 @@ void debug(int level, char* format, ...) {
#if defined(NO_DEBUG) && defined(__GNUC__)
#else
void debug_P(int level, PGM_P format, ...) {
void debug_P(int level, PGM_P format, ...)
{
#ifdef NO_DEBUG
#else
@ -66,4 +68,3 @@ void debug_P(int level, PGM_P format, ...) {
#endif
}
#endif

View File

@ -29,27 +29,30 @@
#include <avr/pgmspace.h>
#if defined(NO_DEBUG) && defined(__GNUC__)
/* gcc's cpp has extensions; it allows for macros with a variable number of
arguments. We use this extension here to preprocess pmesg away. */
/*
* gcc's cpp has extensions; it allows for macros with a variable number of arguments. We use this extension here to preprocess pmesg away.
*/
#define debug(level, format, args...) ((void)0)
#else
void debug(int level, char *format, ...);
/* print a message, if it is considered significant enough.
Adapted from [K&R2], p. 174 */
/*
* print a message, if it is considered significant enough. Adapted from [K&R2], p. 174
*/
#endif
#if defined(NO_DEBUG) && defined(__GNUC__)
/* gcc's cpp has extensions; it allows for macros with a variable number of
arguments. We use this extension here to preprocess pmesg away. */
/*
* gcc's cpp has extensions; it allows for macros with a variable number of arguments. We use this extension here to preprocess pmesg away.
*/
#define debug_P(level, format, args...) ((void)0)
#else
void debug_P(int level, PGM_P format, ...);
/* print a message, if it is considered significant enough.
Adapted from [K&R2], p. 174 */
/*
* print a message, if it is considered significant enough. Adapted from [K&R2], p. 174
*/
#endif
#endif /* DEBUG_H */

View File

@ -31,4 +31,3 @@ void dump_memory(uint32_t bottom_addr, uint32_t top_addr);
void dump_packet(uint32_t addr, uint32_t len, uint8_t * packet);
#endif

197
avr/usbload/fastlz.c Normal file
View File

@ -0,0 +1,197 @@
#if defined(__GNUC__) && (__GNUC__ > 2)
#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1))
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0))
#else
#define FASTLZ_EXPECT_CONDITIONAL(c) (c)
#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c)
#endif
/*
* Use inlined functions for supported systems.
*/
#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) || defined(__WATCOMC__) || defined(__SUNPRO_C)
#define FASTLZ_INLINE inline
#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__)
#define FASTLZ_INLINE __inline
#else
#define FASTLZ_INLINE
#endif
typedef unsigned char flzuint8;
typedef unsigned short flzuint16;
typedef unsigned int flzuint32;
/* prototypes */
int fastlz_decompress(const void* input, int length, void* output);
#define MAX_DISTANCE 256
#include <avr/pgmspace.h> /* required by usbdrv.h */
#include <util/delay.h> /* for _delay_ms() */
#include <avr/interrupt.h> /* for sei() */
#include "sram.h"
#include "debug.h"
#include "info.h"
#include "ringbuffer.h"
//#define log2(NUM) printf("%i op=%i(%x) ip=%i(%x) ref=%i(%x) dist=%i buf->end=%i len=%i ctrl=%i ofs=%i(%i) limit=%i\n",NUM, output_index,output[output_index], input_index,input[input_index],ref_index,input[ref_index],output_index - ref_index,ref_buffer_ptr->end, len, ctrl, ofs, ofs>>6,input_index < ip_limit);
#define log2(NUM) info_P(PSTR("%i op=%i ip=%i ref=%i dist=%i buf->end=%i len=%i ctrl=%i ofs=%i(%i) limit=%i\n"),NUM, output_index, input_index,ref_index,output_index - ref_index,ref_buffer_ptr->end, len, ctrl, ofs, ofs>>6,input_index < ip_limit);
#define OUTPUT_INC(B) do { \
__b = B;\
sram_bulk_write(__b);\
sram_bulk_write_next();\
bufferWrite(ref_buffer_ptr, __b);\
output_index++;\
} while (0)
#define OUTPUT_INC_FROM_REFINC() do { \
__dist = (output_index-ref_index); \
__c = buffer_get(ref_buffer_ptr, __dist); \
sram_bulk_write(__c);\
sram_bulk_write_next();\
output_index++;\
bufferWrite(ref_buffer_ptr, __c);\
ref_index++;\
} while (0)
#define FROM_REF(OUT) do { \
flzuint16 __dist = (output_index-ref_index+1); \
OUT = buffer_get(ref_buffer_ptr, __dist); \
} while (0)
#define OUTBYTE(OUT) do { \
sram_bulk_write(OUT);\
sram_bulk_write_next();\
output_index++;\
} while(0)
#define INBYTE(IN) do { \
cli();\
IN = pgm_read_byte((PGM_VOID_P)input_index++); \
sei();\
} while(0)
#define INPUT_INC(IN) do { \
cli();\
if (input_index<32768) { \
IN = pgm_read_byte((PGM_VOID_P)input_index++); \
} else { \
IN = pgm_read_byte((PGM_VOID_P)input_index-32768); \
input_index++; \
}\
sei();\
} while (0)
ring_buffer_typedef(unsigned char, byte_buffer);
int fastlz_decompress2(unsigned char* input1, unsigned char* input2, int length)
{
flzuint32 input_index = 0;
flzuint32 ip_limit = length;
flzuint32 output_index = 0;
flzuint32 ref_index = 0;
//flzuint32 ctrl = (input[input_index++]) & 31;
flzuint32 ctrl;
INPUT_INC(ctrl);
ctrl = ctrl & 31;
int loop = 1;
byte_buffer ref_buffer;
buffer_init(ref_buffer, MAX_DISTANCE, unsigned char);
byte_buffer* ref_buffer_ptr;
ref_buffer_ptr = &ref_buffer;
do
{
flzuint8 __b;
flzuint16 __dist;
flzuint8 __c;
flzuint8 tmp;
ref_index = output_index;
flzuint32 len = ctrl >> 5;
flzuint32 ofs = (ctrl & 31) << 6;
//log2(1)
if(ctrl >= 32)
{
len--;
ref_index -= ofs;
if (len == 7-1){
INPUT_INC(tmp);
len += tmp;
//len += input[input_index++];
}
INPUT_INC(tmp);
ref_index -= tmp;
//ref_index -= input[input_index++];
//log2(1)
if(FASTLZ_EXPECT_CONDITIONAL( input_index < ip_limit))
INPUT_INC(ctrl);
//ctrl = input[input_index++];
else
loop = 0;
//log2(1)
if(ref_index == output_index)
{
//log2(2)
//flzuint8 b = output[ref_index-1];
flzuint8 b;
FROM_REF(b);
OUTPUT_INC(b);
OUTPUT_INC(b);
OUTPUT_INC(b);
for(; len; --len)
OUTPUT_INC(b);
}
else
{
//log2(3)
ref_index--;
OUTPUT_INC_FROM_REFINC();
OUTPUT_INC_FROM_REFINC();
OUTPUT_INC_FROM_REFINC();
for(; len; --len)
OUTPUT_INC_FROM_REFINC();
}
}
else
{
ctrl++;
//log2(4)
INPUT_INC(tmp);
OUTPUT_INC(tmp);
//OUTPUT_INC(input[input_index++]);
for(--ctrl; ctrl; ctrl--){
//log2(5)
INPUT_INC(tmp);
OUTPUT_INC(tmp);
//OUTPUT_INC(input[input_index++]);
}
loop = FASTLZ_EXPECT_CONDITIONAL(input_index < ip_limit);
if (loop){
INPUT_INC(ctrl);
//ctrl = input[input_index++];
}
//log2(6)
}
}
while(FASTLZ_EXPECT_CONDITIONAL(loop));
buffer_destroy(ref_buffer_ptr);
return 0;
}

14
avr/usbload/fastlz.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef FASTLZ_H
#define FASTLZ_H
#define FASTLZ_VERSION 0x000100
#define FASTLZ_VERSION_MAJOR 0
#define FASTLZ_VERSION_MINOR 0
#define FASTLZ_VERSION_REVISION 0
#define FASTLZ_VERSION_STRING "0.1.0"
int fastlz_decompress2(const void* input1, const void* input2, int length);
#endif /* FASTLZ_H */

View File

@ -37,7 +37,8 @@ extern FILE uart_stdout;
#define info(format, args...) ((void)0)
#else
void info(char* format, ...) {
void info(char *format, ...)
{
#ifdef NO_INFO
#else
@ -59,7 +60,8 @@ void info(char* format, ...) {
#define info(format, args...) ((void)0)
#else
void info_P(PGM_P format, ...) {
void info_P(PGM_P format, ...)
{
#ifdef NO_INFO
#else
@ -71,4 +73,3 @@ void info_P(PGM_P format, ...) {
#endif
}
#endif

View File

@ -29,24 +29,28 @@
#include <avr/pgmspace.h>
#if defined(NO_INFO) && defined(__GNUC__)
/* gcc's cpp has extensions; it allows for macros with a variable number of
arguments. We use this extension here to preprocess pmesg away. */
/*
* gcc's cpp has extensions; it allows for macros with a variable number of arguments. We use this extension here to preprocess pmesg away.
*/
#define info(format, args...) ((void)0)
#else
void info(char *format, ...);
/* print a message, if it is considered significant enough.
Adapted from [K&R2], p. 174 */
/*
* print a message, if it is considered significant enough. Adapted from [K&R2], p. 174
*/
#endif
#if defined(NO_INFO) && defined(__GNUC__)
/* gcc's cpp has extensions; it allows for macros with a variable number of
arguments. We use this extension here to preprocess pmesg away. */
/*
* gcc's cpp has extensions; it allows for macros with a variable number of arguments. We use this extension here to preprocess pmesg away.
*/
#define info_P(format, args...) ((void)0)
#else
void info_P(PGM_P format, ...);
/* print a message, if it is considered significant enough.
Adapted from [K&R2], p. 174 */
/*
* print a message, if it is considered significant enough. Adapted from [K&R2], p. 174
*/
#endif

View File

@ -23,49 +23,49 @@
#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h> /* for sei() */
#include <avr/wdt.h>
#include "usbdrv.h"
#include "oddebug.h" /* This is also an example for using debug
* macros */
#include "oddebug.h" /* This is also an example for using debug macros */
#include "debug.h"
#include "info.h"
#include "sram.h"
#include "system.h"
extern system_t system;
extern system_t my_system;
void (*jump_to_app) (void) = 0x0000;
void irq_init(){
void irq_init()
{
cli();
PCMSK3 |= (1 << PCINT27);
PCICR |= (1 << PCIE3);
sei();
system.reset_irq = RESET_IRQ_ON;
my_system.reset_irq = RESET_IRQ_ON;
}
void irq_stop(){
void irq_stop()
{
cli();
PCMSK3 &= ~(1 << PCINT27);
sei();
system.reset_irq = RESET_IRQ_OFF;
my_system.reset_irq = RESET_IRQ_OFF;
}
void leave_application(void)
{
cli();
usbDeviceDisconnect();
system.avr_reset_count++;
my_system.avr_reset_count++;
wdt_enable(WDTO_15MS);
while (1);
}
ISR (SIG_PIN_CHANGE3)
ISR(PCINT3_vect)
{
if (snes_reset_test()) {
info_P(PSTR("Catch SNES reset button\n"));
@ -73,4 +73,3 @@ ISR (SIG_PIN_CHANGE3)
leave_application();
}
}

View File

@ -1,11 +1,12 @@
/*
File: qd16boot01.smc
Time: Tue, 20 Oct 2009 21:42:10
File: qd16boot_ver01.smc
Time: Sat, 20 Aug 2016 18:12:14
*/
#ifndef __FIFO_H__
#define __FIFO_H__
#define ROM_HUFFMAN_SIZE 0
#define LOADER_NAME "qd16boot_ver01.smc"
#define LOADER_COMPRESS "RLE"
#define ROM_RLE_SIZE 31091
#define ROM_BUFFER_CNT 1

View File

@ -19,8 +19,6 @@
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>
@ -54,10 +52,9 @@
#ifndef NO_DEBUG
extern FILE uart_stdout;
#endif
extern system_t system;
uint8_t debug_level = (DEBUG | DEBUG_CRC);
extern system_t my_system;
uint8_t debug_level = (DEBUG | DEBUG_USB | DEBUG_CRC);
usb_transaction_t usb_trans;
@ -71,20 +68,24 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
usb_trans.req_bank = 0;
usb_trans.rx_remaining = 0;
debug_P(DEBUG_USB, PSTR("USB_BULK_UPLOAD_INIT: %i %i\n"), rq->wValue.word,
rq->wIndex.word);
debug_P(DEBUG_USB, PSTR("USB_BULK_UPLOAD_INIT: %i %i\n"),
rq->wValue.word, rq->wIndex.word);
usb_trans.req_bank_size = (uint32_t) (1L << rq->wValue.word);
usb_trans.req_bank_cnt = rq->wIndex.word;
usb_trans.req_addr_end = (uint32_t) usb_trans.req_bank_size * usb_trans.req_bank_cnt;
usb_trans.req_addr_end =
(uint32_t) usb_trans.req_bank_size * usb_trans.req_bank_cnt;
usb_trans.req_percent = 0;
usb_trans.req_percent_last = 0;
usb_trans.sync_errors = 0;
debug_P(DEBUG_USB,
PSTR("USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n"),
usb_trans.req_bank_size, usb_trans.req_bank_cnt, usb_trans.req_addr_end);
PSTR
("USB_BULK_UPLOAD_INIT: bank_size=0x%08lx bank_cnt=0x%x end_addr=0x%08lx\n"),
usb_trans.req_bank_size, usb_trans.req_bank_cnt,
usb_trans.req_addr_end);
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_START, 0);
shared_memory_write(SHARED_MEM_TX_CMD_BANK_COUNT, usb_trans.req_bank_cnt);
shared_memory_write(SHARED_MEM_TX_CMD_BANK_COUNT,
usb_trans.req_bank_cnt);
#if DO_TIMER
if (usb_trans.req_addr == 0x000000) {
#ifndef NO_DEBUG
@ -105,16 +106,19 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
if (usb_trans.req_addr && usb_trans.req_addr % usb_trans.req_bank_size == 0) {
if (usb_trans.req_addr
&& usb_trans.req_addr % usb_trans.req_bank_size == 0) {
#if DO_TIMER
#ifndef NO_DEBUG
#ifdef FLT_DEBUG
debug_P(DEBUG_USB,
PSTR("USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%.4f\n"),
PSTR
("USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%.4f\n"),
usb_trans.req_bank, usb_trans.req_addr, timer_stop());
#else
debug_P(DEBUG_USB,
PSTR("USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%i\n"),
PSTR
("USB_BULK_UPLOAD_ADDR: req_bank=0x%02x addr=0x%08lx time=%i\n"),
usb_trans.req_bank, usb_trans.req_addr, timer_stop_int());
#endif
timer_start();
@ -138,23 +142,28 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
usb_trans.rx_remaining = rq->wLength.word;
#if DO_SHM
usb_trans.req_percent = (uint32_t)( 100 * usb_trans.req_addr ) / usb_trans.req_addr_end;
usb_trans.req_percent =
(uint32_t) (100 * usb_trans.req_addr) / usb_trans.req_addr_end;
if (usb_trans.req_percent != usb_trans.req_percent_last) {
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS, usb_trans.req_percent);
shared_memory_write(SHARED_MEM_TX_CMD_UPLOAD_PROGESS,
usb_trans.req_percent);
}
usb_trans.req_percent_last = usb_trans.req_percent;
shared_memory_scratchpad_region_save_helper(usb_trans.req_addr);
#endif
if (usb_trans.req_addr && (usb_trans.req_addr % usb_trans.req_bank_size) == 0) {
if (usb_trans.req_addr
&& (usb_trans.req_addr % usb_trans.req_bank_size) == 0) {
#if DO_TIMER
#ifndef NO_DEBUG
#ifdef FLT_DEBUG
debug_P(DEBUG_USB,
PSTR("USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%.4f\n"),
PSTR
("USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%.4f\n"),
usb_trans.req_bank, usb_trans.req_addr, timer_stop());
#else
debug_P(DEBUG_USB,
PSTR("USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%i\n"),
PSTR
("USB_BULK_UPLOAD_NEXT: req_bank=0x%02x addr=0x%08lx time=%i\n"),
usb_trans.req_bank, usb_trans.req_addr, timer_stop_int());
#endif
timer_start();
@ -162,7 +171,8 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
#endif
usb_trans.req_bank++;
#if DO_SHM
shared_memory_write(SHARED_MEM_TX_CMD_BANK_CURRENT, usb_trans.req_bank);
shared_memory_write(SHARED_MEM_TX_CMD_BANK_CURRENT,
usb_trans.req_bank);
#endif
}
ret_len = USB_MAX_TRANS;
@ -170,11 +180,6 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_BULK_UPLOAD_END) {
if (usb_trans.req_state != REQ_STATUS_BULK_UPLOAD) {
debug_P(DEBUG_USB,
PSTR("USB_BULK_UPLOAD_END: ERROR state is not REQ_STATUS_BULK_UPLOAD\n"));
return 0;
}
debug_P(DEBUG_USB, PSTR("USB_BULK_UPLOAD_END:\n"));
usb_trans.req_state = REQ_STATUS_IDLE;
sram_bulk_write_end();
@ -190,8 +195,12 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
usb_trans.req_addr = rq->wValue.word;
usb_trans.req_addr = usb_trans.req_addr << 16;
usb_trans.req_addr = usb_trans.req_addr | rq->wIndex.word;
debug_P(DEBUG_USB, PSTR("USB_CRC: addr=0x%08lx \n"), usb_trans.req_addr);
crc_check_bulk_memory(0x000000, usb_trans.req_addr, usb_trans.req_bank_size);
debug_P(DEBUG_USB, PSTR("USB_CRC: addr=0x%08lx \n"),
usb_trans.req_addr);
#if DO_CRC_CHECK
crc_check_bulk_memory(0x000000, usb_trans.req_addr,
usb_trans.req_bank_size);
#endif
ret_len = 0;
/*
* -------------------------------------------------------------------------
@ -219,6 +228,7 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
* -------------------------------------------------------------------------
*/
} else if (rq->bRequest == USB_SET_LAODER) {
debug_P(DEBUG_USB, PSTR("USB_SET_LAODER:\n"));
usb_trans.loader_enabled = rq->wValue.word;
ret_len = 0;
}
@ -231,7 +241,8 @@ usbMsgLen_t usbFunctionSetup(uchar data[8])
*/
void globals_init(){
void globals_init()
{
memset(&usb_trans, 0, sizeof(usb_transaction_t));
usb_trans.req_addr = 0;
@ -263,20 +274,14 @@ int main(void)
usb_connect();
sei();
while (1) {
system_set_bus_avr();
system_set_wr_disable();
/*
avr_bus_active();
info_P(PSTR("Activate AVR bus\n"));
info_P(PSTR("Disable SNES WR\n"));
snes_wr_disable();
*/
info_P(PSTR("USB poll\n"));
while (usb_trans.req_state != REQ_STATUS_SNES) {
usbPoll();
#if DO_SHELL
#ifndef NO_DEBUG
shell_run();
#endif
#endif
}
@ -291,7 +296,9 @@ int main(void)
#if DO_CRC_CHECK
info_P(PSTR("-->CRC Check\n"));
crc_check_bulk_memory(0x000000, usb_trans.req_bank_size * usb_trans.req_bank_cnt, usb_trans.req_bank_size);
crc_check_bulk_memory(0x000000,
usb_trans.req_bank_size * usb_trans.req_bank_cnt,
usb_trans.req_bank_size);
#endif
system_set_rom_mode(&usb_trans);
@ -299,35 +306,24 @@ int main(void)
system_set_bus_snes();
system_send_snes_reset();
irq_stop();
/*
info_P(PSTR("-->Switch TO SNES\n"));
set_rom_mode();
snes_wr_disable();
info_P(PSTR("Disable SNES WR\n"));
snes_bus_active();
info_P(PSTR("Activate SNES bus\n"));
irq_stop();
send_reset();
*/
info_P(PSTR("Poll USB\n"));
while ((usb_trans.req_state != REQ_STATUS_AVR)) {
usbPoll();
#if DO_SHELL
#ifndef NO_DEBUG
shell_run();
#endif
#endif
}
//info_P(PSTR("-->Switch TO AVR\n"));
info_P(PSTR("-->Switch TO AVR\n"));
shared_memory_init();
irq_init();
if (usb_trans.loader_enabled) {
boot_startup_rom(500);
boot_startup_rom(50);
} else {
system_set_bus_avr();
system_send_snes_reset();
//avr_bus_active();
//send_reset();
}
irq_init();
globals_init();
}
return 0;
}

View File

@ -32,10 +32,14 @@
#define PWM_OVERFLOW_MAX 1024
uint8_t pwm_sine_table[] = {
0x7f,0x8b,0x97,0xa4,0xaf,0xbb,0xc5,0xcf,0xd9,0xe1,0xe8,0xef,0xf4,0xf8,0xfb,0xfd,
0xfd,0xfd,0xfb,0xf8,0xf3,0xee,0xe7,0xe0,0xd7,0xce,0xc4,0xb9,0xae,0xa2,0x96,0x89,
0x7e,0x71,0x65,0x59,0x4d,0x42,0x37,0x2d,0x24,0x1c,0x15,0x0f,0x09,0x05,0x03,0x01,
0x01,0x01,0x03,0x07,0x0b,0x11,0x17,0x1f,0x28,0x31,0x3b,0x46,0x52,0x5e,0x6a,0x76
0x7f, 0x8b, 0x97, 0xa4, 0xaf, 0xbb, 0xc5, 0xcf, 0xd9, 0xe1, 0xe8, 0xef,
0xf4, 0xf8, 0xfb, 0xfd,
0xfd, 0xfd, 0xfb, 0xf8, 0xf3, 0xee, 0xe7, 0xe0, 0xd7, 0xce, 0xc4, 0xb9,
0xae, 0xa2, 0x96, 0x89,
0x7e, 0x71, 0x65, 0x59, 0x4d, 0x42, 0x37, 0x2d, 0x24, 0x1c, 0x15, 0x0f,
0x09, 0x05, 0x03, 0x01,
0x01, 0x01, 0x03, 0x07, 0x0b, 0x11, 0x17, 0x1f, 0x28, 0x31, 0x3b, 0x46,
0x52, 0x5e, 0x6a, 0x76
};
volatile uint8_t pwm_setting;
@ -43,7 +47,8 @@ volatile uint16_t pwm_overflow;
volatile uint8_t pwm_idx;
volatile uint16_t pwm_overflow_max;
ISR(TIMER2_COMPA_vect) {
ISR(TIMER2_COMPA_vect)
{
static uint8_t pwm_cnt = 0;
OCR2A += (uint16_t) T_PWM;
@ -64,33 +69,40 @@ volatile uint16_t pwm_overflow_max;
}
}
void pwm_speed(uint16_t val) {
void pwm_speed(uint16_t val)
{
pwm_overflow_max = val;
}
void pwm_speed_slow(uint16_t val) {
void pwm_speed_slow(uint16_t val)
{
pwm_overflow_max = PWM_OVERFLOW_MAX * 2;
}
void pwm_speed_fast(uint16_t val) {
void pwm_speed_fast(uint16_t val)
{
pwm_overflow_max = PWM_OVERFLOW_MAX / 2;
}
void pwm_speed_normal(uint16_t val) {
void pwm_speed_normal(uint16_t val)
{
pwm_overflow_max = PWM_OVERFLOW_MAX;
}
void pwm_set(uint8_t val) {
void pwm_set(uint8_t val)
{
pwm_setting = val;
}
void pwm_stop(void) {
void pwm_stop(void)
{
while (pwm_setting != 0xfd);
TIMSK2 = 0;
}
void pwm_init(void) {
void pwm_init(void)
{
pwm_overflow_max = PWM_OVERFLOW_MAX;
pwm_setting = 0x7f;
pwm_overflow = 0;

42
avr/usbload/ringbuffer.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef _ringbuffer_h
#define _ringbuffer_h
int __mod(int a, int b)
{
int r = a % b;
return r < 0 ? r + b : r;
}
#define ring_buffer_typedef(T, NAME) \
typedef struct { \
int size; \
int start; \
int end; \
T* elems; \
} NAME
#define buffer_init(BUF, S, T) \
BUF.size = S+1; \
BUF.start = 0; \
BUF.end = 0; \
BUF.elems = (T*)calloc(BUF.size, sizeof(T))
#define buffer_destroy(BUF) free(BUF->elems)
#define nex_start_index(BUF) ((BUF->start + 1) % BUF->size)
#define is_buffer_empty(BUF) (BUF->end == BUF->start)
#define buffer_get(BUF, INDEX) (BUF->elems[__mod(BUF->end - INDEX, BUF->size)])
#define bufferWrite(BUF, ELEM) \
BUF->elems[BUF->end] = ELEM; \
BUF->end = (BUF->end + 1) % BUF->size; \
if (is_buffer_empty(BUF)) { \
BUF->start = nex_start_index(BUF); \
}
#define bufferRead(BUF, ELEM) \
ELEM = BUF->elems[BUF->start]; \
BUF->start = nex_start_index(BUF);
#endif

View File

@ -48,25 +48,35 @@ uint8_t scratchpad_locked_rx = 1;
uint8_t scratchpad_locked_tx = 1;
void shared_memory_init(void){
void shared_memory_init(void)
{
scratchpad_locked_rx = 1;
scratchpad_locked_tx = 1;
}
uint8_t shared_memory_scratchpad_region_save_helper(uint32_t addr){
uint8_t shared_memory_scratchpad_region_save_helper(uint32_t addr)
{
#if DO_SHM_SCRATCHPAD
if(addr > (SHARED_MEM_TX_LOC_STATE + (SHARED_MEM_TX_LOC_SIZE )) && scratchpad_locked_tx){
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_save_helper: open tx addr=0x%06lx\n"),addr);
if (addr > (SHARED_MEM_TX_LOC_STATE + (SHARED_MEM_TX_LOC_SIZE))
&& scratchpad_locked_tx) {
debug_P(DEBUG_SHM,
PSTR
("shared_memory_scratchpad_region_save_helper: open tx addr=0x%06lx\n"),
addr);
shared_memory_scratchpad_region_tx_save();
return 0;
}
if(addr > (SHARED_MEM_RX_LOC_STATE + ( SHARED_MEM_RX_LOC_SIZE )) && scratchpad_locked_rx){
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_save_helper: open rx addr=0x%06lx\n"),addr);
if (addr > (SHARED_MEM_RX_LOC_STATE + (SHARED_MEM_RX_LOC_SIZE))
&& scratchpad_locked_rx) {
debug_P(DEBUG_SHM,
PSTR
("shared_memory_scratchpad_region_save_helper: open rx addr=0x%06lx\n"),
addr);
shared_memory_scratchpad_region_rx_save();
return 0;
}
@ -82,24 +92,31 @@ void shared_memory_scratchpad_region_tx_save()
#if SHARED_SCRATCHPAD_CRC
uint16_t crc;
crc = crc_check_bulk_memory((uint32_t) SHARED_MEM_TX_LOC_STATE,
(uint32_t)(SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_save: crc=%x\n"),crc);
(uint32_t) (SHARED_MEM_TX_LOC_STATE +
SHARED_MEM_TX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_save: crc=%x\n"), crc);
#endif
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_save: unlock\n"));
sram_bulk_copy_into_buffer((uint32_t)SHARED_MEM_TX_LOC_STATE,scratchpad_region_tx,
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_save: unlock\n"));
sram_bulk_copy_into_buffer((uint32_t) SHARED_MEM_TX_LOC_STATE,
scratchpad_region_tx,
(uint32_t) SHARED_MEM_TX_LOC_SIZE);
scratchpad_locked_tx = 0;
#if SHARED_SCRATCHPAD_CRC
do_crc_update(0, scratchpad_region_tx, SHARED_MEM_TX_LOC_SIZE);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_save: crc=%x\n"),crc);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_save: crc=%x\n"), crc);
#endif
#if SHARED_SCRATCHPAD_DUMP
dump_packet(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_LOC_SIZE, scratchpad_region_tx);
dump_memory(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE);
dump_packet(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_LOC_SIZE,
scratchpad_region_tx);
dump_memory(SHARED_MEM_TX_LOC_STATE,
SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE);
#endif
sram_bulk_addr_restore();
@ -112,23 +129,30 @@ void shared_memory_scratchpad_region_rx_save()
#if SHARED_SCRATCHPAD_CRC
uint16_t crc;
crc = crc_check_bulk_memory((uint32_t) SHARED_MEM_RX_LOC_STATE,
(uint32_t)(SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_save: crc=%x\n"),crc);
(uint32_t) (SHARED_MEM_RX_LOC_STATE +
SHARED_MEM_RX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_save: crc=%x\n"), crc);
#endif
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_save: unlock\n"));
sram_bulk_copy_into_buffer((uint32_t)SHARED_MEM_RX_LOC_STATE,scratchpad_region_rx,
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_save: unlock\n"));
sram_bulk_copy_into_buffer((uint32_t) SHARED_MEM_RX_LOC_STATE,
scratchpad_region_rx,
(uint32_t) SHARED_MEM_RX_LOC_SIZE);
scratchpad_locked_rx = 0;
#if SHARED_SCRATCHPAD_CRC
do_crc_update(0, scratchpad_region_rx, SHARED_MEM_RX_LOC_SIZE);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_save: crc=%x\n"),crc);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_save: crc=%x\n"), crc);
#endif
#if SHARED_SCRATCHPAD_DUMP
dump_packet(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_LOC_SIZE, scratchpad_region_rx);
dump_memory(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE);
dump_packet(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_LOC_SIZE,
scratchpad_region_rx);
dump_memory(SHARED_MEM_RX_LOC_STATE,
SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE);
#endif
sram_bulk_addr_restore();
@ -138,29 +162,39 @@ void shared_memory_scratchpad_region_tx_restore()
{
if (scratchpad_locked_tx)
return;
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_restore: lock\n"));
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_restore: lock\n"));
#if SHARED_SCRATCHPAD_DUMP
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_restore: memory\n"));
dump_memory(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_restore: memory\n"));
dump_memory(SHARED_MEM_TX_LOC_STATE,
SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE);
#endif
sram_bulk_copy_from_buffer((uint32_t)SHARED_MEM_TX_LOC_STATE,scratchpad_region_tx,
sram_bulk_copy_from_buffer((uint32_t) SHARED_MEM_TX_LOC_STATE,
scratchpad_region_tx,
(uint32_t) SHARED_MEM_TX_LOC_SIZE);
scratchpad_locked_tx = 1;
#if SHARED_SCRATCHPAD_DUMP
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_restore: buffer\n"));
dump_packet(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_LOC_SIZE, scratchpad_region_tx);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_restore: memory\n"));
dump_memory(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_restore: buffer\n"));
dump_packet(SHARED_MEM_TX_LOC_STATE, SHARED_MEM_TX_LOC_SIZE,
scratchpad_region_tx);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_restore: memory\n"));
dump_memory(SHARED_MEM_TX_LOC_STATE,
SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE);
#endif
#if SHARED_SCRATCHPAD_CRC
uint16_t crc;
crc = crc_check_bulk_memory((uint32_t) SHARED_MEM_TX_LOC_STATE,
(uint32_t)(SHARED_MEM_TX_LOC_STATE + SHARED_MEM_TX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_tx_restore: crc=%x\n"),crc);
(uint32_t) (SHARED_MEM_TX_LOC_STATE +
SHARED_MEM_TX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_tx_restore: crc=%x\n"), crc);
#endif
}
@ -171,29 +205,39 @@ void shared_memory_scratchpad_region_rx_restore()
return;
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_restore: lock\n"));
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_restore: lock\n"));
#if SHARED_SCRATCHPAD_DUMP
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_restore: memory\n"));
dump_memory(SHARED_MEM_RX_LOC_STATE - 0x10, SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_restore: memory\n"));
dump_memory(SHARED_MEM_RX_LOC_STATE - 0x10,
SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE);
#endif
sram_bulk_copy_from_buffer((uint32_t)SHARED_MEM_RX_LOC_STATE,scratchpad_region_rx,
sram_bulk_copy_from_buffer((uint32_t) SHARED_MEM_RX_LOC_STATE,
scratchpad_region_rx,
(uint32_t) SHARED_MEM_RX_LOC_SIZE);
scratchpad_locked_rx = 1;
#if SHARED_SCRATCHPAD_DUMP
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_restore: buffer\n"));
dump_packet(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_LOC_SIZE, scratchpad_region_rx);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_restore: memory\n"));
dump_memory(SHARED_MEM_RX_LOC_STATE - 0x10, SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_restore: buffer\n"));
dump_packet(SHARED_MEM_RX_LOC_STATE, SHARED_MEM_RX_LOC_SIZE,
scratchpad_region_rx);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_restore: memory\n"));
dump_memory(SHARED_MEM_RX_LOC_STATE - 0x10,
SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE);
#endif
#if SHARED_SCRATCHPAD_CRC
uint16_t crc;
crc = crc_check_bulk_memory((uint32_t) SHARED_MEM_RX_LOC_STATE,
(uint32_t)(SHARED_MEM_RX_LOC_STATE + SHARED_MEM_RX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM, PSTR("shared_memory_scratchpad_region_rx_restore: crc=%x\n"),crc);
(uint32_t) (SHARED_MEM_RX_LOC_STATE +
SHARED_MEM_RX_LOC_SIZE), 0x8000);
debug_P(DEBUG_SHM,
PSTR("shared_memory_scratchpad_region_rx_restore: crc=%x\n"), crc);
#endif
}
@ -236,7 +280,8 @@ void shared_memory_write(uint8_t cmd, uint8_t value)
return;
}
#endif
debug_P(DEBUG_SHM, PSTR("shared_memory_write: 0x%04x=0x%02x 0x%04x=0x%02x \n"),
debug_P(DEBUG_SHM,
PSTR("shared_memory_write: 0x%04x=0x%02x 0x%04x=0x%02x \n"),
SHARED_MEM_TX_LOC_CMD, cmd, SHARED_MEM_TX_LOC_PAYLOAD, value);
sram_bulk_addr_save();
@ -298,7 +343,7 @@ void shared_memory_yield()
int shared_memory_read(uint8_t * cmd, uint8_t * len, uint8_t * buffer)
{
uint8_t state;
// uint8_t state;
#if DO_SHM
#if DO_SHM_SCRATCHPAD
if (scratchpad_locked_rx) {
@ -316,7 +361,8 @@ int shared_memory_read(uint8_t *cmd, uint8_t *len,uint8_t *buffer)
*cmd = sram_read(SHARED_MEM_RX_LOC_CMD);
*len = sram_read(SHARED_MEM_RX_LOC_LEN);
debug_P(DEBUG_SHM, PSTR("shared_memory_read: 0x%04x=0x%02x 0x%04x=0x%02x \n"),
debug_P(DEBUG_SHM,
PSTR("shared_memory_read: 0x%04x=0x%02x 0x%04x=0x%02x \n"),
SHARED_MEM_RX_LOC_CMD, *cmd, SHARED_MEM_RX_LOC_LEN, *len);
sram_bulk_copy_into_buffer(SHARED_MEM_RX_LOC_PAYLOAD, buffer, *len);

View File

@ -56,7 +56,9 @@
#define SHARED_IRQ_LOC_LO 0x00fffe
#define SHARED_IRQ_LOC_HI 0x00ffff
/* Use COP IRQ LOC for hooked IRQ handler */
/*
* Use COP IRQ LOC for hooked IRQ handler
*/
#define SHARED_IRQ_HANDLER_LO 0x0ffe4
#define SHARED_IRQ_HANDLER_HI 0x0ffe5

View File

@ -42,7 +42,7 @@
#include "system.h"
extern system_t system;
extern system_t my_system;
const char STR_ROM[] PROGMEM = "Rom";
const char STR_RAM[] PROGMEM = "Sram";
@ -59,6 +59,8 @@ volatile uint8_t cr = 0;
uint8_t *token_ptr;
#if DO_SHELL
uint8_t *get_token(void)
{
uint8_t *p = token_ptr;
@ -117,6 +119,7 @@ uint8_t get_hex_arg3(uint32_t *hexval1, uint32_t *hexval2, uint32_t *hexval3)
return get_hex(hexval1) && get_hex(hexval2) && get_hex(hexval3);
}
#if 0
static uint8_t get_int32(uint32_t * val)
{
if (!get_hex(val)) {
@ -138,7 +141,7 @@ static uint8_t get_int32(uint32_t *val)
return 1;
}
}
#endif
static int get_bool(void)
{
const uint8_t *t;
@ -151,7 +154,8 @@ static uint8_t get_int32(uint32_t *val)
info_P(PSTR("Invalid argument (should be 0 or 1)!\n"));
return -1;
}
void prompt(void){
void prompt(void)
{
uart_putc('\r');
uart_putc('\n');
@ -172,14 +176,17 @@ ISR(USART0_RX_vect)
recv_buf[recv_counter] = UDR0;
uart_putc(recv_buf[recv_counter]);
if (recv_buf[recv_counter] == 0x0d) {
/* recv_buf[recv_counter] = 0; */
/*
* recv_buf[recv_counter] = 0;
*/
cr = 1;
recv_buf[++recv_counter] = '\0';
recv_counter = 0;
prompt();
} else {
// we accept backspace or delete
if ((recv_buf[recv_counter] == 0x08 || recv_buf[recv_counter] == 0x7f) && recv_counter > 0) {
if ((recv_buf[recv_counter] == 0x08 || recv_buf[recv_counter] == 0x7f)
&& recv_counter > 0) {
recv_counter--;
} else {
recv_counter++;
@ -192,7 +199,9 @@ enum cmds {
CMD_DUMP,
CMD_DUMPVEC,
CMD_DUMPHEADER,
#if DO_CRC_CHECK
CMD_CRC,
#endif
CMD_EXIT,
CMD_RESET,
CMD_RESETSNIFF,
@ -212,11 +221,13 @@ enum cmds {
CMD_HELP
};
uint8_t cmdlist[][CMD_HELP] PROGMEM = {
const uint8_t cmdlist[][CMD_HELP] PROGMEM = {
{"DUMP"},
{"DUMPVEC"},
{"DUMPHEADER"},
#if DO_CRC_CHECK
{"CRC"},
#endif
{"EXIT"},
{"RESET"},
{"RESETSNIFF"},
@ -237,7 +248,8 @@ uint8_t cmdlist[][CMD_HELP] PROGMEM = {
};
void shell_help(void){
void shell_help(void)
{
uint8_t i;
info_P(PSTR("\n"));
for (i = CMD_DUMP; i < CMD_HELP; i++) {
@ -253,10 +265,8 @@ void shell_run(void)
uint8_t *t;
uint32_t arg1;
uint32_t arg2;
uint32_t arg3;
uint16_t crc;
uint16_t offset;
uint16_t i;
uint8_t c;
if (!cr)
@ -278,12 +288,14 @@ void shell_run(void)
else
info_P(PSTR("DUMP <start addr> <end addr>\n"));
#if DO_CRC_CHECK
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_CRC]) == 0) {
if (get_hex_arg2(&arg1, &arg2)) {
crc = crc_check_bulk_memory(arg1, arg2, 0x8000);
info_P(PSTR("0x%06lx - 0x%06lx crc=0x%04x\n"), arg1, arg2, crc);
} else
info_P(PSTR("CRC <start addr> <end addr>\n"));
#endif
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_EXIT]) == 0) {
leave_application();
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_RESET]) == 0) {
@ -296,36 +308,21 @@ void shell_run(void)
snes_irq_hi();
snes_irq_off();
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_AVR]) == 0) {
//info_P(PSTR("Activate AVR bus\n"));
//avr_bus_active();
//snes_irq_lo();
//snes_irq_off();
system_set_bus_avr();
snes_irq_lo();
system_snes_irq_off();
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SNES]) == 0) {
//info_P(PSTR("Activate SNES bus\n"));
//snes_irq_lo();
//snes_irq_off();
//snes_wr_disable();
//snes_bus_active();
snes_irq_lo();
system_snes_irq_off();
system_set_wr_disable();
system_set_bus_snes();
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_LOROM]) == 0) {
//info_P(PSTR("Set LOROM\n"));
//snes_lorom();
//snes_wr_disable();
system_set_rom_lorom();
system_set_wr_disable();
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_HIROM]) == 0) {
//info_P(PSTR("Set HIROM\n"));
//snes_hirom();
//snes_wr_disable();
system_set_rom_hirom();
system_set_wr_disable();
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_WR]) == 0) {
@ -348,36 +345,38 @@ void shell_run(void)
}
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_DUMPVEC]) == 0) {
uint16_t offset;
if (system.rom_mode==LOROM)
if (my_system.rom_mode == LOROM)
offset = 0x8000;
else
offset = 0x0000;
info_P(PSTR("ABORT 0x%04x 0x%04x\n"), (0xFFE8 - offset),sram_read16_be(0xFFE8 - offset));
info_P(PSTR("BRK 0x%04x 0x%04x\n"), (0xFFE6 - offset),sram_read16_be(0xFFE6 - offset));
info_P(PSTR("COP 0x%04x 0x%04x\n"), (0xFFE4 - offset),sram_read16_be(0xFFE4 - offset));
info_P(PSTR("IRQ 0x%04x 0x%04x\n"), (0xFFEE - offset),sram_read16_be(0xFFEE - offset));
info_P(PSTR("NMI 0x%04x 0x%04x\n"), (0xFFEA - offset),sram_read16_be(0xFFEA - offset));
info_P(PSTR("RES 0x%04x 0x%04x\n"), (0xFFFC - offset),sram_read16_be(0xFFFC - offset));
info_P(PSTR("ABORT 0x%04x 0x%04x\n"), (0xFFE8 - offset),
sram_read16_be(0xFFE8 - offset));
info_P(PSTR("BRK 0x%04x 0x%04x\n"), (0xFFE6 - offset),
sram_read16_be(0xFFE6 - offset));
info_P(PSTR("COP 0x%04x 0x%04x\n"), (0xFFE4 - offset),
sram_read16_be(0xFFE4 - offset));
info_P(PSTR("IRQ 0x%04x 0x%04x\n"), (0xFFEE - offset),
sram_read16_be(0xFFEE - offset));
info_P(PSTR("NMI 0x%04x 0x%04x\n"), (0xFFEA - offset),
sram_read16_be(0xFFEA - offset));
info_P(PSTR("RES 0x%04x 0x%04x\n"), (0xFFFC - offset),
sram_read16_be(0xFFFC - offset));
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_DUMPHEADER]) == 0) {
if (system.rom_mode==LOROM)
if (my_system.rom_mode == LOROM)
offset = 0x8000;
else
offset = 0x0000;
/*
# $ffc0..$ffd4 => Name of the ROM, typically in ASCII, using spaces to pad the name to 21 bytes.
# $ffd5 => ROM layout, typically $20 for LoROM, or $21 for HiROM. Add $10 for FastROM.
# $ffd6 => Cartridge type, typically $00 for ROM only, or $02 for ROM with save-RAM.
# $ffd7 => ROM size byte.
# $ffd8 => RAM size byte.
# $ffd9 => Country code, which selects the video in the emulator. Values $00, $01, $0d use NTSC. Values in range $02..$0c use PAL. Other values are invalid.
# $ffda => Licensee code. If this value is $33, then the ROM has an extended header with ID at $ffb2..$ffb5.
# $ffdb => Version number, typically $00.
# $ffdc..$ffdd => Checksum complement, which is the bitwise-xor of the checksum and $ffff.
# $ffde..$ffdf => SNES checksum, an unsigned 16-bit checksum of bytes.
# $ffe0..$ffe3 => Unknown.
* # $ffc0..$ffd4 => Name of the ROM, typically in ASCII, using spaces to pad the name to 21 bytes. # $ffd5 => ROM layout,
* typically $20 for LoROM, or $21 for HiROM. Add $10 for FastROM. # $ffd6 => Cartridge type, typically $00 for ROM only, or $02
* for ROM with save-RAM. # $ffd7 => ROM size byte. # $ffd8 => RAM size byte. # $ffd9 => Country code, which selects the video in
* the emulator. Values $00, $01, $0d use NTSC. Values in range $02..$0c use PAL. Other values are invalid. # $ffda => Licensee
* code. If this value is $33, then the ROM has an extended header with ID at $ffb2..$ffb5. # $ffdb => Version number, typically
* $00. # $ffdc..$ffdd => Checksum complement, which is the bitwise-xor of the checksum and $ffff. # $ffde..$ffdf => SNES checksum,
* an unsigned 16-bit checksum of bytes. # $ffe0..$ffe3 => Unknown.
*/
info_P(PSTR("NAME 0x%04x "), (0xffc0 - offset));
for (arg1 = (0xffc0 - offset); arg1 < (0xffc0 - offset + 21); arg1++) {
@ -442,7 +441,8 @@ void shell_run(void)
break;
}
arg1 = (2 << (sram_read(0xffd7 - offset) - 1));
info_P(PSTR("ROM 0x%04x %li MBit ( %li KiB)\n"), (0xffd7 - offset), (arg1 / 128), arg1);
info_P(PSTR("ROM 0x%04x %li MBit ( %li KiB)\n"),
(0xffd7 - offset), (arg1 / 128), arg1);
arg1 = (2 << (sram_read(0xffd8 - offset) - 1));
info_P(PSTR("RAM 0x%04x %li KiB\n"), (0xffd8 - offset), arg1);
@ -455,10 +455,14 @@ void shell_run(void)
else
info_P(PSTR("Unkown 0x%02x\n"), c);
info_P(PSTR("LIC 0x%04x 0x%02x\n"), (0xffda - offset),sram_read(0xffda - offset));
info_P(PSTR("VER 0x%04x 0x%02x\n"), (0xffdb - offset),sram_read(0xffdb - offset));
info_P(PSTR("SUM1 0x%04x 0x%04x\n"), (0xffdc - offset),sram_read16_be(0xffdc - offset));
info_P(PSTR("SUM2 0x%04x 0x%04x\n"), (0xffde - offset),sram_read16_be(0xffde - offset));
info_P(PSTR("LIC 0x%04x 0x%02x\n"), (0xffda - offset),
sram_read(0xffda - offset));
info_P(PSTR("VER 0x%04x 0x%02x\n"), (0xffdb - offset),
sram_read(0xffdb - offset));
info_P(PSTR("SUM1 0x%04x 0x%04x\n"), (0xffdc - offset),
sram_read16_be(0xffdc - offset));
info_P(PSTR("SUM2 0x%04x 0x%04x\n"), (0xffde - offset),
sram_read16_be(0xffde - offset));
} else if (strcmp_P((char *) t, (PGM_P) cmdlist[CMD_SHMWR]) == 0) {
@ -488,4 +492,4 @@ void shell_run(void)
prompt();
}
#endif

View File

@ -117,12 +117,14 @@ void sreg_set(uint32_t addr)
void sram_bulk_addr_save()
{
addr_stash = addr_current;
debug_P(DEBUG_SRAM, PSTR("sram_bulk_addr_save: addr=0x%08lx\n\r"), addr_stash);
debug_P(DEBUG_SRAM, PSTR("sram_bulk_addr_save: addr=0x%08lx\n\r"),
addr_stash);
}
inline void sram_bulk_addr_restore()
{
debug_P(DEBUG_SRAM, PSTR("sram_bulk_addr_restore: addr=0x%08lx\n\r"), addr_stash);
debug_P(DEBUG_SRAM, PSTR("sram_bulk_addr_restore: addr=0x%08lx\n\r"),
addr_stash);
sram_bulk_write_start(addr_stash);
}
@ -215,7 +217,8 @@ uint8_t sram_read(uint32_t addr)
}
uint16_t sram_read16_be(uint32_t addr){
uint16_t sram_read16_be(uint32_t addr)
{
uint8_t hi = sram_read(addr);
uint8_t lo = sram_read(addr + 1);
return (hi << 8 | lo);
@ -238,7 +241,6 @@ void sram_bulk_write_start(uint32_t addr)
inline void sram_bulk_write_next(void)
{
AVR_WR_PORT &= ~(1 << AVR_WR_PIN);
addr_current++;
counter_up();
}
@ -261,7 +263,8 @@ void sram_bulk_write_end(void)
void sram_write(uint32_t addr, uint8_t data)
{
debug_P(DEBUG_SRAM_RAW, PSTR("sram_write: addr=0x%08lx data=%x\n\r"), addr, data);
debug_P(DEBUG_SRAM_RAW, PSTR("sram_write: addr=0x%08lx data=%x\n\r"), addr,
data);
avr_data_out();
@ -295,7 +298,9 @@ void sram_bulk_copy_from_buffer(uint32_t addr, uint8_t * src, uint32_t len)
uint32_t i;
uint8_t *ptr = src;
debug_P(DEBUG_SRAM, PSTR("sram_bulk_copy_from_buffer: addr=0x%08lx src=0x%p len=%li\n\r"),
debug_P(DEBUG_SRAM,
PSTR
("sram_bulk_copy_from_buffer: addr=0x%08lx src=0x%p len=%li\n\r"),
addr, src, len);
sram_bulk_write_start(addr);
for (i = addr; i < (addr + len); i++) {
@ -312,8 +317,10 @@ void sram_bulk_copy_into_buffer(uint32_t addr, uint8_t * dst, uint32_t len)
{
uint32_t i;
uint8_t *ptr = dst;
debug_P(DEBUG_SRAM, PSTR("sram_bulk_copy_into_buffer: addr=0x%08lx dst=0x%p len=%li\n\r"),
// uint8_t *ptr = dst;
debug_P(DEBUG_SRAM,
PSTR
("sram_bulk_copy_into_buffer: addr=0x%08lx dst=0x%p len=%li\n\r"),
addr, dst, len);
sram_bulk_read_start(addr);
for (i = addr; i < (addr + len); i++) {
@ -323,9 +330,11 @@ void sram_bulk_copy_into_buffer(uint32_t addr, uint8_t * dst, uint32_t len)
sram_bulk_read_end();
}
void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value){
void sram_bulk_set(uint32_t addr, uint32_t len, uint8_t value)
{
uint32_t i;
debug_P(DEBUG_SRAM, PSTR("sram_bulk_set: addr=0x%08lx len=%li\n\r"), addr,len);
debug_P(DEBUG_SRAM, PSTR("sram_bulk_set: addr=0x%08lx len=%li\n\r"), addr,
len);
sram_bulk_write_start(addr);
for (i = addr; i < (addr + len); i++) {
if (0 == i % 0xfff)
@ -335,4 +344,3 @@ void sram_bulk_set(uint32_t addr, uint32_t len,uint8_t value){
}
sram_bulk_write_end();
}

View File

@ -29,7 +29,9 @@
/* ---------------------------- PORT A ---------------------------- */
/*
* ---------------------------- PORT A ----------------------------
*/
#define AVR_DATA_PORT PORTA
#define AVR_DATA_DIR DDRA
@ -41,7 +43,9 @@
#define avr_data_out() (AVR_DATA_DIR = 0xff)
/* ---------------------------- PORT B ---------------------------- */
/*
* ---------------------------- PORT B ----------------------------
*/
#define AVR_PORT PORTB
#define AVR_DIR DDRB
@ -78,7 +82,9 @@
#define snes_irq_lo() (SNES_IRQ_PORT &= ~(1 << SNES_IRQ_PIN))
/* ---------------------------- PORT C ---------------------------- */
/*
* ---------------------------- PORT C ----------------------------
*/
#define AVR_ADDR_PORT PORTC
#define AVR_ADDR_DIR DDRC
@ -140,7 +146,9 @@
#define led_pwm_on() (LED_DIR &=~ (1 << LED_PIN))
#define led_pwm_off() (LED_DIR |= (1 << LED_PIN))
/* ---------------------------- PORT D ---------------------------- */
/*
* ---------------------------- PORT D ----------------------------
*/
#define AVR_SNES_PORT PORTD
#define AVR_SNES_DIR DDRD

View File

@ -21,7 +21,6 @@
#include <stdlib.h>
#include <stdint.h>
#include <avr/io.h>
#include <util/delay.h> /* for _delay_ms() */
#include <avr/interrupt.h>
@ -35,32 +34,32 @@
#include "requests.h"
#include "irq.h"
system_t system;
system_t my_system;
void system_init(void)
{
snes_reset_hi();
snes_reset_off();
system.reset_line = RESET_OFF;
my_system.reset_line = RESET_OFF;
snes_irq_hi();
snes_irq_off();
system.irq_line = IRQ_OFF;
my_system.irq_line = IRQ_OFF;
snes_wr_disable();
system.wr_line = WR_DISABLE;
my_system.wr_line = WR_DISABLE;
avr_bus_active();
system.bus_mode = MODE_AVR;
my_system.bus_mode = MODE_AVR;
snes_lorom();
system.rom_mode = LOROM;
my_system.rom_mode = LOROM;
system.snes_reset_count = 0;
system.avr_reset_count = 0;
my_system.snes_reset_count = 0;
my_system.avr_reset_count = 0;
system.reset_irq = RESET_IRQ_OFF;
my_system.reset_irq = RESET_IRQ_OFF;
}
@ -74,7 +73,7 @@ void system_send_snes_reset()
snes_reset_hi();
snes_reset_off();
sei();
system.snes_reset_count++;
my_system.snes_reset_count++;
}
void system_send_snes_irq()
@ -89,13 +88,13 @@ void system_send_snes_irq()
void system_snes_irq_off()
{
snes_irq_off();
system.irq_line = IRQ_OFF;
my_system.irq_line = IRQ_OFF;
}
void system_snes_irq_on()
{
snes_irq_on();
system.irq_line = IRQ_ON;
my_system.irq_line = IRQ_ON;
}
@ -103,25 +102,27 @@ void system_set_bus_avr()
{
avr_bus_active();
info_P(PSTR("Activate AVR bus\n"));
system.bus_mode = MODE_AVR;
my_system.bus_mode = MODE_AVR;
}
void system_set_wr_disable(){
void system_set_wr_disable()
{
snes_wr_disable();
system.wr_line = WR_DISABLE;
my_system.wr_line = WR_DISABLE;
info_P(PSTR("Disable SNES WR\n"));
}
void system_set_wr_enable(){
void system_set_wr_enable()
{
snes_wr_enable();
system.wr_line = WR_ENABLE;
my_system.wr_line = WR_ENABLE;
info_P(PSTR("Enable SNES WR\n"));
}
void system_set_bus_snes()
{
snes_bus_active();
system.bus_mode = MODE_SNES;
my_system.bus_mode = MODE_SNES;
info_P(PSTR("Activate SNES bus\n"));
}
@ -129,11 +130,11 @@ void system_set_rom_mode(usb_transaction_t *usb_trans)
{
if (usb_trans->req_bank_size == 0x8000) {
snes_lorom();
system.rom_mode = LOROM;
my_system.rom_mode = LOROM;
info_P(PSTR("Set SNES lorom \n"));
} else {
snes_hirom();
system.rom_mode = HIROM;
my_system.rom_mode = HIROM;
info_P(PSTR("Set SNES hirom \n"));
}
}
@ -141,7 +142,7 @@ void system_set_rom_mode(usb_transaction_t *usb_trans)
void system_set_rom_lorom()
{
snes_lorom();
system.rom_mode = LOROM;
my_system.rom_mode = LOROM;
info_P(PSTR("Set SNES lorom \n"));
}
@ -149,38 +150,43 @@ void system_set_rom_lorom()
void system_set_rom_hirom()
{
snes_hirom();
system.rom_mode = HIROM;
my_system.rom_mode = HIROM;
info_P(PSTR("Set SNES hirom \n"));
}
char* system_status_helper(uint8_t val){
char *system_status_helper(uint8_t val)
{
if (val)
return "ON";
else
return "OFF";
}
char* system_status_bus(uint8_t val){
char *system_status_bus(uint8_t val)
{
if (val)
return "SNES";
else
return "AVR";
}
char* system_status_rom(uint8_t val){
char *system_status_rom(uint8_t val)
{
if (val)
return "HIROM";
else
return "LOROM";
}
void system_status(){
info_P(PSTR("\nBus Mode %s\n"),system_status_bus(system.bus_mode));
info_P(PSTR("Rom Mode %s\n"),system_status_rom(system.rom_mode));
info_P(PSTR("Reset Line %s\n"),system_status_helper(system.reset_line));
info_P(PSTR("IRQ Line %s\n"),system_status_helper(system.irq_line));
info_P(PSTR("WR Line %s\n"),system_status_helper(system.wr_line));
info_P(PSTR("Reset IRQ %s\n"),system_status_helper(system.reset_irq));
info_P(PSTR("SNES Reset 0x%02x\n"),system.snes_reset_count);
info_P(PSTR("AVR Reset 0x%02x\n"),system.avr_reset_count);
void system_status()
{
info_P(PSTR("\nBus Mode %s\n"), system_status_bus(my_system.bus_mode));
info_P(PSTR("Rom Mode %s\n"), system_status_rom(my_system.rom_mode));
info_P(PSTR("Reset Line %s\n"),
system_status_helper(my_system.reset_line));
info_P(PSTR("IRQ Line %s\n"), system_status_helper(my_system.irq_line));
info_P(PSTR("WR Line %s\n"), system_status_helper(my_system.wr_line));
info_P(PSTR("Reset IRQ %s\n"), system_status_helper(my_system.reset_irq));
info_P(PSTR("SNES Reset 0x%02x\n"), my_system.snes_reset_count);
info_P(PSTR("AVR Reset 0x%02x\n"), my_system.avr_reset_count);
}

View File

@ -93,16 +93,20 @@ void test_non_zero_memory(uint32_t bottom_addr, uint32_t top_addr)
}
void test_memory_pattern(uint32_t bottom_addr, uint32_t top_addr, uint32_t bank_size)
void test_memory_pattern(uint32_t bottom_addr, uint32_t top_addr,
uint32_t bank_size)
{
uint32_t addr = 0;
uint8_t pattern = 0x55;
info_P(PSTR("test_memory_pattern: bottom_addr=0x%08lx top_addr=0x%08lx\n"), bottom_addr, top_addr);
info_P(PSTR("test_memory_pattern: bottom_addr=0x%08lx top_addr=0x%08lx\n"),
bottom_addr, top_addr);
sram_bulk_write_start(bottom_addr);
for (addr = bottom_addr; addr < top_addr; addr++) {
if (addr % bank_size == 0) {
pattern++;
info_P(PSTR("test_memory_pattern: write addr=0x%08lx pattern=0x%08lx\n"), addr, pattern);
info_P(PSTR
("test_memory_pattern: write addr=0x%08lx pattern=0x%08lx\n"),
addr, pattern);
}
sram_bulk_write(pattern);
}
@ -110,9 +114,12 @@ void test_memory_pattern(uint32_t bottom_addr, uint32_t top_addr, uint32_t bank_
for (addr = bottom_addr; addr < top_addr; addr += bank_size) {
info_P(PSTR("test_memory_pattern: dump bottom_addr=0x%08lx top_addr=0x%08lx\n"), addr, addr + bank_size);
info_P(PSTR
("test_memory_pattern: dump bottom_addr=0x%08lx top_addr=0x%08lx\n"),
addr, addr + bank_size);
dump_memory(addr, addr + bank_size);
info_P(PSTR("----------------------------------------------------------------\n"));
info_P(PSTR
("----------------------------------------------------------------\n"));
}
crc_check_bulk_memory((uint32_t) bottom_addr, top_addr, bank_size);
@ -128,4 +135,3 @@ void test_crc()
info_P(PSTR("test_crc: check\n"));
test_non_zero_memory(0x000000, 0x10000);
}

View File

@ -24,7 +24,6 @@
#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <avr/io.h>
#include <avr/interrupt.h> /* for sei() */
#include "debug.h"
@ -53,8 +52,7 @@ extern uint8_t snes_reset_line;
uint16_t prescaler;
uint16_t volatile second; // count seconds
ISR (SIG_OUTPUT_COMPARE1A)
ISR(TIMER1_COMPA_vect)
{
@ -89,6 +87,3 @@ uint16_t timer_stop_int(void)
uint16_t t = ((DEBOUNCE - prescaler) / DEBOUNCE) + second;
return t;
}

View File

@ -45,23 +45,14 @@ FILE uart_stdout = FDEV_SETUP_STREAM(uart_stream, NULL, _FDEV_SETUP_WRITE);
void uart_init(void)
{
UCSR0A = _BV(U2X0); /* improves baud rate error @ F_CPU = 1 MHz */
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0); /* tx/rx enable, rx complete
* intr */
UCSR0B = _BV(TXEN0) | _BV(RXEN0) | _BV(RXCIE0); /* tx/rx enable, rx complete * intr */
UBRR0L = (F_CPU / (8 * 115200UL)) - 1;
}
/*
ISR(USART0_RX_vect)
{
uint8_t c;
c = UDR0;
if (bit_is_clear(UCSR0A, FE0)) {
rxbuff = c;
intflags.rx_int = 1;
}
}
* ISR(USART0_RX_vect) { uint8_t c; c = UDR0; if (bit_is_clear(UCSR0A, FE0)) { rxbuff = c; intflags.rx_int = 1; } }
*/
void uart_putc(uint8_t c)

View File

@ -34,6 +34,3 @@ void uart_puts(const char *s);
void uart_puts_P(PGM_P s);
#endif

View File

@ -27,8 +27,7 @@
#include <stdlib.h>
#include "usbdrv.h"
#include "oddebug.h" /* This is also an example for using debug
* macros */
#include "oddebug.h" /* This is also an example for using debug macros */
#include "config.h"
#include "requests.h" /* The custom request numbers we use */
#include "uart.h"
@ -48,14 +47,17 @@ uint8_t usbFunctionWrite(uint8_t * data, uint8_t len)
uint8_t i;
if (len > usb_trans.rx_remaining) {
info_P(PSTR("ERROR:usbFunctionWrite more data than expected remain: %i len: %i\n"),
info_P(PSTR
("ERROR:usbFunctionWrite more data than expected remain: %i len: %i\n"),
usb_trans.rx_remaining, len);
len = usb_trans.rx_remaining;
}
if (usb_trans.req_state == REQ_STATUS_BULK_UPLOAD) {
usb_trans.rx_remaining -= len;
debug_P(DEBUG_USB_TRANS, PSTR("usbFunctionWrite REQ_STATUS_BULK_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n"),
debug_P(DEBUG_USB_TRANS,
PSTR
("usbFunctionWrite REQ_STATUS_BULK_UPLOAD addr: 0x%08lx len: %i rx_remaining=%i\n"),
usb_trans.req_addr, len, usb_trans.rx_remaining);
ptr = data;
i = len;
@ -73,7 +75,8 @@ uint8_t usbFunctionRead(uint8_t * data, uint8_t len)
if (len > usb_trans.tx_remaining)
len = usb_trans.tx_remaining;
usb_trans.tx_remaining -= len;
debug_P(DEBUG_USB_TRANS, PSTR("usbFunctionRead len=%i tx_remaining=%i \n"), len, usb_trans.tx_remaining);
debug_P(DEBUG_USB_TRANS, PSTR("usbFunctionRead len=%i tx_remaining=%i \n"),
len, usb_trans.tx_remaining);
for (i = 0; i < len; i++) {
*data = usb_trans.tx_buffer[len];

View File

@ -20,325 +20,287 @@
/* Name: usbconfig.h
* Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers
* Author: Christian Starkjohann
* Creation Date: 2005-04-01
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
/*
* Name: usbconfig.h Project: V-USB, virtual USB port for Atmel's(r) AVR(r) microcontrollers Author: Christian Starkjohann Creation Date:
* 2005-04-01 Tabsize: 4 Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH License: GNU GPL v2 (see License.txt), GNU GPL v3 or
* proprietary (CommercialLicense.txt) This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
*/
#ifndef __usbconfig_h_included__
#define __usbconfig_h_included__
/*
General Description:
This file is an example configuration (with inline documentation) for the USB
driver. It configures V-USB for USB D+ connected to Port D bit 2 (which is
also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may
wire the lines to any other port, as long as D+ is also wired to INT0 (or any
other hardware interrupt, as long as it is the highest level interrupt, see
section at the end of this file).
* General Description: This file is an example configuration (with inline documentation) for the USB driver. It configures V-USB for USB
* D+ connected to Port D bit 2 (which is also hardware interrupt 0 on many devices) and USB D- to Port D bit 4. You may wire the lines to
* any other port, as long as D+ is also wired to INT0 (or any other hardware interrupt, as long as it is the highest level interrupt, see
* section at the end of this file).
*/
/* ---------------------------- Hardware Config ---------------------------- */
/*
* ---------------------------- Hardware Config ----------------------------
*/
#define USB_CFG_IOPORTNAME D
/* This is the port where the USB bus is connected. When you configure it to
* "B", the registers PORTB, PINB and DDRB will be used.
/*
* This is the port where the USB bus is connected. When you configure it to "B", the registers PORTB, PINB and DDRB will be used.
*/
#define USB_CFG_DMINUS_BIT 4
/* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected.
* This may be any bit in the port.
/*
* This is the bit number in USB_CFG_IOPORT where the USB D- line is connected. This may be any bit in the port.
*/
#define USB_CFG_DPLUS_BIT 2
/* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected.
* This may be any bit in the port. Please note that D+ must also be connected
* to interrupt pin INT0! [You can also use other interrupts, see section
* "Optional MCU Description" below, or you can connect D- to the interrupt, as
* it is required if you use the USB_COUNT_SOF feature. If you use D- for the
* interrupt, the USB interrupt will also be triggered at Start-Of-Frame
* markers every millisecond.]
/*
* This is the bit number in USB_CFG_IOPORT where the USB D+ line is connected. This may be any bit in the port. Please note that D+ must
* also be connected to interrupt pin INT0! [You can also use other interrupts, see section "Optional MCU Description" below, or you can
* connect D- to the interrupt, as it is required if you use the USB_COUNT_SOF feature. If you use D- for the interrupt, the USB interrupt
* will also be triggered at Start-Of-Frame markers every millisecond.]
*/
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
* 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no
* crystal, they tolerate +/- 1% deviation from the nominal frequency. All
* other rates require a precision of 2000 ppm and thus a crystal!
* Default if not specified: 12 MHz
/*
* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000, 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the
* code require no crystal, they tolerate +/- 1% deviation from the nominal frequency. All other rates require a precision of 2000 ppm and
* thus a crystal! Default if not specified: 12 MHz
*/
#define USB_CFG_CHECK_CRC 0
/* Define this to 1 if you want that the driver checks integrity of incoming
* data packets (CRC checks). CRC checks cost quite a bit of code size and are
* currently only available for 18 MHz crystal clock. You must choose
* USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
/*
* Define this to 1 if you want that the driver checks integrity of incoming data packets (CRC checks). CRC checks cost quite a bit of code
* size and are currently only available for 18 MHz crystal clock. You must choose USB_CFG_CLOCK_KHZ = 18000 if you enable this option.
*/
/* ----------------------- Optional Hardware Config ------------------------ */
/*
* ----------------------- Optional Hardware Config ------------------------
*/
// #define USB_CFG_PULLUP_IOPORTNAME D
/* If you connect the 1.5k pullup resistor from D- to a port pin instead of
* V+, you can connect and disconnect the device from firmware by calling
* the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h).
* This constant defines the port on which the pullup resistor is connected.
/*
* If you connect the 1.5k pullup resistor from D- to a port pin instead of V+, you can connect and disconnect the device from firmware by
* calling the macros usbDeviceConnect() and usbDeviceDisconnect() (see usbdrv.h). This constant defines the port on which the pullup
* resistor is connected.
*/
// #define USB_CFG_PULLUP_BIT 6
/* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined
* above) where the 1.5k pullup resistor is connected. See description
* above for details.
/*
* This constant defines the bit number in USB_CFG_PULLUP_IOPORT (defined above) where the 1.5k pullup resistor is connected. See
* description above for details.
*/
/* --------------------------- Functional Range ---------------------------- */
/*
* --------------------------- Functional Range ----------------------------
*/
#define USB_CFG_HAVE_INTRIN_ENDPOINT 0
/* Define this to 1 if you want to compile a version with two endpoints: The
* default control endpoint 0 and an interrupt-in endpoint (any other endpoint
* number).
/*
* Define this to 1 if you want to compile a version with two endpoints: The default control endpoint 0 and an interrupt-in endpoint (any
* other endpoint number).
*/
#define USB_CFG_HAVE_INTRIN_ENDPOINT3 0
/* Define this to 1 if you want to compile a version with three endpoints: The
* default control endpoint 0, an interrupt-in endpoint 3 (or the number
* configured below) and a catch-all default interrupt-in endpoint as above.
* You must also define USB_CFG_HAVE_INTRIN_ENDPOINT to 1 for this feature.
/*
* Define this to 1 if you want to compile a version with three endpoints: The default control endpoint 0, an interrupt-in endpoint 3 (or
* the number configured below) and a catch-all default interrupt-in endpoint as above. You must also define USB_CFG_HAVE_INTRIN_ENDPOINT
* to 1 for this feature.
*/
#define USB_CFG_EP3_NUMBER 3
/* If the so-called endpoint 3 is used, it can now be configured to any other
* endpoint number (except 0) with this macro. Default if undefined is 3.
/*
* If the so-called endpoint 3 is used, it can now be configured to any other endpoint number (except 0) with this macro. Default if
* undefined is 3.
*/
/* #define USB_INITIAL_DATATOKEN USBPID_DATA1 */
/* The above macro defines the startup condition for data toggling on the
* interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1.
* Since the token is toggled BEFORE sending any data, the first packet is
* sent with the oposite value of this configuration!
/*
* #define USB_INITIAL_DATATOKEN USBPID_DATA1
*/
/*
* The above macro defines the startup condition for data toggling on the interrupt/bulk endpoints 1 and 3. Defaults to USBPID_DATA1. Since
* the token is toggled BEFORE sending any data, the first packet is sent with the oposite value of this configuration!
*/
#define USB_CFG_IMPLEMENT_HALT 0
/* Define this to 1 if you also want to implement the ENDPOINT_HALT feature
* for endpoint 1 (interrupt endpoint). Although you may not need this feature,
* it is required by the standard. We have made it a config option because it
* bloats the code considerably.
/*
* Define this to 1 if you also want to implement the ENDPOINT_HALT feature for endpoint 1 (interrupt endpoint). Although you may not need
* this feature, it is required by the standard. We have made it a config option because it bloats the code considerably.
*/
#define USB_CFG_SUPPRESS_INTR_CODE 1
/* Define this to 1 if you want to declare interrupt-in endpoints, but don't
* want to send any data over them. If this macro is defined to 1, functions
* usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if
* you need the interrupt-in endpoints in order to comply to an interface
* (e.g. HID), but never want to send any data. This option saves a couple
* of bytes in flash memory and the transmit buffers in RAM.
/*
* Define this to 1 if you want to declare interrupt-in endpoints, but don't want to send any data over them. If this macro is defined to
* 1, functions usbSetInterrupt() and usbSetInterrupt3() are omitted. This is useful if you need the interrupt-in endpoints in order to
* comply to an interface (e.g. HID), but never want to send any data. This option saves a couple of bytes in flash memory and the transmit
* buffers in RAM.
*/
#define USB_CFG_INTR_POLL_INTERVAL 20
/* If you compile a version with endpoint 1 (interrupt-in), this is the poll
* interval. The value is in milliseconds and must not be less than 10 ms for
* low speed devices.
/*
* If you compile a version with endpoint 1 (interrupt-in), this is the poll interval. The value is in milliseconds and must not be less
* than 10 ms for low speed devices.
*/
#define USB_CFG_IS_SELF_POWERED 0
/* Define this to 1 if the device has its own power supply. Set it to 0 if the
* device is powered from the USB bus.
/*
* Define this to 1 if the device has its own power supply. Set it to 0 if the device is powered from the USB bus.
*/
#define USB_CFG_MAX_BUS_POWER 300
/* Set this variable to the maximum USB bus power consumption of your device.
* The value is in milliamperes. [It will be divided by two since USB
* communicates power requirements in units of 2 mA.]
/*
* Set this variable to the maximum USB bus power consumption of your device. The value is in milliamperes. [It will be divided by two
* since USB communicates power requirements in units of 2 mA.]
*/
#define USB_CFG_IMPLEMENT_FN_WRITE 1
/* Set this to 1 if you want usbFunctionWrite() to be called for control-out
* transfers. Set it to 0 if you don't need it and want to save a couple of
* bytes.
/*
* Set this to 1 if you want usbFunctionWrite() to be called for control-out transfers. Set it to 0 if you don't need it and want to save a
* couple of bytes.
*/
#define USB_CFG_IMPLEMENT_FN_READ 0
/* Set this to 1 if you need to send control replies which are generated
* "on the fly" when usbFunctionRead() is called. If you only want to send
* data from a static buffer, set it to 0 and return the data from
* usbFunctionSetup(). This saves a couple of bytes.
/*
* Set this to 1 if you need to send control replies which are generated "on the fly" when usbFunctionRead() is called. If you only want to
* send data from a static buffer, set it to 0 and return the data from usbFunctionSetup(). This saves a couple of bytes.
*/
#define USB_CFG_IMPLEMENT_FN_WRITEOUT 0
/* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints.
* You must implement the function usbFunctionWriteOut() which receives all
* interrupt/bulk data sent to any endpoint other than 0. The endpoint number
* can be found in 'usbRxToken'.
/*
* Define this to 1 if you want to use interrupt-out (or bulk out) endpoints. You must implement the function usbFunctionWriteOut() which
* receives all interrupt/bulk data sent to any endpoint other than 0. The endpoint number can be found in 'usbRxToken'.
*/
#define USB_CFG_HAVE_FLOWCONTROL 0
/* Define this to 1 if you want flowcontrol over USB data. See the definition
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
* usbdrv.h.
/*
* Define this to 1 if you want flowcontrol over USB data. See the definition of the macros usbDisableAllRequests() and
* usbEnableAllRequests() in usbdrv.h.
*/
#define USB_CFG_LONG_TRANSFERS 0
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
* in a single control-in or control-out transfer. Note that the capability
* for long transfers increases the driver size.
/*
* Define this to 1 if you want to send/receive blocks of more than 254 bytes in a single control-in or control-out transfer. Note that the
* capability for long transfers increases the driver size.
*/
/* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED(); */
/* This macro is a hook if you want to do unconventional things. If it is
* defined, it's inserted at the beginning of received message processing.
* If you eat the received message and don't want default processing to
* proceed, do a return after doing your things. One possible application
* (besides debugging) is to flash a status LED on each packet.
/*
* #define USB_RX_USER_HOOK(data, len) if(usbRxToken == (uchar)USBPID_SETUP) blinkLED();
*/
/* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();} */
/* This macro is a hook if you need to know when an USB RESET occurs. It has
* one parameter which distinguishes between the start of RESET state and its
* end.
/*
* This macro is a hook if you want to do unconventional things. If it is defined, it's inserted at the beginning of received message
* processing. If you eat the received message and don't want default processing to proceed, do a return after doing your things. One
* possible application (besides debugging) is to flash a status LED on each packet.
*/
/* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned(); */
/* This macro (if defined) is executed when a USB SET_ADDRESS request was
* received.
/*
* #define USB_RESET_HOOK(resetStarts) if(!resetStarts){hadUsbReset();}
*/
/*
* This macro is a hook if you need to know when an USB RESET occurs. It has one parameter which distinguishes between the start of RESET
* state and its end.
*/
/*
* #define USB_SET_ADDRESS_HOOK() hadAddressAssigned();
*/
/*
* This macro (if defined) is executed when a USB SET_ADDRESS request was received.
*/
#define USB_COUNT_SOF 0
/* define this macro to 1 if you need the global variable "usbSofCount" which
* counts SOF packets. This feature requires that the hardware interrupt is
* connected to D- instead of D+.
/*
* define this macro to 1 if you need the global variable "usbSofCount" which counts SOF packets. This feature requires that the hardware
* interrupt is connected to D- instead of D+.
*/
/* #ifdef __ASSEMBLER__
* macro myAssemblerMacro
* in YL, TCNT0
* sts timer0Snapshot, YL
* endm
* #endif
* #define USB_SOF_HOOK myAssemblerMacro
* This macro (if defined) is executed in the assembler module when a
* Start Of Frame condition is detected. It is recommended to define it to
* the name of an assembler macro which is defined here as well so that more
* than one assembler instruction can be used. The macro may use the register
* YL and modify SREG. If it lasts longer than a couple of cycles, USB messages
* immediately after an SOF pulse may be lost and must be retried by the host.
* What can you do with this hook? Since the SOF signal occurs exactly every
* 1 ms (unless the host is in sleep mode), you can use it to tune OSCCAL in
* designs running on the internal RC oscillator.
* Please note that Start Of Frame detection works only if D- is wired to the
* interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
/*
* #ifdef __ASSEMBLER__ macro myAssemblerMacro in YL, TCNT0 sts timer0Snapshot, YL endm #endif #define USB_SOF_HOOK myAssemblerMacro This
* macro (if defined) is executed in the assembler module when a Start Of Frame condition is detected. It is recommended to define it to
* the name of an assembler macro which is defined here as well so that more than one assembler instruction can be used. The macro may use
* the register YL and modify SREG. If it lasts longer than a couple of cycles, USB messages immediately after an SOF pulse may be lost and
* must be retried by the host. What can you do with this hook? Since the SOF signal occurs exactly every 1 ms (unless the host is in sleep
* mode), you can use it to tune OSCCAL in designs running on the internal RC oscillator. Please note that Start Of Frame detection works
* only if D- is wired to the interrupt, not D+. THIS IS DIFFERENT THAN MOST EXAMPLES!
*/
#define USB_CFG_CHECK_DATA_TOGGLING 0
/* define this macro to 1 if you want to filter out duplicate data packets
* sent by the host. Duplicates occur only as a consequence of communication
* errors, when the host does not receive an ACK. Please note that you need to
* implement the filtering yourself in usbFunctionWriteOut() and
* usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable
* for each control- and out-endpoint to check for duplicate packets.
/*
* define this macro to 1 if you want to filter out duplicate data packets sent by the host. Duplicates occur only as a consequence of
* communication errors, when the host does not receive an ACK. Please note that you need to implement the filtering yourself in
* usbFunctionWriteOut() and usbFunctionWrite(). Use the global usbCurrentDataToken and a static variable for each control- and
* out-endpoint to check for duplicate packets.
*/
#define USB_CFG_HAVE_MEASURE_FRAME_LENGTH 0
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
/*
* define this macro to 1 if you want the function usbMeasureFrameLength() compiled in. This function can be used to calibrate the AVR's RC
* oscillator.
*/
/* -------------------------- Device Description --------------------------- */
/*
* -------------------------- Device Description ---------------------------
*/
#define USB_CFG_VENDOR_ID 0xc0, 0x16
/* USB vendor ID for the device, low byte first. If you have registered your
* own Vendor ID, define it here. Otherwise you use one of obdev's free shared
* VID/PID pairs. Be sure to read USBID-License.txt for rules!
/*
* USB vendor ID for the device, low byte first. If you have registered your own Vendor ID, define it here. Otherwise you use one of
* obdev's free shared VID/PID pairs. Be sure to read USBID-License.txt for rules!
*/
#define USB_CFG_DEVICE_ID 0xdd, 0x05
/* This is the ID of the product, low byte first. It is interpreted in the
* scope of the vendor ID. If you have registered your own VID with usb.org
* or if you have licensed a PID from somebody else, define it here. Otherwise
* you use obdev's free shared VID/PID pair. Be sure to read the rules in
* USBID-License.txt!
/*
* This is the ID of the product, low byte first. It is interpreted in the scope of the vendor ID. If you have registered your own VID with
* usb.org or if you have licensed a PID from somebody else, define it here. Otherwise you use obdev's free shared VID/PID pair. Be sure to
* read the rules in USBID-License.txt!
*/
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
/* Version number of the device: Minor number first, then major number.
/*
* Version number of the device: Minor number first, then major number.
*/
#define USB_CFG_VENDOR_NAME 'o', 'p', 't', 'i', 'x', 'x', '.', 'o', 'r', 'g'
#define USB_CFG_VENDOR_NAME_LEN 10
/* These two values define the vendor name returned by the USB device. The name
* must be given as a list of characters under single quotes. The characters
* are interpreted as Unicode (UTF-16) entities.
* If you don't want a vendor name string, undefine these macros.
* ALWAYS define a vendor name containing your Internet domain name if you use
* obdev's free shared VID/PID pair. See the file USBID-License.txt for
* details.
/*
* These two values define the vendor name returned by the USB device. The name must be given as a list of characters under single quotes.
* The characters are interpreted as Unicode (UTF-16) entities. If you don't want a vendor name string, undefine these macros. ALWAYS
* define a vendor name containing your Internet domain name if you use obdev's free shared VID/PID pair. See the file USBID-License.txt
* for details.
*/
#define USB_CFG_DEVICE_NAME 'Q', 'U', 'I', 'C', 'K', 'D', 'E', 'V', '1', '6'
#define USB_CFG_DEVICE_NAME_LEN 10
/* Same as above for the device name. If you don't want a device name, undefine
* the macros. See the file USBID-License.txt before you assign a name if you
* use a shared VID/PID.
/*
* Same as above for the device name. If you don't want a device name, undefine the macros. See the file USBID-License.txt before you
* assign a name if you use a shared VID/PID.
*/
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
/* Same as above for the serial number. If you don't want a serial number,
* undefine the macros.
* It may be useful to provide the serial number through other means than at
* compile time. See the section about descriptor properties below for how
* to fine tune control over USB descriptors such as the string descriptor
* for the serial number.
/*
* #define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e'
*/
/*
* #define USB_CFG_SERIAL_NUMBER_LEN 0
*/
/*
* Same as above for the serial number. If you don't want a serial number, undefine the macros. It may be useful to provide the serial
* number through other means than at compile time. See the section about descriptor properties below for how to fine tune control over USB
* descriptors such as the string descriptor for the serial number.
*/
#define USB_CFG_DEVICE_CLASS 0xff /* set to 0 if deferred to interface */
#define USB_CFG_DEVICE_SUBCLASS 0
/* See USB specification if you want to conform to an existing device class.
* Class 0xff is "vendor specific".
/*
* See USB specification if you want to conform to an existing device class. Class 0xff is "vendor specific".
*/
#define USB_CFG_INTERFACE_CLASS 0 /* define class here if not at device level */
#define USB_CFG_INTERFACE_SUBCLASS 0
#define USB_CFG_INTERFACE_PROTOCOL 0
/* See USB specification if you want to conform to an existing device class or
* protocol. The following classes must be set at interface level:
* HID class is 3, no subclass and protocol required (but may be useful!)
* CDC class is 2, use subclass 2 and protocol 1 for ACM
/*
* See USB specification if you want to conform to an existing device class or protocol. The following classes must be set at interface
* level: HID class is 3, no subclass and protocol required (but may be useful!) CDC class is 2, use subclass 2 and protocol 1 for ACM
*/
#define USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH 0
/* Define this to the length of the HID report descriptor, if you implement
* an HID device. Otherwise don't define it or define it to 0.
* If you use this define, you must add a PROGMEM character array named
* "usbHidReportDescriptor" to your code which contains the report descriptor.
* Don't forget to keep the array and this define in sync!
/*
* Define this to the length of the HID report descriptor, if you implement an HID device. Otherwise don't define it or define it to 0. If
* you use this define, you must add a PROGMEM character array named "usbHidReportDescriptor" to your code which contains the report
* descriptor. Don't forget to keep the array and this define in sync!
*/
/* #define USB_PUBLIC static */
/* Use the define above if you #include usbdrv.c instead of linking against it.
* This technique saves a couple of bytes in flash memory.
/*
* #define USB_PUBLIC static
*/
/*
* Use the define above if you #include usbdrv.c instead of linking against it. This technique saves a couple of bytes in flash memory.
*/
/* ------------------- Fine Control over USB Descriptors ------------------- */
/* If you don't want to use the driver's default USB descriptors, you can
* provide our own. These can be provided as (1) fixed length static data in
* flash memory, (2) fixed length static data in RAM or (3) dynamically at
* runtime in the function usbFunctionDescriptor(). See usbdrv.h for more
* information about this function.
* Descriptor handling is configured through the descriptor's properties. If
* no properties are defined or if they are 0, the default descriptor is used.
* Possible properties are:
* + USB_PROP_IS_DYNAMIC: The data for the descriptor should be fetched
* at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is
* used, the data is in FLASH by default. Add property USB_PROP_IS_RAM if
* you want RAM pointers.
* + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or found
* in static memory is in RAM, not in flash memory.
* + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash),
* the driver must know the descriptor's length. The descriptor itself is
* found at the address of a well known identifier (see below).
* List of static descriptor names (must be declared PROGMEM if in flash):
* char usbDescriptorDevice[];
* char usbDescriptorConfiguration[];
* char usbDescriptorHidReport[];
* char usbDescriptorString0[];
* int usbDescriptorStringVendor[];
* int usbDescriptorStringDevice[];
* int usbDescriptorStringSerialNumber[];
* Other descriptors can't be provided statically, they must be provided
* dynamically at runtime.
*
* Descriptor properties are or-ed or added together, e.g.:
* #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18))
*
* The following descriptors are defined:
* USB_CFG_DESCR_PROPS_DEVICE
* USB_CFG_DESCR_PROPS_CONFIGURATION
* USB_CFG_DESCR_PROPS_STRINGS
* USB_CFG_DESCR_PROPS_STRING_0
* USB_CFG_DESCR_PROPS_STRING_VENDOR
* USB_CFG_DESCR_PROPS_STRING_PRODUCT
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
* USB_CFG_DESCR_PROPS_HID
* USB_CFG_DESCR_PROPS_HID_REPORT
* USB_CFG_DESCR_PROPS_UNKNOWN (for all descriptors not handled by the driver)
*
* Note about string descriptors: String descriptors are not just strings, they
* are Unicode strings prefixed with a 2 byte header. Example:
* int serialNumberDescriptor[] = {
* USB_STRING_DESCRIPTOR_HEADER(6),
* 'S', 'e', 'r', 'i', 'a', 'l'
/*
* ------------------- Fine Control over USB Descriptors -------------------
*/
/*
* If you don't want to use the driver's default USB descriptors, you can provide our own. These can be provided as (1) fixed length static
* data in flash memory, (2) fixed length static data in RAM or (3) dynamically at runtime in the function usbFunctionDescriptor(). See
* usbdrv.h for more information about this function. Descriptor handling is configured through the descriptor's properties. If no
* properties are defined or if they are 0, the default descriptor is used. Possible properties are: + USB_PROP_IS_DYNAMIC: The data for
* the descriptor should be fetched at runtime via usbFunctionDescriptor(). If the usbMsgPtr mechanism is used, the data is in FLASH by
* default. Add property USB_PROP_IS_RAM if you want RAM pointers. + USB_PROP_IS_RAM: The data returned by usbFunctionDescriptor() or
* found in static memory is in RAM, not in flash memory. + USB_PROP_LENGTH(len): If the data is in static memory (RAM or flash), the
* driver must know the descriptor's length. The descriptor itself is found at the address of a well known identifier (see below). List of
* static descriptor names (must be declared PROGMEM if in flash): char usbDescriptorDevice[]; char usbDescriptorConfiguration[]; char
* usbDescriptorHidReport[]; char usbDescriptorString0[]; int usbDescriptorStringVendor[]; int usbDescriptorStringDevice[]; int
* usbDescriptorStringSerialNumber[]; Other descriptors can't be provided statically, they must be provided dynamically at runtime.
* Descriptor properties are or-ed or added together, e.g.: #define USB_CFG_DESCR_PROPS_DEVICE (USB_PROP_IS_RAM | USB_PROP_LENGTH(18)) The
* following descriptors are defined: USB_CFG_DESCR_PROPS_DEVICE USB_CFG_DESCR_PROPS_CONFIGURATION USB_CFG_DESCR_PROPS_STRINGS
* USB_CFG_DESCR_PROPS_STRING_0 USB_CFG_DESCR_PROPS_STRING_VENDOR USB_CFG_DESCR_PROPS_STRING_PRODUCT
* USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER USB_CFG_DESCR_PROPS_HID USB_CFG_DESCR_PROPS_HID_REPORT USB_CFG_DESCR_PROPS_UNKNOWN (for all
* descriptors not handled by the driver) Note about string descriptors: String descriptors are not just strings, they are Unicode strings
* prefixed with a 2 byte header. Example: int serialNumberDescriptor[] = { USB_STRING_DESCRIPTOR_HEADER(6), 'S', 'e', 'r', 'i', 'a', 'l'
* };
*/
@ -353,21 +315,38 @@ section at the end of this file).
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
/* ----------------------- Optional MCU Description ------------------------ */
/* The following configurations have working defaults in usbdrv.h. You
* usually don't need to set them explicitly. Only if you want to run
* the driver on a device which is not yet supported or with a compiler
* which is not fully supported (such as IAR C) or if you use a differnt
* interrupt than INT0, you may have to define some of these.
/*
* ----------------------- Optional MCU Description ------------------------
*/
/*
* The following configurations have working defaults in usbdrv.h. You usually don't need to set them explicitly. Only if you want to run
* the driver on a device which is not yet supported or with a compiler which is not fully supported (such as IAR C) or if you use a
* differnt interrupt than INT0, you may have to define some of these.
*/
/*
* #define USB_INTR_CFG MCUCR
*/
/*
* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01))
*/
/*
* #define USB_INTR_CFG_CLR 0
*/
/*
* #define USB_INTR_ENABLE GIMSK
*/
/*
* #define USB_INTR_ENABLE_BIT INT0
*/
/*
* #define USB_INTR_PENDING GIFR
*/
/*
* #define USB_INTR_PENDING_BIT INTF0
*/
/*
* #define USB_INTR_VECTOR SIG_INTERRUPT0
*/
/* #define USB_INTR_CFG MCUCR */
/* #define USB_INTR_CFG_SET ((1 << ISC00) | (1 << ISC01)) */
/* #define USB_INTR_CFG_CLR 0 */
/* #define USB_INTR_ENABLE GIMSK */
/* #define USB_INTR_ENABLE_BIT INT0 */
/* #define USB_INTR_PENDING GIFR */
/* #define USB_INTR_PENDING_BIT INTF0 */
/* #define USB_INTR_VECTOR SIG_INTERRUPT0 */
#endif /* __usbconfig_h_included__ */

View File

@ -275,3 +275,55 @@ Scroll down to the bottom to see the most recent changes.
background of USB ID registration clearer.
* Release 2009-04-15
- Changed CommercialLicense.txt to reflect the new range of PIDs from
Jason Kotzin.
- Removed USBID-License.txt in favor of USB-IDs-for-free.txt and
USB-ID-FAQ.txt
- Fixed a bug in the 12.8 MHz module: End Of Packet decection was made in
the center between bit 0 and 1 of each byte. This is where the data lines
are expected to change and the sampled data may therefore be nonsense.
We therefore check EOP ONLY if bits 0 AND 1 have both been read as 0 on D-.
- Fixed a bitstuffing problem in the 16 MHz module: If bit 6 was stuffed,
the unstuffing code in the receiver routine was 1 cycle too long. If
multiple bytes had the unstuffing in bit 6, the error summed up until the
receiver was out of sync.
- Included option for faster CRC routine.
Thanks to Slawomir Fras (BoskiDialer) for this code!
- Updated bits in Configuration Descriptor's bmAttributes according to
USB 1.1 (in particular bit 7, it is a must-be-set bit now).
* Release 2009-08-22
- Moved first DBG1() after odDebugInit() in all examples.
- Use vector INT0_vect instead of SIG_INTERRUPT0 if defined. This makes
V-USB compatible with the new "p" suffix devices (e.g. ATMega328p).
- USB_CFG_CLOCK_KHZ setting is now required in usbconfig.h (no default any
more).
- New option USB_CFG_DRIVER_FLASH_PAGE allows boot loaders on devices with
more than 64 kB flash.
- Built-in configuration descriptor allows custom definition for second
endpoint now.
* Release 2010-07-15
- Fixed bug in usbDriverSetup() which prevented descriptor sizes above 255
bytes.
- Avoid a compiler warning for unused parameter in usbHandleResetHook() when
compiler option -Wextra is enabled.
- Fixed wrong hex value for some IDs in USB-IDs-for-free.txt.
- Keep a define for USBATTR_BUSPOWER, although the flag does not exist
in USB 1.1 any more. Set it to 0. This is for backward compatibility.
* Release 2012-01-09
- Define a separate (defined) type for usbMsgPtr so that projects using a
tiny memory model can define it to an 8 bit type in usbconfig.h. This
change also saves a couple of bytes when using a scalar 16 bit type.
- Inserted "const" keyword for all PROGMEM declarations because new GCC
requires it.
- Fixed problem with dependence of usbportability.h on usbconfig.h. This
problem occurred with IAR CC only.
- Prepared repository for github.com.
* Release 2012-12-06

View File

@ -1,5 +1,5 @@
V-USB Driver Software License Agreement
Version 2009-04-14
Version 2012-07-09
THIS LICENSE AGREEMENT GRANTS YOU CERTAIN RIGHTS IN A SOFTWARE. YOU CAN
ENTER INTO THIS AGREEMENT AND ACQUIRE THE RIGHTS OUTLINED BELOW BY PAYING
@ -32,13 +32,22 @@ product(s), restricted by the limitations in section 3 below.
2.3 Modifications. OBJECTIVE DEVELOPMENT grants you the right to modify
the source code and your copy of V-USB according to your needs.
2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB Product
ID(s), sent to you in e-mail. These Product IDs are reserved exclusively for
you. They have been obtained from Wouter van Ooijen (www.voti.nl), who has
reserved the Vendor ID 5824 (decimal) at the USB Implementers Forum, Inc.
(www.usb.org). This mechanism ensures that there are no Product ID conflicts,
but you cannot become USB certified (enter into the USB-IF Trademark License
Agreement) as you would need your own Vendor ID for that.
2.4 USB IDs. OBJECTIVE DEVELOPMENT furnishes you with one or two USB
Product ID(s), sent to you in e-mail. These Product IDs are reserved
exclusively for you. OBJECTIVE DEVELOPMENT has obtained USB Product ID
ranges under the Vendor ID 5824 from Wouter van Ooijen (Van Ooijen
Technische Informatica, www.voti.nl) and under the Vendor ID 8352 from
Jason Kotzin (now flirc.tv, Inc.). Both owners of the Vendor IDs have
obtained these IDs from the USB Implementers Forum, Inc. (www.usb.org).
OBJECTIVE DEVELOPMENT disclaims all liability which might arise from the
assignment of USB IDs.
2.5 USB Certification. Although not part of this agreement, we want to make
it clear that you cannot become USB certified when you use V-USB or a USB
Product ID assigned by OBJECTIVE DEVELOPMENT. AVR microcontrollers don't
meet the electrical specifications required by the USB specification and
the USB Implementers Forum certifies only members who bought a Vendor ID of
their own.
3 LICENSE RESTRICTIONS

View File

@ -39,8 +39,8 @@ The driver consists of the following files:
with IAR's tools.
License.txt ............ Open Source license for this driver.
CommercialLicense.txt .. Optional commercial license for this driver.
USBID-License.txt ...... Terms and conditions for using particular USB ID
values for particular purposes.
USB-ID-FAQ.txt ......... General infos about USB Product- and Vendor-IDs.
USB-IDs-for-free.txt ... List and terms of use for free shared PIDs.
(*) ... These files should be linked to your project.
@ -49,8 +49,7 @@ CPU CORE CLOCK FREQUENCY
========================
We supply assembler modules for clock frequencies of 12 MHz, 12.8 MHz, 15 MHz,
16 MHz, 16.5 MHz 18 MHz and 20 MHz. Other clock rates are not supported. The
actual clock rate must be configured in usbdrv.h unless you use the default
12 MHz.
actual clock rate must be configured in usbconfig.h.
12 MHz Clock
This is the traditional clock rate of V-USB because it's the lowest clock
@ -105,7 +104,7 @@ can assign PIDs at will.
Since an entry level cost of 1,500 USD is too high for most small companies
and hobbyists, we provide some VID/PID pairs for free. See the file
USBID-License.txt for details.
USB-IDs-for-free.txt for details.
Objective Development also has some license offerings which include product
IDs. See http://www.obdev.at/vusb/ for details.
@ -114,13 +113,28 @@ IDs. See http://www.obdev.at/vusb/ for details.
DEVELOPMENT SYSTEM
==================
This driver has been developed and optimized for the GNU compiler version 3
(gcc 3). It does work well with gcc 4, but with bigger code size. We recommend
that you use the GNU compiler suite because it is freely available. V-USB
has also been ported to the IAR compiler and assembler. It has been tested
with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the "small" and "tiny"
memory model. Not every release is tested with IAR CC and the driver may
therefore fail to compile with IAR. Please note that gcc is more efficient for
usbdrv.c because this module has been deliberately optimized for gcc.
and 4. We recommend that you use the GNU compiler suite because it is freely
available. V-USB has also been ported to the IAR compiler and assembler. It
has been tested with IAR 4.10B/W32 and 4.12A/W32 on an ATmega8 with the
"small" and "tiny" memory model. Not every release is tested with IAR CC and
the driver may therefore fail to compile with IAR. Please note that gcc is
more efficient for usbdrv.c because this module has been deliberately
optimized for gcc.
Gcc version 3 produces smaller code than version 4 due to new optimizing
capabilities which don't always improve things on 8 bit CPUs. The code size
generated by gcc 4 can be reduced with the compiler options
-fno-move-loop-invariants, -fno-tree-scev-cprop and
-fno-inline-small-functions in addition to -Os. On devices with more than
8k of flash memory, we also recommend the linker option --relax (written as
-Wl,--relax for gcc) to convert absolute calls into relative where possible.
For more information about optimizing options see:
http://www.tty1.net/blog/2008-04-29-avr-gcc-optimisations_en.html
These optimizations are good for gcc 4.x. Version 3.x of gcc does not support
most of these options and produces good code anyway.
USING V-USB FOR FREE

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id$
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: oddebug.c 692 2008-11-07 15:07:40Z cs $
*/
#include "oddebug.h"

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: oddebug.h 692 2008-11-07 15:07:40Z cs $
*/
#ifndef __oddebug_h_included__

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbconfig-prototype.h 740 2009-04-13 18:23:31Z cs $
*/
#ifndef __usbconfig_h_included__
@ -45,10 +44,12 @@ section at the end of this file).
*/
#define USB_CFG_CLOCK_KHZ (F_CPU/1000)
/* Clock rate of the AVR in kHz. Legal values are 12000, 12800, 15000, 16000,
* 16500 and 20000. The 12.8 MHz and 16.5 MHz versions of the code require no
* crystal, they tolerate +/- 1% deviation from the nominal frequency. All
* other rates require a precision of 2000 ppm and thus a crystal!
* Default if not specified: 12 MHz
* 16500, 18000 and 20000. The 12.8 MHz and 16.5 MHz versions of the code
* require no crystal, they tolerate +/- 1% deviation from the nominal
* frequency. All other rates require a precision of 2000 ppm and thus a
* crystal!
* Since F_CPU should be defined to your actual clock rate anyway, you should
* not need to modify this setting.
*/
#define USB_CFG_CHECK_CRC 0
/* Define this to 1 if you want that the driver checks integrity of incoming
@ -144,6 +145,11 @@ section at the end of this file).
* of the macros usbDisableAllRequests() and usbEnableAllRequests() in
* usbdrv.h.
*/
#define USB_CFG_DRIVER_FLASH_PAGE 0
/* If the device has more than 64 kBytes of flash, define this to the 64 k page
* where the driver's constants (descriptors) are located. Or in other words:
* Define this to 1 for boot loaders on the ATMega128.
*/
#define USB_CFG_LONG_TRANSFERS 0
/* Define this to 1 if you want to send/receive blocks of more than 254 bytes
* in a single control-in or control-out transfer. Note that the capability
@ -201,24 +207,36 @@ section at the end of this file).
/* define this macro to 1 if you want the function usbMeasureFrameLength()
* compiled in. This function can be used to calibrate the AVR's RC oscillator.
*/
#define USB_USE_FAST_CRC 0
/* The assembler module has two implementations for the CRC algorithm. One is
* faster, the other is smaller. This CRC routine is only used for transmitted
* messages where timing is not critical. The faster routine needs 31 cycles
* per byte while the smaller one needs 61 to 69 cycles. The faster routine
* may be worth the 32 bytes bigger code size if you transmit lots of data and
* run the AVR close to its limit.
*/
/* -------------------------- Device Description --------------------------- */
#define USB_CFG_VENDOR_ID 0xc0, 0x16
#define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
/* USB vendor ID for the device, low byte first. If you have registered your
* own Vendor ID, define it here. Otherwise you use one of obdev's free shared
* VID/PID pairs. Be sure to read USBID-License.txt for rules!
* + This template uses obdev's shared VID/PID pair: 0x16c0/0x5dc.
* + Use this VID/PID pair ONLY if you understand the implications!
* own Vendor ID, define it here. Otherwise you may use one of obdev's free
* shared VID/PID pairs. Be sure to read USB-IDs-for-free.txt for rules!
* *** IMPORTANT NOTE ***
* This template uses obdev's shared VID/PID pair for Vendor Class devices
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
* the implications!
*/
#define USB_CFG_DEVICE_ID 0xdc, 0x05
#define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x05dc = 1500 */
/* This is the ID of the product, low byte first. It is interpreted in the
* scope of the vendor ID. If you have registered your own VID with usb.org
* or if you have licensed a PID from somebody else, define it here. Otherwise
* you use obdev's free shared VID/PID pair. Be sure to read the rules in
* USBID-License.txt!
* + This template uses obdev's shared VID/PID pair: 0x16c0/0x5dc.
* + Use this VID/PID pair ONLY if you understand the implications!
* you may use one of obdev's free shared VID/PID pairs. See the file
* USB-IDs-for-free.txt for details!
* *** IMPORTANT NOTE ***
* This template uses obdev's shared VID/PID pair for Vendor Class devices
* with libusb: 0x16c0/0x5dc. Use this VID/PID pair ONLY if you understand
* the implications!
*/
#define USB_CFG_DEVICE_VERSION 0x00, 0x01
/* Version number of the device: Minor number first, then major number.
@ -230,14 +248,14 @@ section at the end of this file).
* are interpreted as Unicode (UTF-16) entities.
* If you don't want a vendor name string, undefine these macros.
* ALWAYS define a vendor name containing your Internet domain name if you use
* obdev's free shared VID/PID pair. See the file USBID-License.txt for
* obdev's free shared VID/PID pair. See the file USB-IDs-for-free.txt for
* details.
*/
#define USB_CFG_DEVICE_NAME 'T', 'e', 'm', 'p', 'l', 'a', 't', 'e'
#define USB_CFG_DEVICE_NAME_LEN 8
/* Same as above for the device name. If you don't want a device name, undefine
* the macros. See the file USBID-License.txt before you assign a name if you
* use a shared VID/PID.
* the macros. See the file USB-IDs-for-free.txt before you assign a name if
* you use a shared VID/PID.
*/
/*#define USB_CFG_SERIAL_NUMBER 'N', 'o', 'n', 'e' */
/*#define USB_CFG_SERIAL_NUMBER_LEN 0 */
@ -337,6 +355,15 @@ section at the end of this file).
#define USB_CFG_DESCR_PROPS_HID_REPORT 0
#define USB_CFG_DESCR_PROPS_UNKNOWN 0
#define usbMsgPtr_t unsigned short
/* If usbMsgPtr_t is not defined, it defaults to 'uchar *'. We define it to
* a scalar type here because gcc generates slightly shorter code for scalar
* arithmetics than for pointer arithmetics. Remove this define for backward
* type compatibility or define it to an 8 bit type if you use data in RAM only
* and all RAM is below 256 bytes (tiny memory model in IAR CC).
*/
/* ----------------------- Optional MCU Description ------------------------ */
/* The following configurations have working defaults in usbdrv.h. You
@ -352,6 +379,6 @@ section at the end of this file).
/* #define USB_INTR_ENABLE_BIT INT0 */
/* #define USB_INTR_PENDING GIFR */
/* #define USB_INTR_PENDING_BIT INTF0 */
/* #define USB_INTR_VECTOR SIG_INTERRUPT0 */
/* #define USB_INTR_VECTOR INT0_vect */
#endif /* __usbconfig_h_included__ */

View File

@ -5,10 +5,8 @@
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.c 740 2009-04-13 18:23:31Z cs $
*/
#include "usbportability.h"
#include "usbdrv.h"
#include "oddebug.h"
@ -45,7 +43,7 @@ uchar usbCurrentDataToken;/* when we check data toggling to ignore duplica
#endif
/* USB status registers / not shared with asm code */
uchar *usbMsgPtr; /* data to transmit next -- ROM or RAM address */
usbMsgPtr_t usbMsgPtr; /* data to transmit next -- ROM or RAM address */
static usbMsgLen_t usbMsgLen = USB_NO_MSG; /* remaining number of bytes */
static uchar usbMsgFlags; /* flag values see below */
@ -67,7 +65,7 @@ optimizing hints:
#if USB_CFG_DESCR_PROPS_STRING_0 == 0
#undef USB_CFG_DESCR_PROPS_STRING_0
#define USB_CFG_DESCR_PROPS_STRING_0 sizeof(usbDescriptorString0)
PROGMEM char usbDescriptorString0[] = { /* language descriptor */
PROGMEM const char usbDescriptorString0[] = { /* language descriptor */
4, /* sizeof(usbDescriptorString0): length of descriptor in bytes */
3, /* descriptor type */
0x09, 0x04, /* language index (0x0409 = US-English) */
@ -77,7 +75,7 @@ PROGMEM char usbDescriptorString0[] = { /* language descriptor */
#if USB_CFG_DESCR_PROPS_STRING_VENDOR == 0 && USB_CFG_VENDOR_NAME_LEN
#undef USB_CFG_DESCR_PROPS_STRING_VENDOR
#define USB_CFG_DESCR_PROPS_STRING_VENDOR sizeof(usbDescriptorStringVendor)
PROGMEM int usbDescriptorStringVendor[] = {
PROGMEM const int usbDescriptorStringVendor[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_VENDOR_NAME_LEN),
USB_CFG_VENDOR_NAME
};
@ -86,7 +84,7 @@ PROGMEM int usbDescriptorStringVendor[] = {
#if USB_CFG_DESCR_PROPS_STRING_PRODUCT == 0 && USB_CFG_DEVICE_NAME_LEN
#undef USB_CFG_DESCR_PROPS_STRING_PRODUCT
#define USB_CFG_DESCR_PROPS_STRING_PRODUCT sizeof(usbDescriptorStringDevice)
PROGMEM int usbDescriptorStringDevice[] = {
PROGMEM const int usbDescriptorStringDevice[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_DEVICE_NAME_LEN),
USB_CFG_DEVICE_NAME
};
@ -95,7 +93,7 @@ PROGMEM int usbDescriptorStringDevice[] = {
#if USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER == 0 && USB_CFG_SERIAL_NUMBER_LEN
#undef USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER
#define USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER sizeof(usbDescriptorStringSerialNumber)
PROGMEM int usbDescriptorStringSerialNumber[] = {
PROGMEM const int usbDescriptorStringSerialNumber[] = {
USB_STRING_DESCRIPTOR_HEADER(USB_CFG_SERIAL_NUMBER_LEN),
USB_CFG_SERIAL_NUMBER
};
@ -108,7 +106,7 @@ PROGMEM int usbDescriptorStringSerialNumber[] = {
#if USB_CFG_DESCR_PROPS_DEVICE == 0
#undef USB_CFG_DESCR_PROPS_DEVICE
#define USB_CFG_DESCR_PROPS_DEVICE sizeof(usbDescriptorDevice)
PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
PROGMEM const char usbDescriptorDevice[] = { /* USB device descriptor */
18, /* sizeof(usbDescriptorDevice): length of descriptor in bytes */
USBDESCR_DEVICE, /* descriptor type */
0x10, 0x01, /* USB version supported */
@ -139,7 +137,7 @@ PROGMEM char usbDescriptorDevice[] = { /* USB device descriptor */
#if USB_CFG_DESCR_PROPS_CONFIGURATION == 0
#undef USB_CFG_DESCR_PROPS_CONFIGURATION
#define USB_CFG_DESCR_PROPS_CONFIGURATION sizeof(usbDescriptorConfiguration)
PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
PROGMEM const char usbDescriptorConfiguration[] = { /* USB configuration descriptor */
9, /* sizeof(usbDescriptorConfiguration): length of descriptor in bytes */
USBDESCR_CONFIG, /* descriptor type */
18 + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT + 7 * USB_CFG_HAVE_INTRIN_ENDPOINT3 +
@ -149,9 +147,9 @@ PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor
1, /* index of this configuration */
0, /* configuration name string index */
#if USB_CFG_IS_SELF_POWERED
USBATTR_SELFPOWER, /* attributes */
(1 << 7) | USBATTR_SELFPOWER, /* attributes */
#else
(char)USBATTR_BUSPOWER, /* attributes */
(1 << 7), /* attributes */
#endif
USB_CFG_MAX_BUS_POWER/2, /* max USB current in 2mA units */
/* interface descriptor follows inline: */
@ -184,7 +182,7 @@ PROGMEM char usbDescriptorConfiguration[] = { /* USB configuration descriptor
#if USB_CFG_HAVE_INTRIN_ENDPOINT3 /* endpoint descriptor for endpoint 3 */
7, /* sizeof(usbDescrEndpoint) */
USBDESCR_ENDPOINT, /* descriptor type = endpoint */
(char)0x83, /* IN endpoint number 1 */
(char)(0x80 | USB_CFG_EP3_NUMBER), /* IN endpoint number 3 */
0x03, /* attrib: Interrupt endpoint */
8, 0, /* maximum packet size */
USB_CFG_INTR_POLL_INTERVAL, /* in ms */
@ -301,7 +299,7 @@ USB_PUBLIC void usbSetInterrupt3(uchar *data, uchar len)
len = usbFunctionDescriptor(rq); \
}else{ \
len = USB_PROP_LENGTH(cfgProp); \
usbMsgPtr = (uchar *)(staticName); \
usbMsgPtr = (usbMsgPtr_t)(staticName); \
} \
}
@ -361,7 +359,8 @@ uchar flags = USB_FLG_MSGPTR_IS_ROM;
*/
static inline usbMsgLen_t usbDriverSetup(usbRequest_t *rq)
{
uchar len = 0, *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
usbMsgLen_t len = 0;
uchar *dataPtr = usbTxBuf + 9; /* there are 2 bytes free space at the end of the buffer */
uchar value = rq->wValue.bytes[0];
#if USB_CFG_IMPLEMENT_HALT
uchar index = rq->wIndex.bytes[0];
@ -408,7 +407,7 @@ uchar index = rq->wIndex.bytes[0];
SWITCH_DEFAULT /* 7=SET_DESCRIPTOR, 12=SYNC_FRAME */
/* Should we add an optional hook here? */
SWITCH_END
usbMsgPtr = dataPtr;
usbMsgPtr = (usbMsgPtr_t)dataPtr;
skipMsgPtrAssignment:
return len;
}
@ -498,7 +497,8 @@ static uchar usbDeviceRead(uchar *data, uchar len)
}else
#endif
{
uchar i = len, *r = usbMsgPtr;
uchar i = len;
usbMsgPtr_t r = usbMsgPtr;
if(usbMsgFlags & USB_FLG_MSGPTR_IS_ROM){ /* ROM data */
do{
uchar c = USB_READ_FLASH(r); /* assign to char size variable to enforce byte ops */
@ -507,7 +507,8 @@ static uchar usbDeviceRead(uchar *data, uchar len)
}while(--i);
}else{ /* RAM data */
do{
*data++ = *r++;
*data++ = *((uchar *)r);
r++;
}while(--i);
}
usbMsgPtr = r;
@ -557,6 +558,8 @@ uchar isReset = !notResetState;
USB_RESET_HOOK(isReset);
wasReset = isReset;
}
#else
notResetState = notResetState; // avoid compiler warning
#endif
}

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2005 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrv.h 748 2009-04-15 15:05:07Z cs $
*/
#ifndef __usbdrv_h_included__
@ -105,9 +104,9 @@ interrupt routine.
Interrupt latency:
The application must ensure that the USB interrupt is not disabled for more
than 25 cycles (this is for 12 MHz, faster clocks allow longer latency).
This implies that all interrupt routines must either be declared as "INTERRUPT"
instead of "SIGNAL" (see "avr/signal.h") or that they are written in assembler
with "sei" as the first instruction.
This implies that all interrupt routines must either have the "ISR_NOBLOCK"
attribute set (see "avr/interrupt.h") or be written in assembler with "sei"
as the first instruction.
Maximum interrupt duration / CPU cycle consumption:
The driver handles all USB communication during the interrupt service
@ -122,7 +121,7 @@ USB messages, even if they address another (low-speed) device on the same bus.
/* --------------------------- Module Interface ---------------------------- */
/* ------------------------------------------------------------------------- */
#define USBDRV_VERSION 20090415
#define USBDRV_VERSION 20121206
/* This define uniquely identifies a driver version. It is a decimal number
* constructed from the driver's release date in the form YYYYMMDD. If the
* driver's behavior or interface changes, you can use this constant to
@ -163,11 +162,24 @@ USB messages, even if they address another (low-speed) device on the same bus.
*/
#define USB_NO_MSG ((usbMsgLen_t)-1) /* constant meaning "no message" */
#ifndef usbMsgPtr_t
#define usbMsgPtr_t uchar *
#endif
/* Making usbMsgPtr_t a define allows the user of this library to define it to
* an 8 bit type on tiny devices. This reduces code size, especially if the
* compiler supports a tiny memory model.
* The type can be a pointer or scalar type, casts are made where necessary.
* Although it's paradoxical, Gcc 4 generates slightly better code for scalar
* types than for pointers.
*/
struct usbRequest; /* forward declaration */
USB_PUBLIC void usbInit(void);
/* This function must be called before interrupts are enabled and the main
* loop is entered.
* loop is entered. We exepct that the PORT and DDR bits for D+ and D- have
* not been changed from their default status (which is 0). If you have changed
* them, set both back to 0 (configure them as input with no internal pull-up).
*/
USB_PUBLIC void usbPoll(void);
/* This function must be called at regular intervals from the main loop.
@ -176,7 +188,7 @@ USB_PUBLIC void usbPoll(void);
* Please note that debug outputs through the UART take ~ 0.5ms per byte
* at 19200 bps.
*/
extern uchar *usbMsgPtr;
extern usbMsgPtr_t usbMsgPtr;
/* This variable may be used to pass transmit data to the driver from the
* implementation of usbFunctionWrite(). It is also used internally by the
* driver for standard control requests.
@ -388,13 +400,13 @@ extern volatile schar usbRxLen;
* about the various methods to define USB descriptors. If you do nothing,
* the default descriptors will be used.
*/
#define USB_PROP_IS_DYNAMIC (1 << 14)
#define USB_PROP_IS_DYNAMIC (1u << 14)
/* If this property is set for a descriptor, usbFunctionDescriptor() will be
* used to obtain the particular descriptor. Data directly returned via
* usbMsgPtr are FLASH data by default, combine (OR) with USB_PROP_IS_RAM to
* return RAM data.
*/
#define USB_PROP_IS_RAM (1 << 15)
#define USB_PROP_IS_RAM (1u << 15)
/* If this property is set for a descriptor, the data is read from RAM
* memory instead of Flash. The property is used for all methods to provide
* external descriptors.
@ -448,43 +460,43 @@ extern volatile schar usbRxLen;
#ifndef __ASSEMBLER__
extern
#if !(USB_CFG_DESCR_PROPS_DEVICE & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorDevice[];
extern
#if !(USB_CFG_DESCR_PROPS_CONFIGURATION & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorConfiguration[];
extern
#if !(USB_CFG_DESCR_PROPS_HID_REPORT & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorHidReport[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_0 & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
char usbDescriptorString0[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_VENDOR & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
int usbDescriptorStringVendor[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_PRODUCT & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
int usbDescriptorStringDevice[];
extern
#if !(USB_CFG_DESCR_PROPS_STRING_SERIAL_NUMBER & USB_PROP_IS_RAM)
PROGMEM
PROGMEM const
#endif
int usbDescriptorStringSerialNumber[];
@ -511,22 +523,22 @@ int usbDescriptorStringSerialNumber[];
#if !defined __ASSEMBLER__ && (!defined USB_CFG_VENDOR_ID || !defined USB_CFG_DEVICE_ID)
#warning "You should define USB_CFG_VENDOR_ID and USB_CFG_DEVICE_ID in usbconfig.h"
/* If the user has not defined IDs, we default to obdev's free IDs.
* See USBID-License.txt for details.
* See USB-IDs-for-free.txt for details.
*/
#endif
/* make sure we have a VID and PID defined, byte order is lowbyte, highbyte */
#ifndef USB_CFG_VENDOR_ID
# define USB_CFG_VENDOR_ID 0xc0, 0x16 /* 5824 in dec, stands for VOTI */
# define USB_CFG_VENDOR_ID 0xc0, 0x16 /* = 0x16c0 = 5824 = voti.nl */
#endif
#ifndef USB_CFG_DEVICE_ID
# if USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH
# define USB_CFG_DEVICE_ID 0xdf, 0x05 /* 1503 in dec, shared PID for HIDs */
# define USB_CFG_DEVICE_ID 0xdf, 0x05 /* = 0x5df = 1503, shared PID for HIDs */
# elif USB_CFG_INTERFACE_CLASS == 2
# define USB_CFG_DEVICE_ID 0xe1, 0x05 /* 1505 in dec, shared PID for CDC Modems */
# define USB_CFG_DEVICE_ID 0xe1, 0x05 /* = 0x5e1 = 1505, shared PID for CDC Modems */
# else
# define USB_CFG_DEVICE_ID 0xdc, 0x05 /* 1500 in dec, obdev's free PID */
# define USB_CFG_DEVICE_ID 0xdc, 0x05 /* = 0x5dc = 1500, obdev's free PID */
# endif
#endif
@ -716,7 +728,8 @@ typedef struct usbRequest{
#define USBDESCR_HID_REPORT 0x22
#define USBDESCR_HID_PHYS 0x23
#define USBATTR_BUSPOWER 0x80
//#define USBATTR_BUSPOWER 0x80 // USB 1.1 does not define this value any more
#define USBATTR_BUSPOWER 0
#define USBATTR_SELFPOWER 0x40
#define USBATTR_REMOTEWAKE 0x20

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm.S 740 2009-04-13 18:23:31Z cs $
*/
/*
@ -57,7 +56,11 @@ the file appropriate for the given clock rate.
#else /* __IAR_SYSTEMS_ASM__ */
# ifndef USB_INTR_VECTOR /* default to hardware interrupt INT0 */
# define USB_INTR_VECTOR SIG_INTERRUPT0
# ifdef INT0_vect
# define USB_INTR_VECTOR INT0_vect // this is the "new" define for the vector
# else
# define USB_INTR_VECTOR SIG_INTERRUPT0 // this is the "old" vector
# endif
# endif
.text
.global USB_INTR_VECTOR
@ -139,16 +142,93 @@ RTMODEL "__rt_version", "3"
#endif
; extern unsigned usbCrc16(unsigned char *data, unsigned char len);
; data: r24/25
; len: r22
#if USB_USE_FAST_CRC
; This implementation is faster, but has bigger code size
; Thanks to Slawomir Fras (BoskiDialer) for this code!
; It implements the following C pseudo-code:
; unsigned table(unsigned char x)
; {
; unsigned value;
;
; value = (unsigned)x << 6;
; value ^= (unsigned)x << 7;
; if(parity(x))
; value ^= 0xc001;
; return value;
; }
; unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen)
; {
; unsigned crc = 0xffff;
;
; while(argLen--)
; crc = table(lo8(crc) ^ *argPtr++) ^ hi8(crc);
; return ~crc;
; }
; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
; argPtr r24+25 / r16+r17
; argLen r22 / r18
; temp variables:
; r18: data byte
; r19: bit counter
; r20/21: polynomial
; r23: scratch
; r24/25: crc-sum
; r26/27=X: ptr
; byte r18 / r22
; scratch r23
; resCrc r24+r25 / r16+r17
; ptr X / Z
usbCrc16:
mov ptrL, argPtrL
mov ptrH, argPtrH
ldi resCrcL, 0xFF
ldi resCrcH, 0xFF
rjmp usbCrc16LoopTest
usbCrc16ByteLoop:
ld byte, ptr+
eor resCrcL, byte ; resCrcL is now 'x' in table()
mov byte, resCrcL ; compute parity of 'x'
swap byte
eor byte, resCrcL
mov scratch, byte
lsr byte
lsr byte
eor byte, scratch
inc byte
lsr byte
andi byte, 1 ; byte is now parity(x)
mov scratch, resCrcL
mov resCrcL, resCrcH
eor resCrcL, byte ; low byte of if(parity(x)) value ^= 0xc001;
neg byte
andi byte, 0xc0
mov resCrcH, byte ; high byte of if(parity(x)) value ^= 0xc001;
clr byte
lsr scratch
ror byte
eor resCrcH, scratch
eor resCrcL, byte
lsr scratch
ror byte
eor resCrcH, scratch
eor resCrcL, byte
usbCrc16LoopTest:
subi argLen, 1
brsh usbCrc16ByteLoop
com resCrcL
com resCrcH
ret
#else /* USB_USE_FAST_CRC */
; This implementation is slower, but has less code size
;
; extern unsigned usbCrc16(unsigned char *argPtr, unsigned char argLen);
; argPtr r24+25 / r16+r17
; argLen r22 / r18
; temp variables:
; byte r18 / r22
; bitCnt r19
; poly r20+r21
; scratch r23
; resCrc r24+r25 / r16+r17
; ptr X / Z
usbCrc16:
mov ptrL, argPtrL
mov ptrH, argPtrH
@ -156,27 +236,30 @@ usbCrc16:
ldi resCrcH, 0
ldi polyL, lo8(0xa001)
ldi polyH, hi8(0xa001)
com argLen ; argLen = -argLen - 1
crcByteLoop:
subi argLen, -1
brcc crcReady ; modified loop to ensure that carry is set below
com argLen ; argLen = -argLen - 1: modified loop to ensure that carry is set
ldi bitCnt, 0 ; loop counter with starnd condition = end condition
rjmp usbCrcLoopEntry
usbCrcByteLoop:
ld byte, ptr+
ldi bitCnt, -8 ; strange loop counter to ensure that carry is set where we need it
eor resCrcL, byte
crcBitLoop:
ror resCrcH ; carry is always set here
usbCrcBitLoop:
ror resCrcH ; carry is always set here (see brcs jumps to here)
ror resCrcL
brcs crcNoXor
brcs usbCrcNoXor
eor resCrcL, polyL
eor resCrcH, polyH
crcNoXor:
subi bitCnt, -1
brcs crcBitLoop
rjmp crcByteLoop
crcReady:
usbCrcNoXor:
subi bitCnt, 224 ; (8 * 224) % 256 = 0; this loop iterates 8 times
brcs usbCrcBitLoop
usbCrcLoopEntry:
subi argLen, -1
brcs usbCrcByteLoop
usbCrcReady:
ret
; Thanks to Reimar Doeffinger for optimizing this CRC routine!
#endif /* USB_USE_FAST_CRC */
; extern unsigned usbCrc16Append(unsigned char *data, unsigned char len);
usbCrc16Append:
rcall usbCrc16
@ -277,7 +360,11 @@ usbMFTimeout:
;----------------------------------------------------------------------------
#ifndef USB_CFG_CLOCK_KHZ
# define USB_CFG_CLOCK_KHZ 12000
# ifdef F_CPU
# define USB_CFG_CLOCK_KHZ (F_CPU/1000)
# else
# error "USB_CFG_CLOCK_KHZ not defined in usbconfig.h and no F_CPU set!"
# endif
#endif
#if USB_CFG_CHECK_CRC /* separate dispatcher for CRC type modules */

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2006 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id$
*/
/*

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm12.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbdrvasm128.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -31,8 +30,9 @@ limitations:
They typical range is 14.5 MHz and most AVRs can actually reach this rate.
(2) Writing EEPROM and Flash may be unreliable (short data lifetime) since
the write procedure is timed from the RC oscillator.
(3) End Of Packet detection is between bit 0 and bit 1 where the EOP condition
may not be reliable when a hub is used. It should be in bit 1.
(3) End Of Packet detection (SE0) should be in bit 1, bit it is only checked
if bits 0 and 1 both read as 0 on D- and D+ read as 0 in the middle. This may
cause problems with old hubs which delay SE0 by up to one cycle.
(4) Code size is much larger than that of the other modules.
Since almost all of this code is timing critical, don't change unless you
@ -217,8 +217,10 @@ unstuff0s:
ifioclr USBIN, USBMINUS ;[00]
ifioset USBIN, USBPLUS ;[01]
rjmp bit0IsClr ;[02] executed if first expr false or second true
jumpToSe0AndStore:
rjmp se0AndStore ;[03] executed only if both bits 0
se0AndStore: ; executed only if both bits 0
st y+, x1 ;[15/17] cycles after start of byte
rjmp se0 ;[17/19]
bit0IsClr:
ifrset phase, USBMINUS ;[04] check phase only if D- changed
lpm ;[05]
@ -228,7 +230,7 @@ bit1AfterClr:
andi phase, USBMASK ;[08]
ifioset USBIN, USBMINUS ;[09] <--- sample 1
rjmp bit1IsSet ;[10]
breq jumpToSe0AndStore ;[11]
breq se0AndStore ;[11] if D- was 0 in bits 0 AND 1 and D+ was 0 in between, we have SE0
andi shift, ~(7 << 1) ;[12]
in phase, USBIN ;[13] <- phase
breq unstuff1c ;[14]
@ -355,10 +357,6 @@ unstuff7c:
nop ;[59]
rjmp bit7IsSet ;[60]
se0AndStore:
st y+, x1 ;[15/17] cycles after start of byte
rjmp se0 ;[17/19]
bit7IsClr:
ifrset phase, USBMINUS ;[62] check phase only if D- changed
lpm ;[63]
@ -391,25 +389,24 @@ bit0IsSet:
in phase, USBIN ;[06] <- phase (one cycle too late)
ori shift, 1 << 0 ;[07]
bit1AfterSet:
andi phase, USBMASK ;[08]
andi shift, ~(7 << 1) ;[08] compensated by "ori shift, 1<<1" if bit1IsClr
ifioclr USBIN, USBMINUS ;[09] <--- sample 1
rjmp bit1IsClr ;[10]
andi shift, ~(7 << 1) ;[11]
breq unstuff1s ;[12]
in phase, USBIN ;[13] <- phase
nop ;[14]
breq unstuff1s ;[11]
nop2 ;[12] do not check for SE0 if bit 0 was 1
in phase, USBIN ;[14] <- phase (one cycle too late)
rjmp bit2AfterSet ;[15]
unstuff1s:
in phase, USBIN ;[14] <- phase (one cycle too late)
andi fix, ~(1 << 1) ;[15]
nop2 ;[08]
in phase, USBIN ;[13] <- phase
andi fix, ~(1 << 1) ;[14]
lpm ;[07]
nop2 ;[10]
bit1IsClr:
ifrset phase, USBMINUS ;[12] check phase only if D- changed
lpm ;[13]
in phase, USBIN ;[14] <- phase (one cycle too late)
breq se0AndStore ;[15] if we come from unstuff1s, Z bit is never set
ori shift, 1 << 1 ;[16]
ori shift, 1 << 1 ;[15]
nop ;[16]
bit2AfterClr:
ifioset USBIN, USBMINUS ;[17] <--- sample 2
rjmp bit2IsSet ;[18]

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm15.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm16.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the
@ -117,12 +116,15 @@ haveTwoBitsK:
; Receiver loop (numbers in brackets are cycles within byte after instr)
;----------------------------------------------------------------------------
; duration of unstuffing code should be 10.66666667 cycles. We adjust "leap"
; accordingly to approximate this value in the long run.
unstuff6:
andi x2, USBMASK ;[03]
ori x3, 1<<6 ;[04] will not be shifted any more
andi shift, ~0x80;[05]
mov x1, x2 ;[06] sampled bit 7 is actually re-sampled bit 6
subi leap, 3 ;[07] since this is a short (10 cycle) bit, enforce leap bit
subi leap, -1 ;[07] total duration = 11 bits -> subtract 1/3
rjmp didUnstuff6 ;[08]
unstuff7:
@ -130,7 +132,7 @@ unstuff7:
in x2, USBIN ;[00] [10] re-sample bit 7
andi x2, USBMASK ;[01]
andi shift, ~0x80;[02]
subi leap, 3 ;[03] since this is a short (10 cycle) bit, enforce leap bit
subi leap, 2 ;[03] total duration = 10 bits -> add 1/3
rjmp didUnstuff7 ;[04]
unstuffEven:
@ -139,8 +141,8 @@ unstuffEven:
andi shift, ~0x80;[01]
andi x1, USBMASK ;[02]
breq se0 ;[03]
subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
nop ;[05]
subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3
nop2 ;[05]
rjmp didUnstuffE ;[06]
unstuffOdd:
@ -149,8 +151,8 @@ unstuffOdd:
andi shift, ~0x80;[01]
andi x2, USBMASK ;[02]
breq se0 ;[03]
subi leap, 3 ;[04] since this is a short (10 cycle) bit, enforce leap bit
nop ;[05]
subi leap, -1 ;[04] total duration = 11 bits -> subtract 1/3
nop2 ;[05]
rjmp didUnstuffO ;[06]
rxByteLoop:

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2007 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm165.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by Lukas Schrittwieser and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm18-crc.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@ -6,7 +6,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by Jeroen Benschop and OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* Revision: $Id: usbdrvasm20.inc 740 2009-04-13 18:23:31Z cs $
*/
/* Do not link this file! Link usbdrvasm.S instead, which includes the

View File

@ -5,7 +5,6 @@
* Tabsize: 4
* Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
* License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
* This Revision: $Id: usbportability.h 740 2009-04-13 18:23:31Z cs $
*/
/*
@ -125,7 +124,11 @@ static inline void sei(void)
# include <avr/pgmspace.h>
#endif
#if USB_CFG_DRIVER_FLASH_PAGE
# define USB_READ_FLASH(addr) pgm_read_byte_far(((long)USB_CFG_DRIVER_FLASH_PAGE << 16) | (long)(addr))
#else
# define USB_READ_FLASH(addr) pgm_read_byte(addr)
#endif
#define macro .macro
#define endm .endm

View File

@ -55,30 +55,45 @@ void util_trim(uint8_t *s)
{
uint8_t *p = s;
uint8_t *q;
/* skip leading whitespace */
/*
* skip leading whitespace
*/
while (*p == ' ' || *p == '\t' || *p == '\r' || *p == '\n')
p++;
/* now p points at the first non-whitespace uint8_tacter */
/*
* now p points at the first non-whitespace uint8_tacter
*/
if (*p == '\0') {
/* only whitespace */
/*
* only whitespace
*/
*s = '\0';
return;
}
q = s + strlen((char *) s);
/* skip trailing whitespace */
/* we have found p < q such that *p is non-whitespace,
so this loop terminates with q >= p */
/*
* skip trailing whitespace
*/
/*
* we have found p < q such that *p is non-whitespace, so this loop terminates with q >= p
*/
do
q--;
while (*q == ' ' || *q == '\t' || *q == '\r' || *q == '\n');
/* now q points at the last non-whitespace uint8_tacter */
/* cut off trailing whitespace */
/*
* now q points at the last non-whitespace uint8_tacter
*/
/*
* cut off trailing whitespace
*/
*++q = '\0';
/* move to string */
/*
* move to string
*/
memmove(s, p, q + 1 - p);
}
@ -128,5 +143,3 @@ uint8_t util_sscanbool(const uint8_t *s)
return 1;
return -1;
}

View File

@ -28,4 +28,3 @@ void wdt_init(void)
return;
}

View File

@ -39,4 +39,3 @@ do \
} while(0)
#endif

View File

@ -0,0 +1,45 @@
--------------------------------
SDcard Board
--------------------------------
Connector
1 DO -> 7
2 GND -> 6
3 VCC -> 4
4 CS -> 1
5 DI -> 2
6 CLK -> 5
-
SDcard
------------------\
| \
| 8 7 6 5 4 3 2 1 9 |
| |
1 CS
2 CMD/DI
3 GND
4 VCC
5 CLK/SCLK
6 GND
7 DAT/DO
8 --
9 --
--------------------------------
Quickdev Header
--------------------------------
top/usb
1 GND -> GND
2 ISP RST - RESET -
3 ISP SCK - PB7 - CLK
4 ISP MISO - PB6 - DI
5 ISP MOSI - PB5 - DO
6 MMC CS - PB4 - CS
7 VCC -> VCC
#define SPI_DI 6 MISO
#define SPI_DO 5 MOSI

Binary file not shown.

View File

@ -0,0 +1,29 @@
________ .__ __ ________ ____ ________
\_____ \ __ __|__| ____ | | __\______ \ _______ _/_ |/ _____/
/ / \ \| | \ |/ ___\| |/ / | | \_/ __ \ \/ /| / __ \
/ \_/. \ | / \ \___| < | ` \ ___/\ / | \ |__\ \
\_____\ \_/____/|__|\___ >__|_ \/_______ /\___ >\_/ |___|\_____ /
\__> \/ \/ \/ \/ \/
___.
__ __ _____\_ |__
| | \/ ___/| __ \
| | /\___ \ | \_\ \
|____//____ >|___ /
\/ \/

BIN
files/Quickdev16_label.odt Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

25130
files/docs/avr/at90usb.pdf Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
files/docs/avr/stk500.pdf Normal file

Binary file not shown.

Binary file not shown.

BIN
files/docs/ftdi/FT232RL.pdf Normal file

Binary file not shown.

2248
files/docs/snes/65816.STD Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,515 @@
G65SC802 and G65SC816
Microprocessor Addressing modes
The G65SC816 is capable of directly addressing 16 MBytes of memory.
This address space has special significance within certain addressing
modes, as follows:
Reset and Interrupt Vectors
The Reset and Interrupt vectors use the majority of the fixed addresses
between 00FFE0 and 00FFFF.
Stack
The Native mode Stack address will always be within the range 000000 to
00FFFF. In the Emulation mode, the Stack address range is 000100 to 0001FF.
The following opcodes and addressing modes can increment or decrement beyond
this range when accessing two or three bytes:
JSL; JSR (a,x); PEA; PEI; PER; PHD; PLD; RTL; d,s; (d,s),y.
Direct
The Direct addressing modes are often used to access memory registers and
pointers. The contents of the Direct Register (D) is added to the offset
contained in the instruction operand to produce an address in the range 000000
to 00FFFF. Note that in the Emulation mode, [Direct] and [Direct],y addressing
modes and the PEI instruction will increment from 0000FE or 0000FF into the
Stack area, even if D=0.
Program Address Space
The Program Bank register is not affected by the Relative, Relative Long,
Absolute, Absolute Indirect, and Absolute Indexed Indirect addressing modes
or by incrementing the Program Counter from FFFF. The only instructions that
affect the Program Bank register are: RTI, RTL, JML, JSL, and JMP Absolute
Long. Program code may exceed 64K bytes altough code segments may not span
bank boundaries.
Data Address Space
The data address space is contiguous throughout the 16 MByte address space.
Words, arrays, records, or any data structures may span 64K byte bank
boundaries with no compromise in code efficiency. As a result, indexing from
page FF in the G65SC802 may result in data accessed in page zero. The
following addressing modes generate 24-bit effective addresses.
* Direct Indexed Indirect (d,x)
* Direct Indirect Indexed (d),y
* Direct Indirect (d)
* Direct Indirect Long [d]
* Direct Indirect Indexed Long [d],y
* Absolute
* Absolute,x
* Absolute,y
* Absolute long
* Absolute long indexed
* Stack Relative Indirect Indexed (d,s),y
The following addressing mode descriptions provide additional detail as
to how effective addresses are calculated.
Twenty-four addressing modes are available for use with the G65SC802
and G65SC816 microprocessors. The "long" addressing modes may be
used with the G65SC802; however, the high byte of the address is not
available to the hardware. Detailed descriptions of the 24 addressing
modes are as follows:
1. Immediate Addressing -- #
The operand is the second byte (second and third bytes when in the 16-bit
mode) of the instruction.
2. Absolute -- a
With Absolute addressing the second and third bytes of the instruction form
the low-order 16 bits of the effective address. The Data Bank Register
contains the high-order 8 bits of the operand address.
__________________________
Instruction: | opcode | addrl | addrh |
~~~~~~~~~~~~~~~~~~~~~~~~~~
Operand
Address: | DB | addrh | addrl |
3. Absolute Long -- al
The second, third, and fourth byte of the instruction form the 24-bit
effective address.
__________________________________
Instruction: | opcode | addrl | addrh | baddr |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Operand
Address: | baddr | addrh | addrl |
4. Direct -- d
The second byte of the instruction is added to the Direct Register
(D) to form the effective address. An additional cycle is required
when the Direct Register is not page aligned (DL not equal 0). The
Bank register is always 0.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
Operand
Address: | 00 | effective address |
5. Accumulator -- A
This form of addressing always uses a single byte instruction. The
operand is the Accumulator.
6. Implied -- i
Implied addressing uses a single byte instruction. The operand is implicitly
defined by the instruction.
7. Direct Indirect Indexed -- (d),y
This address mode is often referred to as Indirect,Y. The second byte of the
instruction is added to the Direct Register (D). The 16-bit contents of this
memory location is then combined with the Data Bank register to form a 24-bit
base address. The Y Index Register is added to the base address to form the
effective address.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
| 00 | direct address |
then:
| 00 | (direct address) |
+ | DB |
-------------------------------
| base address |
+ | | Y Reg |
------------------------------
Operand
Address: | effective address |
8. Direct Indirect Indexed Long -- [d],y
With this addressing mode the 24-bit base address is pointed to by
the sum of the second byte of the instruction and the Direct
Register The effective address is this 24-bit base address plus the Y
Index Register
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
| 00 | direct address |
then:
| (direct address) |
+ | | Y Reg |
------------------------------
Operand
Address: | effective address |
9. Direct Indexed Indirect -- (d,x)
This address mode is often referred to as Indirect X The second
byte of the Instruction is added to the sum of the Direct Register
and the X Index Register. The result points to the low-order 16 bits
of the effective address. The Data Bank Register contains the high-
order 8 bits of the effective address.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
| direct address |
+ | | X Reg |
---------------------
| 00 | address |
then:
| 00 | (address) |
+ | DB |
-------------------------------
Operand
Address: | effective address |
10. Direct Indexed With X -- d,x
The second byte of the instruction is added to the sum of the Direct Register
and the X Index Register to form the 16-bit effective address. The operand is
always in Bank 0.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
| direct address |
+ | | X Reg |
-------------------------------
Operand
Address: | 00 | effective address |
11. Direct Indexed With Y -- d,y
The second byte of the instruction is added to the sum of the Direct Register
and the Y Index Register to form the 16-bit effective address. The operand is
always in Bank 0.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
| direct address |
+ | | Y Reg |
-------------------------------
Operand
Address: | 00 | effective address |
12. Absolute Indexed With X -- a,x
The second and third bytes of the instruction are added to the
X Index Register to form the low-order 16 bits of the ef~ective ad-
dress The Data Bank Register contains the high-order 8 bits of the
effective address
____________________________
Instruction: | opcode | addrl | addrh |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| DB | addrrh | addrl |
+ | | X Reg |
-------------------------------
Operand
Address: | effective address |
13. Absolute Indexed With Y -- a,y
The second and third bytes of the instruction are added to the
Y Index Register to form the low-order 16 bits of the eftective ad-
dress The Data Bank Register contains the high-order 8 bits of tne
effective address.
____________________________
Instruction: | opcode | addrl | addrh |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| DB | addrrh | addrl |
+ | | Y Reg |
-------------------------------
Operand
Address: | effective address |
14. Absolute Long Indexed With X -- al,x
The second third and fourth bytes ot the instruction form a 24-bit base
address. The effective address is the sum of this 24-bit address and the
X Index Register.
____________________________________
Instruction: | opcode | addrl | addrh | baddr |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| baddr | addrrh | addrl |
+ | | X Reg |
-------------------------------
Operand
Address: | effective address |
15. Program Counter Relative -- r
This address mode referred to as Relative Addressing is used only with the
Branch instructions. If the conditlon being tested is met, the second byte
of the instruction is added to the Program Counter, which has been updated
to point to the opcode of the next instruction. The offset is a signed 8-bit
quantity in the range from -128 to 127 The Program Bank Register is not
affected.
16. Program Counter Relative Long -- rl
This address mode referred to as Relative Long Addressing is used only with
the Unconditional Branch Long instruction (BRL) and the Push Effective
Relative instruction (PER). The second and third 2 bytes of the instruction
are added to the Program Counter which has been updated to point to the opcode
of the next instruction. With the branch instruction the Program Counter is
loaded with the result With the Push Effective Relative instruction the result
is stored on the stack. The offset and result are both an unsigned 16-bit
quantity in the range 0 to 65535.
17. Absolute Indirect -- (a)
The second and third bytes of the instruction form an address to a pointer
in Bank 0. The Program Counter is loaded with the first and second bytes at
this pointer With the Jump Long (JML) instruction the Program Bank Register
is loaded with the third byte of the pointer
____________________________
Instruction: | opcode | addrl | addrh |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| baddr | addrrh | addrl |
Indirect Address = | 00 | addrh | addrl |
New PC = (indirect address)
with JML:
New PC = (indirect address)
New PB = (indirect address +2)
18. Direct Indirect -- (d)
The second byte of the instruction is added to the Direct Register to form
a pointer to the low-order 16 bits of the effective address. The Data Bank
Register contains the high-order 8 bits of the effective address.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
| 00 | direct address |
then:
| 00 | (direct address) |
+ | DB |
-------------------------------
Operand
Address: | effective address |
19. Direct Indirect Long -- [d]
The second byte of the instruction is added to the Direct Register to form
a pointer to the 24-bit effective address.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Direct Register |
+ | offset |
---------------------
| 00 | direct address |
then:
-------------------------------
Operand
Address: | (direct address) |
20. Absolute Indexed Indirect -- (a,x)
The second and third bytes of the instruction are added to the X Index
Register to form a 16-bit pointer in Bank 0. The contents of this pointer
are loaded in the Program Counter. The Program Bank Register is not changed.
____________________________
Instruction: | opcode | addrl | addrh |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
| addrrh | addrl |
+ | | X Reg |
-------------------------------
| 00 | address |
then:
PC = (address)
21. Stack -- s
Stack addressing refers to all instructions that push or pull data from the
stack such as Push, Pull, Jump to Subroutine, Return from Subroutine,
Interrupts, and Return from Interrupt. The bank address is always 0.
Interrupt Vectors are always fetched from Bank 0.
22. Stack Relative -- d,s
The low-order 16 bits of the effective address is formed from the sum of the
second byte of the instruction and the Stack Pointer. The high-order 8 bits
of the effective address is always zero. The relative offset is an unsigned
8-bit quantity in the range of 0 to 255.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Stack Pointer |
+ | offset |
---------------------
| 00 | effective address |
23. Stack Relative Indirect Indexed -- (d,s),y
The second byte of the instruction is added to the Stack Pointer to form
a pointer to the low-order 16-bit base address in Bank 0. The Data Bank
Register contains the high-order 8 bits of the base address. The effective
address is the sum of the 24-bit base address and the Y Index Register.
___________________
Instruction: | opcode | offset |
~~~~~~~~~~~~~~~~~~~
| Stack Pointer |
+ | offset |
---------------------
| 00 | S + offset |
then:
| S + offset |
+ | DB |
-------------------------------
| base address |
+ | | Y Reg |
------------------------------
Operand
Address: | effective address |
24. Block Source Bank, Destination Bank -- xyc
This addressing mode is used by the Block Move instructions.
The second byte of the instruction contains the high-order 8 bits of the
destination address.
The Y Index Register contains the low-order 16 bits of the destination
address. The third byte of the instruction contains the high-order 8 bits
of the source address.
The X Index Register contains the low-order 16 bits of the source address.
The Accumulator contains one less than the number of bytes to move.
The second byte of the block move instructions is also loaded into the Data
Bank Register.
____________________________
Instruction: | opcode | dstbnk | srcbnk |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
dstbnk -> DB
Source Address: | scrbnk | X reg |
Destination Address: | DB | Y reg |
Increment (MVN) or decrement (MVP) X and Y.
Decrement A (if greaterthan zero) then PC-3 -> PC.

View File

@ -0,0 +1,823 @@
Table 9. Detailed Instruction Operation
ADDRESS MODE
CYCLE /VP /ML VDA VPA ADDRESS BUS DATA BUS R/W
1 Immediate -- #
(LDY,CPY,CPX,LDX,ORA,AND,EOR,ADC,BIT,LDA,CMP,SBC,REP,SEP)
(14 Op Codes)
(2 and 3 bytes)
(2 and 3 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 IDL 1
2a 1 1 0 1 PBR,PC+2 IDH 1
2a Absolute -- a
(BIT,STY,STZ,LDY,CPY,CPX,STX,LDX,ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(16 Op Codes)
(3 bytes)
(4 and 5 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
4 1 1 1 0 DBR,AA Data Low 1/0
(1) 4a 1 1 1 0 DBR,AA+1 Data High 1/0
2b Absolute (R-M-W) -- a
(ASL,ROL,LSR,ROR,DEC,INC,TSB,TRB)
(8 Op Codes)
(3 bytes)
(6 and 8 cycles)
1 1 1 1 1 PBA,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
4 1 0 1 0 DBR,AA Data Low 1
(1) 4a 1 0 1 0 DBR,AA+1 Data High 1
(3) 5 1 0 0 0 DBR,AA+2 IO 1
(1) 6a 1 0 1 0 DBR,AA+3 Data Hiqh 0
6 1 0 1 0 DBR,AA Data Low 0
2c Absolute(JUMP) -- a
(JMP)(4C)
(1 Op Code)
(3 bytes)
(3 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 NEW PCL 1
3 1 1 0 1 PBR,PC+2 NEW PCH 1
1 1 1 1 1 PBR,NEWPC New Op Code 1
2d Absolute (Jump to subroutine) -- a
(JSR)
(1 Op Code)
(3 bytes)
(6 cycles)
(different order from N6502)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBA,PC+1 NEW FCC 1
3 1 1 0 1 PBR,PC+2 NEW PCH 1
4 1 1 0 0 PBR,PC+2 IO 1
5 1 1 1 0 0,S PCH 0
6 1 1 1 0 0,S-1 PCL 0
1 1 1 1 1 PBA,NEWPC New Op Code 1
3a Absolute Long -- al
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(4 bytes)
(5 and 6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
4 1 1 0 1 PBR,PC+3 AAB 1
5 1 1 1 0 AAB,AA Data Low 1/0
(1) 5a 1 1 1 0 AAB,AA+1 Data High 1/0
3b Absolute Long (JUMP) -- al
(JMP)
(1 Op Code)
(4 bytes)
(4 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 NEW PCL 1
3 1 1 0 1 PBR,PC+2 NEW PCH 1
4 1 1 0 1 PBR,PC+3 NEW BR 1
1 1 1 1 1 NEW PBR,PC New Op Code 1
3c Absolute Long (Jump to Subroutine Long) -- al
(JSL)
(1 Op Code)
(4 bytes)
(7 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 NEW PCL 1
3 1 1 0 1 PBR,PC+2 NEW PCH 1
4 1 1 1 0 0,S PBR 0
5 1 1 0 0 0,S IO 1
6 1 1 0 1 PBR,PC+3 NEW PBR 1
7 1 1 1 0 0,S-1 PCH 0
8 1 1 1 0 0,S-2 FCL 0
1 1 1 1 1 NEW PBR,PC New Op Code 1
4a Direct -- d
(BIT,STZ,STY,LDY,CPY,CPX,STX,LDX,ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(16 Op Codes)
(2 bytes)
(3,4 and 5 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+2 IO 1
3 1 1 1 0 0,D+DO Data Low 1/0
(1) 3a 1 1 1 0 0,D+DO+1 Data High 1/0
4b Direct (R-M-W) -- d
(ASL,ROL,LSR,ROR,DEC,INC,TSB,TRB)
(8 Op Codes)
(2 bytes)
(5,6,7 and 8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 3a 1 1 0 0 PBR,PC+1 IO 1
3 1 0 1 0 0,D+DO Data Low 1
(1) 3a 1 0 1 0 0,D+DO+1 Data High 1
(3) 4 1 0 0 0 0,D+DO+1 IO 1
(1) 5a 1 0 1 0 0,D+D0+1 Data High 0
5 1 0 1 0 0,D+DO Data Low 0
5 Accumurator -- A
(ASL,INC,ROL,DEC,LSR,ROR)
(6 Op Codes)
(1 byte)
(2 cycles)
1 1 1 1 1 PBR,PC Op COde 1
2 1 1 0 0 PBR,PC+1 IO 1
6a Implied -- i
(DEY,INY,INX,DEX,NOP,XCE,TYA,TAY,TXA,TXS,TAX,TSX,TCS,TSC,TCD,TDC,
TXY,TYX,CLC,SEC,CLI,SEI,CLV,CLD,SED)
(25 Op Codes)
(1 byte)
(2 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 PBR,PC+1 IO 1
*6b Implied -- i
(XBA)
(1 Op Code)
(1 byte)
(3 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
ADDRESS MODE
CYCLE /VP /ML VDA VPA RDY ADDRESS BUS DATA BUS R/W
6c Wait for Interrupt
(WAI)
(1 Op Code)
(1 byte)
(3 cycles)
1 1 1 1 1 1 PBR,PC Op Code 1
(9) 2 1 1 0 0 1 PBR,PC+1 IO 1
3 1 1 0 0 0 PBR,PC+1 IO 1
IRQ,NMI 1 1 1 1 1 1 PBR,PC+1 IRO(BRK) 1
6d Stop-The-Clock
(STP)
(1 Op Code)
(1 byte)
(3 cycles)
1 1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 1 PBR,PC+1 IO 1
RES=1 3 1 1 0 0 1 PBR,PC+1 IO 1
RES=0 1c 1 1 0 0 1 PBR,PC+1 RES(BRK) 1
RES=0 1b 1 1 0 0 1 PBR,PC+1 RES(BRK) 1
RES=1 1a 1 1 0 0 1 PBR,PC+1 RES(BRK) 1
1 1 1 1 1 1 PBR,PC+1 BEGIN 1
See 21a Stack (Hardware interrupt)
ADDRESS MODE
CYCLE /VP /ML VDA VPA ADDRESS BUS DATA BUS R/W
7 Direct Indirect Indexed -- (d),y
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(2 bytes)
(5,6,7 and 8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 1 0 0,D+DO AAL 1
4 1 1 1 0 0,D+DO+1 AAH 1
(4) 4a 1 1 0 0 DBR,AAH,AAL+YL IO 1
5 1 1 1 0 DBR,AA+Y Data Low 1/0
(1) 5a 1 1 1 1 DBR,AA+Y+1 Data High 1/0
8 Direct Indirect Indexed Long -- [d],y
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(2 bytes)
(6,7 and 8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 1 0 0,D+DO AAL 1
4 1 1 1 0 0,D+DO+1 AAH 1
5 1 1 1 0 0,D+DO+2 AAB 1
6 1 1 1 0 AAB,AA+Y Data Low 1/0
(1) 6a 1 1 1 0 AAB,AA+Y+1 Data High 1/0
9 Direct Indexed Indirect -- (d,x)
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(2 bytes)
(6,7 and 8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
a 1 1 1 0 0,D+DO+X AAL 1
5 1 1 1 0 0,D+DO+X+1 AAH 1
6 1 1 1 0 DBR,AA Data Low 1/0
(1) 6a 1 1 1 0 DBR,AA+1 Data High 1/0
10a Direct,X -- d,x
(BIT,STZ,STY,LDY,ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(12 Op Codes)
(2 bytes)
(4,5 and 6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,D+DO+X Data Low 1/0
(1) 4a 1 1 1 0 0,D+DO+X+1 Data High 1/0
10b Direct,X (R-M-W) -- d,x
(ASL,ROL,LSR,ROR,DEC,INC)
(6 Op Codes)
(2 bytes)
(6,7,8 and 9 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 0 1 0 0,D+DO+X Data Low 1
(1) 4a 1 0 1 0 0,D+DO+X+1 Data High 1
(3) 5 1 0 0 0 0,D+DO+X+1 IO 1
(1) 6a 1 0 1 0 0,D+DO+X+1 Data High 0
6 1 0 1 0 0,D+DO+X Data Low 0
11 Direct,Y -- d,y
(STX,LDX)
(2 Op Codes)
(2 bytes)
(4,5 and 6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,D+DO+Y Data Low 1/0
(1) 4a 1 1 1 0 0,D+DO+Y+1 Data High 1/0
12a Absolute,X -- a,x
(BlT,LDY,STZ,ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(11 Op Codes)
(3 bytes)
(4,5 and 6 cycles)
1 1 1 1 1 PBR,PC Op code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
(4) 3a 1 1 0 0 DBR,AAH,AAL+XL IO 1
4 1 1 1 0 DBR,AA+X Data Low 1/0
(1) 4a 1 1 1 0 DBR,AA+X+1 Data High 1/0
12b Absolute,X (R-M-W) -- a,x
(ASC,ROL,LSR,ROR,DEC,INC)
(6 Op Codes)
(3 bytes)
(7 and 9 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
4 1 1 0 0 DBR,AAH,AAL+XL IO 1
5 1 0 1 0 DBR,AA+X Data Low 1
(1) 5a 1 0 1 0 DBR,AA+X+1 Data High 1
(3) 6 1 0 0 0 DBR,AA+X+1 lO 1
(1) 7a 1 0 1 0 DBR,AA+X+1 Data High 0
7 1 0 1 0 DBR,AA+X Data Low 0
*13 Absolute Long,X -- al,x
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(4 bytes)
(5 and 6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+7 AAH 1
4 1 1 0 1 PBA,PC+3 AAB 1
5 1 1 1 0 AAB,AA+X Data Low 1/0
(1) 5a 1 1 1 0 AAB,AA+X+1 Data High 1/0
14 Absolute,Y -- a,y
(LDX,ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(9 Op Codes)
(3 bytes)
(4,5 and 6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
(4) 3a 1 1 0 0 DBR,AAH,AAL+YL IO 1
4 1 1 1 0 DBR,AA+Y Data Low 1/0
(1) 4a 1 1 1 0 DBR,AA+Y+1 Data High 1/0
15 Relative -- r
(BPL,BMI,BVC,BVS,BCC,BCS,BNE,BEQ,BRA)
(9 Op Codes)
(2 bytes)
(2,3 and 1 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 Offset 1
(5) 2a 1 1 0 0 PBR,PC+2 IO 1
(61 2b 1 1 0 0 PBR,PC+2+OFF IO 1
1 1 1 1 1 PBR,NewPC New Op Code 1
*16 Relative Long -- rl
(BRL)
(1 Op Code)
(3 bytes)
(4 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 Offset Low 1
3 1 1 0 1 PBR,PC+2 Offset High 1
4 1 1 0 0 PBR,PC+2 IO 1
1 1 1 1 1 PBR,NewPC New Op Code 1
17a Absolute Indirect -- (a)
(JMP)
(1 Op Code)
(3 bytes)
(5 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
4 1 1 1 0 0,AA NEW PCL 1
5 1 1 1 0 0,AA+1 NEW PCH 1
1 1 1 1 1 PBR,NewPC New Op Code 1
*17b Absolute Indirect -- (a)
(JML)
(1 Op Code)
(3 bytes)
(6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+1 AAH 1
4 1 1 1 0 0,AA NEW PCL 1
5 1 1 1 0 0,AA+1 NEW PCH 1
6 1 1 1 0 0,AA+2 NEW PBR 1
1 1 1 1 1 NEW PBR,PC New Op Code 1
**18 Direct Indirect -- (d)
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(2 bytes)
(5,6 and 7 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 1 0 0,D+DO AAL 1
1 1 1 1 0 0,D+DO+1 AAH 1
5 1 1 1 0 DBR,AA Data Low 1/0
(1) 5a 1 1 1 0 DBR,AA+1 Data Low 1/0
*19 Direct Indirect Long -- [d]
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(2 bytes)
(6,7 and 8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 1 0 0,D+DO AAL 1
4 1 1 1 0 0,D+DO+1 AAH 1
5 1 1 1 0 0,D+DO+2 AAB 1
6 1 1 1 0 AAB,AA Data Low 1/0
(1) 6a 1 1 1 0 AAB,AA+1 Data High 1/0
20a Absolute Indexed Indirect -- (a,x)
(JMP)
(1 Op Code)
(3 bytes)
(6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
4 1 1 0 0 PBR,PC+2 IO 1
5 1 1 0 1 PBR,AA+X NEW PCL 1
6 1 1 0 1 PBR,AA+X+1 NEW PCH 1
1 1 1 1 1 PBR,NEWPC New Op Code 1
*20b Absolute Indered Indirect (Jump to Subroutine Indexed Indirect) -- (a,x)
(JSR)
(1 Op Code)
(3 bytes)
(8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 1 0 0,S PCH 0
4 1 1 1 0 0,S-1 PCL 0
5 1 1 0 1 PBR,PC+2 AAH 1
6 1 1 0 0 PBR,PC+2 IO 1
7 1 1 0 1 PBR,AA+X NEW PCL 1
8 1 1 0 1 PBR,AA+X+1 NEW PCH 1
1 1 1 1 1 PBR,NEWPC New Op Code 1
21a Stack (Hardware Interrupts) -- s
(IRQ,NMI,ABORT,RES)
(4 hardware Interrupts)
(0 bytes)
(7 and 8 cycles)
1 1 1 1 1 PBR,PC IO 1
(3) 2 1 1 0 0 PBR,PC IO 1
(7) 3 1 1 1 0 0,S PBR 0
(10) 4 1 1 1 0 0,S-1 PCH 0
(10) 5 1 1 1 0 0,S-2 PCL 0
(10,11) 6 1 1 1 0 0,S-3 P 0
7 0 1 1 0 0,VA AAVL 1
8 0 1 1 0 0,VA+1 AAVH 1
1 1 1 1 1 0,AAV New Op Code 1
21b Stack (Software Interrupts) -- s
(BRK,COP)
(2 Op Codes)
(2 bytes)
(7 and 8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
(3) 2 1 1 0 1 PBR,PC+1 Signature 1
(7) 3 1 1 1 0 0,S PBR 0
4 1 1 1 0 0,S-1 PCH 0
5 1 1 1 0 0,S-2 PCL 0
6 1 1 1 0 0,S-3 (COP Latches) P 0
7 0 1 1 0 0,VA AAVL 1
8 0 1 1 0 0,VA+1 AAVH 1
1 1 1 1 1 0,AAV New Op Code 1
21c Stack (Return from Interrupt) -- s
(RTI)
(1 Op Code)
(1 byte)
(6 and 7 cycles)
(different order from N6502)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 PBR,PC+1 IO 1
(3) 3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,S+1 P 1
5 1 1 1 0 0,S+2 New PCL 1
6 1 1 1 0 0,S+3 New PCH 1
(7) 7 1 1 1 0 0,S+4 PBR 1
1 1 1 1 1 PBR,NewPC New Op Code 1
21d Stack (Return from Subroutine) -- s
(RTS)
(1 Op Code)
(1 byte)
(6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,S+1 New PCL-1 1
5 1 1 1 0 0,S+2 New PCH 1
6 1 1 0 0 0,S+2 IO 1
1 1 1 1 1 PBR,NewPC New Op Code 1
*21e Stack (Return from Subroutine Long) -- s
(RTL)
(1 Op Code)
(1 byte)
(6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,S+1 NEW PCL 1
5 1 1 1 0 0,S+2 NEW PCH 1
6 1 1 1 0 0,S+3 NEW PBR 1
1 1 1 1 1 NEWPBR,PC New Op Code 1
21f Stack (Push) -- s
(PHP,PHA,PHY,PHX,PHD,PHK,PHB)
(7 Op Codes)
(1 byte)
(3 and 4 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 PBR,PC+1 IO 1
3a 1 1 1 0 0,S Register High 0
3 1 1 1 0 0,S-1 Register Low 0
21g Stack (Pull) -- s
(PLP,PLA,PLY,PLX,PLD,PLB)
(Different than N6502)
(6 Op Codes)
(1 byte)
(4 and 5 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 0 PBR,PC+1 IO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,S+1 Register Low 1
(1) 4a 1 1 1 0 0,S+2 Register High 1
*21h Stack (Push Effective Indirect Address) -- s
(PEI)
(1 Op Code)
(2 bytes)
(6 and 7 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 DO 1
(2) 2a 1 1 0 0 PBR,PC+1 IO 1
3 1 1 1 0 0,D+DO AAL 1
d 1 1 1 0 0,D+DO+1 AAH 1
5 1 1 1 0 0,S AAH 0
6 1 1 1 0 0,S-1 AAL 0
*21i Stack (Push Effective Absolute Address) -- s
(PEA)
(1 Op Code)
(3 bytes)
(5 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 AAL 1
3 1 1 0 1 PBR,PC+2 AAH 1
4 1 1 1 0 0,S AAH 0
5 1 1 1 0 0,S-1 AAL 0
*21j Stack (Push Effective Program Counter Relative Address) -- s
(PER)
(1 Op Code)
(3 bytes)
(6 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 Offset Low 1
3 1 1 0 1 PBR,PC+2 Offset High 1
4 1 1 0 0 PBR,PC+2 IO 1
5 1 1 1 0 0,S PCH+Offset+CARRY 0
6 1 1 1 0 0,S-1 PCL + Offset 0
*22 Stace Relative -- d,s
(ORA,AND,EOR,ADC,STA,LDA,CMP,SBC)
(8 Op Codes)
(2 bytes)
(4 and 5 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 SO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,S+SO Data Low 1/0
(1) 4a 1 1 1 0 0,S+SO+1 Data High 1/0
*23 Stack Relative Indirect Indexed -- (d,s),y
(8 Op Codes)
(2 bytes)
(7 and 8 cycles)
1 1 1 1 1 PBR,PC Op Code 1
2 1 1 0 1 PBR,PC+1 SO 1
3 1 1 0 0 PBR,PC+1 IO 1
4 1 1 1 0 0,S+SO AAL 1
5 1 1 1 0 0,S+SO+1 AAH 1
6 1 1 0 0 0,S+SO+1 IO 1
7 1 1 1 0 DBR,AA+Y Data Low 1/0
(1) 7a 1 1 1 0 DBR,AA+Y+1 Data High 1/0
*24a Block Move Positive (forward) -- xyc
(MVP)
(1 Op Code)
(3 bytes)
(7 cycles)
+- 1 1 1 1 1 PBR,PC Op Code 1
| 2 1 1 0 1 PBR,PC+1 DBA 1
| 3 1 1 0 1 PBR,PC+2 SBA 1
N-2 | 4 1 1 1 0 SBA,X Source Data 1
Byte | 5 1 1 1 0 DBA,Y Dest Data 0
C=2 | 6 1 1 0 0 DBA,Y IO 1
+- 7 1 1 0 0 DBA,Y IO 1
+- 1 1 1 1 1 PBR,PC Op Code 1
| 2 1 1 0 1 PBR,PC+1 DBA 1
N-1 | 3 1 1 0 1 PBR,PC+2 SBA 1
Byte | 4 1 1 1 0 SBA,X-1 Source Data 1
C=1 | 5 1 1 1 0 DBA,Y-1 Dest Data 0
| 6 1 1 0 0 DBA,Y-1 IO 1
+- 7 1 1 0 0 DBA,Y-1 IO 1
+- 1 1 1 1 1 PBR,PC Op Code 1
| 2 1 1 0 1 PBR,PC+1 DBA 1
N Byte | 3 1 1 0 1 PBR,PC+2 SBA 1
Last | 4 1 1 1 0 SBA,X-2 Source Data 1
C=0 | 5 1 1 1 0 DBA,Y-2 Dest Data 0
| 6 1 1 0 0 DBA,Y-2 IO 1
| 7 1 1 0 0 DBA,Y-2 IO 1
+- 1 1 1 1 1 PBR,PC+3 New Op Code 1
x = Source Address
y = Destination
c = Number of Bytes to move -1
x,y Decrement
MVP is used when the destination start address is higher (more positive)
than the source start address.
FFFFFF
^ Dest Start
| Source Start
| Dest End
| Source End
000000
*24b, Block Move Negative (backward) -- xyc
(MVN)
(1 Op Code)
(3 bytes)
(7 cycles)
+- 1 1 1 1 1 PBR,PC Op Code 1
| 2 1 1 0 1 PBR,PC+1 DBA 1
| 3 1 1 0 1 PBR,PC+2 SBA 1
N-2 | 4 1 1 1 0 SBA,X Source Data 1
Byte | 5 1 1 1 0 DBA,Y Dest Data 0
C=2 | 6 1 1 0 0 DBA,Y IO 1
+- 7 1 1 0 0 DBA,Y IO 1
+- 1 1 1 1 1 PBR,PC Op Code 1
| 2 1 1 0 1 PBR,PC+1 DBA 1
N-1 | 3 1 1 0 1 PBR,PC+2 SBA 1
Byte | 4 1 1 1 0 SBA,X+1 Source Data 1
C=1 | 5 1 1 1 0 DBA,Y+1 Dest Data 0
| 6 1 1 0 0 DBA,Y+1 IO 1
+- 7 1 1 0 0 DBA,Y+1 IO 1
+- 1 1 1 1 1 PBR,PC Op Code 1
| 2 1 1 0 1 PBR,PC+1 DBA 1
N Byte | 3 1 1 0 1 PBR,PC+2 SBA 1
Last | 4 1 1 1 0 SBA,X+2 Source Data 1
C=0 | 5 1 1 1 0 DBA,Y+2 Dest Data 0
| 6 1 1 0 0 DBA,Y+2 IO 1
| 7 1 1 0 0 DBA,Y+2 IO 1
+- 1 1 1 1 1 PBR,PC+3 New Op Code 1
x = Source Address
y = Destination
c = Number of Bytes to move -1
x,y Increment
MVN is used when the destination start address is lower (more negative)
than the source start address.
FFFFFF
| Source End
| Dest End
| Source Start
v Dest Start
000000
Notes
(1) Add 1 byte (for immediate only) for M=O or X=O (i.e. 16 bit data),
add 1 cycle for M=O or X=0.
(2) Add 1 cycle for direct register low (DL) not equal 0.
(3) Special case for aborting instruction. This is the last cycle which
may be aborted or the Status, PBR or DBR registers will be updated.
(4) Add 1 cycle for indexing across page boundaries, or write, or X=0.
When X=1 or in the emulation mode, this cycle contains invalid
addresses.
(5) Add 1 cycle if branch is taken.
(6) Add 1 cycle if branch is taken across page boundaries in 6502 emutation
mode (E=1).
(7) Subtract 1 cycle for 6502 emulation mode (E=1).
(8) Add 1 cycle lor REP, SEP.
(9) Wait at cycle 2 for 2 cycles after /NMI or /IRQ active input.
(10) R/W remains high during Reset.
(11) BRK bit 4 equals "0" in Emulation mode.
Abbreviations
AAB Absolute Address Bank
AAH Absolute Address High
AAL Absolute Address Low
AAVH Absolute Address Vector High
AAVL Absolute Address Vector Low
C Accumulator
D Direct Register
DBA Destination Bank Address
DBR Data Bank Register
DO Direct Offset
IDH Immediate Data High
IDL Immediate Data Low
IO Internal Operation
P Status Register
PBR Program Bank Register
PC Program Counter
R-M-W Read-Modify-Write
S Stack Address
SBA Source Bank Address
SO Stack Offset
VA Vector Address
x, y Index Registers
* New G65SC816/802 Addressing Modes
** New G65SC02 Addressing Modes
Blank NMOS 6502 Addressing Modes

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

View File

@ -0,0 +1,72 @@
GTE G 65 SC 802 / G 65 SC 816
Microcircuits
CMOS 8/16-Bit Microprocessor Family
Features
Advanced CMOS design for low power consumption and increased
noise immunity
Emulation mode for total software compatibility with 6502 designs
Full 16-bit ALU, Accumulator, Stack Pointer, and Index Registers
Direct Register for ''zero page'' addressing
24 addressing modes (including 13 original 6502 modes)
Wait for Interrupt (WAI) and Stop the Clock (STP) instructions
for reduced power consumption and decreased interrupt latency
91 instructions with 255 opcodes
Co-Processor (COP) instruction and associated vector
Powerful Block Move instructions
Features (G65SC802 Only)
8-Bit Mode with both software and hardware (pin-to-pin) compatibility
with 6502 designs (64 KByte memory space)
Program selectable 16-bit operation
Choice of external or on-board clock generation
Features (G65SC816 Only)
Full 16-bit operation with 24 address lines for 16 MByte memory
Program selectable 8-Bit Mode for 6502 coding compatibility.
Valid Program Address (VPA) and Valid Data Address (VDA) outputs
for dual cache and DMA cycle steal implementation
Vector Pull (VP) output indicates when interrupt vectors are being
fetched. May be used for vectoring/prioritizing interrupts.
Abort interrupt and associated vector for interrupting any instruction
without modifying internal registers
Memory Lock (ML) for multiprocessor system implementation
General Description
The G65SC802 and G65SC816 are ADV-CMOS (ADVanced CMOS) 16-bit microprocessors
featuring total software compatibility with 8-bit NMOS and CMOS 6500 series
microprocessors. The G65SC802 is pin-to-pin compatible with 8-bit 6502 devices
currently available, while also providing full 16-bit internal operation. The
G65SC816 provides 24 address lines for 16 MByte addressing, while providing
both 8-bit and 16-bit operation.
Each microprocessor contains an Emulation (E) mode for emulating 8-bit NMOS
and CMOS 6500-Series microprocessors. A software switch determines whether the
processor is in the 8-bit ernulation mode or in the Native 16-bit mode.
This allows existing 8-bit system designs to use the many powerful features of
the G65SC802 and G65SC816.
The G65SC802 and G65SC816 provide the system engineer with many powerful
features and options. A 16-bit Direct Page Register is provided to augment the
Direct Page addressing mode, and there are separate Program Bank Registers
for 24-bit memory addressing.
Other valuable features Include:
* An Abort input which can interrupt the current instruction without
modifying internal registers
* Valid Data Address (VDA) and Valid Program Address (VPA) outputs which
facilitate dual cache memory by indicating whether a data or program
segment is being accessed.
* Vector modification by simply monitoring the Vector Pull (VP) output.
* Block Move Instructions
G65SC802 and G65SC816 microprocessors offer the design engineer a new freedom
of design and application, and the many advantages of state-of-the-art
ADV-CMOS technology.
This is advanced information and specifications are subject to change without notice.

View File

@ -0,0 +1,455 @@
Functional Description
The G65SC802 offers the design engineer the opportunity to utilize both
existing software programs and hardware configurations, while also
achieving the added advantages of increased register lengths and faster
execution times. The G65SC802's "ease of use" design and implementation
features provide the designer with increased flexibility and reduced
implementation costs In the Emulation mode, the G65SC802 not only offers
software compatibility, but is also hardware (pin-to-pin) compatible with
6502 designs plus it provides the advantages of 16-bit internal operation
in 6502-compatible applications. The G65SC802 is an excellent direct
replacement microprocessor for 6502 designs.
The G65SC816 provides the design engineer with upward mobility and software
compatibility in applications where a 16-bit system configuration is desired.
The G65SC816's 16-bit hardware configuration, coupled with current software
allows a wide selection of system applications. In the Emulation mode, the
G65SC816 ofters many advantages, including full software compatibility with
6502 coding. In addition, the G65SC816's powerful instruction set and
addressing modes make it an excellent choice for new 16-bit designs.
Internal organization of the G65SC802 and G65SC816 can be divided into two
parts: 1) The Register Section, and 2) The Control Section Instructions
(or opcodes) obtained from program memory are executed by implementing a
series of data transfers within the Register Section.
Signals that cause data transfers to be executed are generated within the
Control Section. Both the G65SC802 and the G65SC816 have a 16-bit internal
architecture with an 8-bit external data bus.
Instructlon Register and Decode
An opcode enters the processor on the Data Bus, and is latched into the
Instruction Register during the instruction fetch cycle. This instruction is
then decoded, along with timing and interrupt signals, to generate the
various Instruction Register control signals.
Timing Control Unit (TCU)
The Timing Control Unit keeps track of each instruction cycle as it is
executed. The TCU is set to zero each time an instruction fetch is executed,
and is advanced at the beginning of each cycle for as many cycles as is
required to complete the instruction Each data transfer between registers
depends upon decoding the contents of both the Instruction Register and
the Timing Control Unit.
Arithmetic and Logic Unit (ALU)
All arithmetic and logic operations take place within the 16-bit ALU. In
addition to data operations, the ALU also calculates the effective address
for relative and indexed addressing modes. The result of a data operation
is stored in either memory or an internal register. Carry, Negative, Over-
flow and Zero flags may be updated following the ALU data operation.
Internal Registers (Refer to Figure 2, Programming Model)
Accumulator (A)
The Accumulator is a general purpose register which stores one of the
operands, or the result of most arithmetic and logical operations. In the
Native mode (E=0), when the Accumulator Select Bit (M) equals zero, the
Accumulator is established as 16 bits wide. When the Accumulator Select
Bit (M) equals one, the Accumulator is 8 bits wide. In this case, the upper
8 bits (AH) may be used for temporary storage in conjunction with the
Exchange AH and AL instruction.
Data Bank (DB)
During the Native mode (E=0), the 8-bit Data Bank Register holds the default
bank address for memory transfers. The 24-bit address is composed of the
16-bit instruction effective address and the 8-bit Data Bank address. The
register value is multiplexed with the data value and is present on the
Data/Address lines during the first half of a data transfer memory cycle for
the G65SC816. The Data Bank Register is initialized to zero during Reset.
Direct (D)
The 16-bit Direct Register provides an address offset for all instructions
using direct addressing. The effective bank zero address is formed by adding
the 8-bit instruction operand address to the Direct Register. The Direct
Register is initialized to zero during Reset.
Index (X and Y)
There are two Index Registers (X and Y) which may be used as general purpose
registers or to provide an index value for calculation of the effective
address. When executing an instruction with indexed addressing, the
microprocessor fetches the opcode and the base address, and then modifies the
address by adding the Index Register contents to the address prior to
performing the desired operation.
Pre-indexing or postindexing of Indirect addresses may be selected. In the
Native mode (E=0), both Index Registers are 16 bits wide (providing the Index
Select Bit (X) equals zero). If the Index Select Bit (X) equals one, both
registers will be 8 bits wide.
Processor Status (P)
The 8-bit Processor Status Register contains status flags and mode select bits.
The Carry (C), Negative (N). Overflow (V), and Zero (Z) status flags serve to
report the status ot most ALU operations. These status flags are tested by use
of Conditional Branch instructions. The Decimal (D), IRQ Disable (I), Memory,
Accumuiator (M), and Index (X) bits are used as mode select flags. These flags
are set by the program to change microprocessor operations.
The Emulation (E) select and the Break (B) flags are accessible only through
the Processor Status Register. The Emulation mode select flag is selected by
the Exchange Carry and Emulation Bits (XCE) instruction.
Table 2, G65SC802 and G65SC816 Mode Comparison, illustrates the features of
the Native (E=0) and Emulation (E=1) modes. The M and X flags are always equal
to one in the Emulation mode. When an interrupt occurs during the Emulation
mode, the Break flag is written to stack memory as bit 4 of the Processor
Status Register.
Program Bank (PB)
The 8-bit Program Bank Register holds the bank address for all instruction
fetches. The 24-bit address consists of the 16-bit instruction effective
address and the 8-bit Program Bank address. The register value is multiplexed
with the data value and presented on the Data/Address lines during the first
half of a program memory read cycle. The Program Bank Register is initialized
to zero during Reset.
Program Counter (PC)
The 16-bit Program Counter Register provides the addresses which are used to
step the microprocessor through sequential program instructions. The register
is incremented each time an instruction or operand is fetched from program
memory.
Stack Pointer (S)
The Stack Pointer is a 16-bit register which is used to indicate the next
available location in the stack memory area. It serves as the effective address
in stack addressing modes as well as subroutine and interrupt processing. The
Stack Pointer allows simple implementation of nested subroutines and multiple-
level interrupts. During the Emulation mode, the Stack Pointer high-order byte
(SH) is always equal to 01. The Bank Address is 00 for all Stack operations.
Signal Description
The following Signal Description applies to both the G65SC802 and the
SSC816 except as otherwise noted.
Abort (/ABORT) -- G65SC816
The Abort input prevents modification of any internal registers during
execution of the current instruction. Upon completion of this instruction,
an interrupt sequence is initiated. The location of the aborted opcode is
stored as the return address in Stack memory. The Abort vector address is
00FFF8, 9 (Emulation mode) or 00FFE8, 9 (Native mode). Abort is asserted
whenever there is a low level on the Abort input. and the Phi2 clock is high.
The Abort internal latch is cleared during the second cycle of the interrupt
sequence. This signal may be used to handle out-of-bounds memory references
in virtual memory systems.
Address Bus (A0-A15)
These sixteen output lines form the Address Bus for memory and I/O exchange on
the Data Bus. When using the G65SC816, the address lines may be set to the
high impedance state by the Bus Enable (BE) signal.
Bus Enable (BE)
The Bus Enable input signal allows external control of the Address and Data
Buffers, as well as the R/W signal With Bus Enable high, the R/W and Address
Buffers are active. The Data/Address Buffers are active during the first half
of every cycle and the second half of a write cycle. When BE is low, these
buffers are disabled. Bus Enable is an asynchronous signal.
Data Bus (D0-D7) -- G65SC802
The eight Data Bus lines provide an 8-bit bidirectional Data Bus for use
during data exchanges between the microprocessor and external memory or
peripherals. Two memory cycles are required for the transfer of 16-bit values.
Data/Address Bus (D0/BA0-D7/BA7) -- G65SC816
These eight lines multiplex bits BAO-BA7 with the data value. The Bank Address
is present during the first half of a memory cycle, and the data value is read
or written during the second half of the memory cycle.
The Bank address external transparent latch should be latched when the Phi2
clock is high or RDY is low. Two memory cycles are required to transfer 16-bit
values. These lines may be set to the high impedance state by the Bus Enable
(BE) signal.
Emulation Status (E) -- G65SC816 (Also Applies to G65SC802, 44-Pin Version)
The Emulation Status output reflects the state of the Emulation (E) mode flag
in the Processor Status (P) Register. This signal may be thought of an opcode
extension and used for memory and system management.
Interrupt Request (/IRQ)
The Interrupt Request input signal is used to request that an interrupt
sequence be initiated. When the IRQ Disable (I) flag is cleared, a low input
logic level initiates an interrupt sequence after the current instruction is
completed. The Wait for Interrupt (WAI) instruction may be executed to ensure
the interrupt will be recognized immediately. The Interrupt Request vector
address is 00FFFE,F (Emulation mode) or 00FFEE,F (Native mode). Since IRQ is a
level-sensitive input, an interrupt will occur if the interrupt source was not
cleared since the last interrupt.
Also, no interrupt will occur if the interrupt source is cleared prior to
interrupt recognition.
Memory Lock (/ML) -- G65SC816 (Also Applies to G65SC802, 44-Pin Version)
The Memory Lock output may be used to ensure the integrity of Read-Modify-Write
instructions in a multiprocessor system. Memory Lock indicates the need to
defer arbitration of the next bus cycle. Memory Lock is low during the last
three or five cycles of ASL, DEC, INC, LSR, ROL, ROR, TRB, and TSB memory
referencing instructions, depending the state of the M flag.
Memory/Index Select Status (M/X) -- G65SC816
This multiplexed output reflects the state ot the Accumulator (M) and index (X)
select flags (bits 5 and 4 of the Processor Status (P) Register).
Flag M is valid during the Phi2 clock positive transition. Instructions PLP,
REP, RTI and SEP may change the state of these bits. Note that the M/X output
may be invalid in the cycle following a change in the M or X bits. These bits
may be thought of as opcode extensions and may be used for memory and system
management.
Non-Maskable Interrupt (/NMI)
A high-to-low transition initiates an intenupt sequence after the current
instruction is completed. The Wait for Interrupt (WAI) instruction may be
executed to ensure that the interrupt will be recognized immediately. The
Non-Maskable Interrupt vector address is 00FFFA,B (Emulation mode) or 00FFEA,B
(Native mode). Since NMI is an edge-sensitive Input, an interrupt will occur
if there is a negative transition while servicing a previous interrupt. Also,
no interrupt will occur if NMI remains low.
Phase 1 Out (Phi1 (OUT)) -- G65SC802
This inverted clock output signal provides timing for external read and write
operations. Executing the Stop (STP) instruction holds this clock in the low
state.
Phase 2 In (Phi2 (IN))
This is the system clock input to the microprocessor internal clock generator
(equivalent to Phi0 (IN) on the 6502). During the low power Standby Mode, Phi2
(IN) should be held in the high state to preserve the contents of internal
registers.
Phase 2 Out (Phi2 (OUT)) -- G65SC802
This clock output signal provides timing for external read and write
operations. Addresses are valid (after the Address Setup Time (TADS))
following the negative transition of Phase 2 Out. Executing the Stop (STP)
instruction holds Phase 2 Out in the High state.
Read/Write (R/W)
When the R/W output signal is in the high state, the microprocessor is reading
data from memory or I/O. When in the low state, the Data Bus contains valid
data from the microprocessor which is to be stored at the addressed memory
location. When using the G65SC816, the R/W signal may be set to the high
impedance state by Bus Enable (BE).
Ready (RDY)
This bidirectional signal indicates that a Wait for Interrupt (WAI) instruction
has been executed allowing the user to halt operation of the microprocessor.
A low input logic level will halt the microprocessor in its current state (note
that when in the Emulation mode, the G65SC802 stops only during a read cycle).
Returning RDY to the active high state allows the microprocessor to continue
following the next Phase 2 In Clock negative transition. The RDY signal is
internally pulled low following the execution of a Wait for Interrupt (WAI)
instruction, and then returned to the high state when a /RES, /ABORT, /NMI, or
/IRQ external interrupt is provided. This feature may be used to eliminate
interrupt latency by placing the WAI instruction at the beginning of the IRQ
servicing routine. If the IRQ Disable flag has been set, the next instruction
will be executed when the IRQ occurs. The processor will not stop after a WAI
instruction if RDY has been forced to a high state. The Stop (STP) instruction
has no effect on RDY.
Reset (/RES)
The Reset input is used to initialize the microprocessor and start program
execution. The Reset input buffer has hysteresis such that a simple R-C timing
circuit may be used with the internal pullup device. The /RES signal must be
held low for at least two clock cycles after VDD reaches operating voltage.
Ready (RDY) has no effect while RES is being held low. During this Reset
conditioning period, the following processor initialization takes place:
Registers
D = 0000 SH = 01
DB = 00 XH = 00
PB = 00 YH = 00
N V M X D I Z C/E
P = * * 1 1 0 1 * */1
* = Not Initialized
STP and WAI instructions are cleared.
Signals
E = 1 VDA = 0
M/X = 1 /VP = 1
R/W = 1 VPA = 0
SYNC = 0
When Reset is brought high, an interrupt sequence is initiated:
* R/W remains in the high state during the stack address cycles.
* The Reset vector address is 00FFFC,D.
Set Overtlow (/SO) -- G65SC802
A negative transition on this input sets the Overflow (V) flag, bit 6 of the
Processor Status (P) Register.
Synchronlze (SYNC) -- G65SC802
The SYNC output is provided to identify those cycles during which the
microprocessor is fetching an opcode. The SYNC signal is high during an opcode
fetch cycle, and when combined with Ready (RDY), can be used for single
instruction execution.
Valid Data Address (VDA) and
Valid Program Address (VPA) -- G65SC816
These two output signals indicate the type of memory being accessed by
the address bus. The following coding applies:
VDA VPA
0 0 Internal Operation -- Address and Data Bus available. Address
outputs may be invalid due to low byte additions only.
0 1 Valid program address -- may be used for program cache control.
1 0 Valid data address -- may be used for data cache control.
1 1 Opcode fetch -- may be used for program cache control
and single step control.
VDD and Vss
VDD Vss the positive supply voltage and Vss is system ground. When
using only one ground on the G65SC802 DIP package, pin 21 preferred.
Vector Pull (VP) -- G65SC816 (Also Applies to G65SC802 44-Pin Version)
The Vector Pull output indicates that a vector location is being addressed
during an interrupt sequence. /VP is low during the last two interrupt sequence
cycles, during which time the processor reads the interrupt vector. The /VP
signal may be used to select and prioritize interrupts from several sources by
modifying the vector addresses.
--------------------------------------------------------------------------
8 bits 8 bits 8 bits
DB DB Data Bank Register
XH XL Index Register (X)
YH YL Index Register (Y)
00 SH SL Stack Pointer (S)
AH AL Accumulator (A)
PB PCH PCL Program Counter (PC)
Program Bank Register (PB)
00 DH DL Direct Register (D)
L = Low, H = High
Processor Status Register (P)
____________________________
| 1 B E |
|__________________________|
| N V M X D I Z C |
|__________________________|
1 Always 1 if E=1
B Break 0 on Stack after interupt if E=1
E Emulation Bit 0= Native mode, 1= 6502 emulation
N Negative 1= Negative
V Overflow 1= True
M Memory/Acc. Select 1= 8 bit, 0= 16 bit
X Index Register Select 1= 8 bit, 0= 16 bit
D Decimal mode 1= Decimal Mode
I IRQ Disable 1= Disable
Z Zero 1= Result Zero
C Carry 1= True
Figure 2. Programming model
--------------------------------------------------------------------------
Table 1. G65SC802 and G65SC816 Compability
Function G65SC802/816 G65SC02 NMOS 6502
Emulation
Decimal Mode:
* After Interrupts 0 -> D 0 -> D Not initialized
* N, Z Flags Valid Valid Undefined
* ADC, SBC No added cycle Add 1 cycle No added cycle
Read-Modify-Write:
* Absolute Indexed, No Page Crossing
7 cycles 6 cycles 7 cycles
* Write Last 2 cycles Last cycle Last 2 cycles
* Memory Lock Last 3 cycles Last 2 cycles Not available
Jump Indirect:
* Cycles 5 cycles 6 cycles 5 cycles
* Jump Address, operand = xxFF Correct Correct Invalid
Branch or Index Across Page Boundary
Read last Read last Read invalid
program byte program byte address
0 -> RDY During Write G65SC802: Ignored Processor Ignored until
until read stops read
G65SC816: Processor
stops
Write During Reset No Yes No
Unused Opcodes No operation No operation Undefined
Phi1 (OUT), Phi2 (OUT), /SO, SYNC Signals
Available with Available Available
G65SC802 only
RDY Signal Bidirectional Input Input
--------------------------------------------------------------------------
Table 2. G65SC802 and G65SC816 Mode Comparison
Function Emulation (E = 1) Native (E = 0)
Stack Pointer (S) 8 bits in page 1 16 bits
Direct Index Address Wrap within page Crosses page boundary
Processor Status (P):
* Bit 4 Always one, except zero X flag (8/16-bit Index)
in stack after hardware
interrupt
* Bit 5 Always one M flag (8/16-bit Accumulator)
Branch Across Page Boundary
4 cycles 3 cycles
Vector Locations:
ABORT 00FFF8,9 00FFF8,9
BRK 00FFFE,F 00FFF6,7
COP 00FFF4,5 00FFF4,5
IRQ 00FFFE,F 00FFFE,F
NMI 00FFFA,B 00FFFA,B
RES 00FFFC,D 00FFFC,D (1 -> E)
Program Bank (PB) During Interrupt, RTI
Not pushed, pulled Pushed and pulled
0 -> RDY During Write
G65SC802: Ignored until read Processor stops
G65SC816: Processor stops
Write During Read-Modify-Write
Last 2 cycles Last 1 or 2 cycles depending
on M flag

View File

@ -0,0 +1,91 @@
Notes on G65SC802/816 Instructions
All Opcodes Function in All Modes of Operation
It should be noted that all opcodes function in all modes of operation.
However, some instructions and addressing modes are intended for G65SC816
24-bit addressing and are therefore less useful for the G65SC802. The
following is a list of Instructions and addressing modes which are primarily
intended for G65SC816 use:
JSL; RTL; [d]; [d],y; JMP al; JML; al; al,x
The following instructions may be used with the G65SC802 even though a
Bank Address is not multiplexed on the Data Bus:
PHK; PHB; PLB
The following instructions have "limited" use in the Emulation mode.
* The REP and SEP instructions cannot modify the M and X bits when in the
Emulation mode. In this mode the M and X bits will always be high (logic 1).
* When in the Emulation mode, the MVP and MVN instructions only move data
in page zero since X and Y Index Register high byte is zero.
Indirect Jumps
The JMP (a) and JML (a) instructions use the direct Bank for indirect
addressing, while JMP (a,x) and JSR (a,x) use the Program Bank for indirect
address tables.
Switching Modes
When switching from the Native mode to the Emulation mode, the X and M bits
of the Status Register are set high (logic 1), the high byte of the Stack is
set to 01, and the high bytes of the X and Y Index Registers are set to 00.
To save previous values, these bytes must always be stored before changing
modes. Note that the low byte of the S, X and Y Registers and the low and high
byte of the Accumulator AL and AH are not affected by a mode change.
WAI Instruction
The WAI instruction pulls RDY low and places the processor in the WAI
"low power" mode. /NMI, /IRQ or /RESET will terminate the WAI condition and
transfer control to the interrupt handler routine. Note that an /ABORT input
will abort the WAI instruction, but will not restart the processor. When the
Status Register I flag is set (IRQ disabled), the IRQ interrupt will cause the
next instruction (following the WAI instruction) to be executed without going
to the IRQ interrupt handler. This method results in the highest speed response
to an IRQ input. When an interrupt is received after an ABORT which occurs
during the WAI instruction, the processor will return to the WAI instruction.
Other than RES (highest priority), ABORT is the next highest priority, followed
by NMI or IRQ interrupts.
STP Instruction
The STP instruction disables the Phi2 clock to all circuitry. When disabled,
the Phi2 clock is held in the high state. In this case, the Data Bus will
remain in the data transfer state and the Bank address will not be multiplexed
onto the Data Bus. Upon executing the STP instruction, the /RES signal is the
only input which can restart the processor. The processor is restarted by
enabling the Phi2 clock, which occurs on the falling edge of the /RES input.
Note that the external oscillator must be stable and operating properly before
RES goes high.
Tranters trom 8-Bit to 16-Bit, or 16-Bit to 8-Bit Registers
All transfers from one register to another will result in a full 16-bit output
from the source register. The destination register size will determine the
number of bits actually stored in the destination register and the values
stored in the processor Status Register. The following are always 16-bit
transfers, regardless of the accumulator size:
TCS; TSC; TCD; TDC
Stack Transfers
When in the Emulation mode, a 01 is forced into SH. In this case, the B
Accumulator will not be loaded into SH during a TCS instruction. When in the
Native mode, the B Accumulator is transferred to SH. Note that in both the
Emulation and Native modes, the full 16 bits of the Stack Register are
transferred to the Accumulator, regardless of the state of the M bit in the
Status Register.

View File

@ -0,0 +1,197 @@
Table 5. Arithmetic and Logical Instructions
Mne- Operation Addressing Mode Status
monic M/X E=1 or E = 0 and dir, dir, (dir) (dir, (dir) [dir] abs abs, abs, absl absl d,s (d,s)
E=0 and M/X=1 M/X = 0 Immed Accu dir x y x) ,y x y ,x ,y N V M X D I Z C
ADC Pm AL + B + Pc -> AL A + W + Pc -> A 69 65 75 72 61 71 67 6D 7D 79 6F 7F 63 73 N V . . . . Z C
AND Pm AL /\B -> AL A /\W -> A 29 25 35 32 21 31 27 2D 3D 39 2F 3F 23 33 N . . . . . Z .
ASL Pm Pc <-B <- 0 Pc <- W <- 0 0A 06 16 0E 1E N . . . . . Z C
BIT Pm AL /\B A /\W 89 24 34 2C 3C N V . . . . Z .
CMP Pm AL - B A - W C9 C5 D5 D2 C1 D1 C7 CD DD D9 CF DF C3 D3 N . . . . . Z C
CPX Px XL - B X - W E0 E4 EC N . . . . . Z C
CPY Px YL - B Y - W C0 C4 CC N . . . . . Z C
DEC Pm B - 1 -> B W - 1 -> W 3A C6 D6 CE DE N . . . . . Z .
EOR Pm AL V- B -> AL A V- W -> A 49 45 55 52 41 51 47 4D 5D 59 4F 5F 43 53 N . . . . . Z .
INC Pm B + 1 -> B W + 1 -> W 1A E6 F6 EE FE N . . . . . Z .
LDA Pm B -> AL W -> A A9 A5 B5 B2 A1 B1 B7 AD BD B9 AF BF A3 B3 N . . . . . Z .
LDX Px B -> XL W -> X A2 A6 B6 AE BE N . . . . . Z .
LDY Px B -> YL W -> Y A0 A4 B4 AC BC N . . . . . Z .
LSR Pm 0 -> B -> Pc 0 -> W -> Pc 4A 46 56 4E 5E 0 . . . . . Z C
ORA Pm AL V B -> AL A V W -> A 09 05 15 12 01 11 17 0D 1D 19 0F 1F 03 13 N . . . . . Z .
ROL Pm Pc <- B <- Pc Pc <- W <- Pc 2A 26 36 2E 3E N . . . . . Z C
ROR Pm Pc -> B -> Pc Pc -> W -> Pc 6A 66 76 6E 7E N . . . . . Z C
SBC Pm AL - B - Pc -> AL A - W - Pc -> A E9 E5 F5 F2 E1 F1 F7 ED FD F9 EF FF E3 F3 N V . . . . Z C
STA Pm AL -> B A -> W 85 95 92 81 91 97 8D 9D 99 8F 9F 83 93 . . . . . . . .
STX Px XL -> B X -> W 86 96 8E . . . . . . . .
STY Px YL -> B Y -> W 84 94 8C . . . . . . . .
STZ Pm 0 -> B 0 -> W 64 74 9C 9E . . . . . . . .
TRB Pm /AL /\ B -> B /A /\ W -> W 14 1C . . . . . . Z .
TSB Pm AL V B -> B A V W -> W 04 0C . . . . . . Z .
V logical OR B byte per effective address
/\ logical AND W word per effective address
V- logical exclusive OR r relative offset
+ arithmetic addition A Accumulator, AL low half of Accumulator
- arithmetic subtraction X Index Register, XL low half of X register
!= not equal Y Index Register, YL low half of Y register
. status bit not affected Pc carry bit
/ negation M/X effective mode bit in Status Register (Pm or Px)
Ws word per stack pointer
Bs byte per stack pointer
Notes:
BIT instruction does not affect N and V flags when using immediate
addressing mode. When using other addressing modes, the N and V flags
are respectively set to bits 7 and 6 or 15 and 14 of the addressed memory
depending on mode (byte or word).
For all Read/Modify/Write instruction addressing modes except accumulator
Add 2 cycles for E=1 or E=0 and Pm=1 (8-bit mode)
Add 3 cycles for E=0 and Pm=0 (16-bit mode).
Add one cycle when indexing across page boundary and E=1 except for STA and
STZ instructions.
If E=1 then 1 -> SH and XL -> SL If E=0 then X -> S regardless of Pm or Px.
Exchanges the carry (Pc) and E bits. Whenever the E bit is set the following
registers and status bits are locked into the indicated state:
XH=0, YH=0, SH=1, Pm=1, Px=1.
Add 1 cycle if branch is taken. In Emulation (E= 1 ) mode only --add 1 cycle
if the branch is taken and crosses a page boundary.
Add 1 cycle in Emulation mode (E=1) for (dir),y; abs,x; and abs,y addressing
modes.
With TSB and TRB instruction, the Z flag is set or cleared by the result
of AAB or AAW.
For all Read/Modify/Write instruction addressing modes except accumulator --
Add 2 cycles for E=1 or E=0 and Pm=1 (8-bit mode)
Add 3 cycles for E=0 and Pm=0 (16-bit mode).
Table 6. Branch, Transter, Push, Pull, and Implied Addressing Mode Instructions
Operation Operation Status
Mnemonic Bytes M/X Cycles 8 Bit Cycles 16 Bit Implied Stack Relative N V M X D I Z C Mnemonic
BCC (6) 2 - 2 PC+r -> PC 2 PC+r -> PC 90 . . . . . . . . BCC
BCS (6) 2 - 2 PC+r -> PC 2 PC+r -> PC B0 . . . . . . . . BCS
BEQ (6) 2 - 2 PC+r -> PC 2 PC+r -> PC F0 . . . . . . . . BEQ
BMI (6) 2 - 2 PC+r -> PC 2 PC+r -> PC 30 . . . . . . . . BMI
BNE (6) 2 - 2 PC+r -> PC 2 PC+r -> PC D0 . . . . . . . . BNE
BPL (6) 2 - 2 PC+r -> PC 2 PC+r -> PC 10 . . . . . . . . BPL
BRA (6) 2 - 2 PC+r -> PC 2 PC+r -> PC 80 . . . . . . . . BRA
BVC (6) 2 - 2 PC+r -> PC 2 PC+r -> PC 50 . . . . . . . . BVC
BVS (6) 2 - 2 PC+r -> PC 2 PC+r -> PC 70 . . . . . . . . BVS
CLC 1 - 2 0 -> Pc 2 0 -> Pc 18 . . . . . . . 0 CLC
CLD 1 - 2 0 -> Pd 2 0 -> Pd D8 . . . . 0 . . . CLD
CLI 1 - 2 0 -> Pi 2 0 -> Pi 58 . . . . . 0 . . CLI
CLV 1 - 2 0 -> Pv 2 O -> Pv B8 . 0 . . . . . . CLV
DEX 1 Px 2 XL - 1 -> XL 2 X - 1 -> X CA N . . . . . Z . DEX
DEY 1 Px 2 YL - 1 -> YL 2 Y - 1 ->Y 88 N . . . . . Z . DEY
INX 1 Px 2 XL + 1 -> XL 2 X + 1 -> X E8 N . . . . . Z . INX
INY 1 Px 2 YL + 1 -> YL 2 Y + 1 -> Y C8 N . . . . . Z . INY
NOP 1 - 2 no operation 2 no operation EA . . . . . . . . NOP
PEA 3 - 5 W->Ws, S-2 ->S 5 same F4 . . . . . . . . PEA
PEI 2 - 6 W->Ws, S-2 ->S 6 same D4 . . . . . . . . PEI
PER 3 - 6 W ->Ws, S-2 ->S 6 same 62 . . . . . . . . PER
PHA 1 Pm 3 AL->Bs, S-1 ->S 4 A ->Ws, S-2 ->S 48 . . . . . . . . PHA
PHB 1 - 3 DB->Bs, S-1 ->S 3 same 8B . . . . . . . . PHB
PHD 1 - 4 D ->Ws, S-2 ->S 4 same OB . . . . . . . . PHD
PHK 1 - 3 PB->Bs, S-1 ->S same 4B . . . . . . . . PHK
PHP 1 - 3 P ->Bs, S-1 ->S 3 same 08 . . . . . . . . PHP
PHX 1 Px 3 XL->Bs, S-1 ->S 4 X-Ws, S-2 -> S DA . . . . . . . . PHX
PHY 1 Px 3 YL->Bs, S-1 ->S 4 Y ->Ws, S-2 ->S 5A . . . . . . . . PHY
PLA 1 Pm 4 S+1 ->S, Bs -> AL 5 S+2 ->S, Ws->A 68 N . . . . . Z . PLA
PLB 1 - 4 S+1 ->S, Bs -> DB 4 same AB N . . . . . Z . PLB
PLD 1 - 5 S+2 ->S, Ws -> D 5 same 2B N . . . . . Z . PLD
PLP 1 - 4 S+1 ->S, Bs -> P 4 same 28 N V M X D I Z C PLP
PLX 1 Px 4 S+1 ->S, Bs -> XL 5 S+2 ->S, Ws->X FA N . . . . . Z . PLX
PLY 1 Px 4 S+1 ->S, Bs -> YL 5 S+2 ->S, Ws->Y 7A N . . . . . Z . PLY
SEC 1 - 2 1 -> Pc 2 1 -> Pc 38 . . . . . . . 1 SEC
SED 1 - 2 1 -> Pd 2 1 -> Pd F8 . . . . 1 . . . SED
SEI 1 - 2 1 -> Pi 2 1 -> Pi 78 . . . . . 1 . . SEI
TAX 1 Px 2 AL -> XL 2 A -> X AA N . . . . . Z . TAX
TAY 1 Px 2 AL -> YL 2 A -> Y A8 N . . . . . Z . TAY
TCD 1 - 2 A -> D 2 A -> D 5B N . . . . . Z . TCD
TCS 1 - 2 A -> S A -> S 1B . . . . . . . . TCS
TDC 1 - 2 D -> A 2 D -> A 7B N . . . . . Z . TDC
TSC 1 - 2 S -> A 2 S -> A 3B N . . . . . Z . TSC
TSX 1 Px 2 SL -> XL 2 S -> X BA N . . . . . Z . TSX
TXA 1 Pm 2 XL -> AL 2 X -> A 8A N . . . . . Z . TXA
TXS 1 - 2 see note 4 2 X -> S 9A . . . . . . . . TXS
TXY 1 Px 2 XL -> YL 2 X -> Y 9B N . . . . . Z . TXY
TYA 1 Pm 2 YL -> AL 2 Y -> A 98 N . . . . . Z . TYA
TYX 1 Px 2 YL -> XL 2 Y -> X BB N . . . . . Z . TYX
XCE 1 - 2 see note 5 2 see note 5 FB . . . . . . . C XCE
See Notes on page 13.
Table 7. Other Addressing Mode Instructions
Status
Mnemonic Addressing Mode Opcode Cycles Bytes N V M X D I Z C Mnemonic Function
BRK stack 00 7/8 2 . . . . 0 1 . . BRK See discussion in Interrupt Processing Sequence section.
BRL relative long 82 3 3 . . . . . . . . BRL PC+r -> PC where -32768 < r < 32767.
COP stack 02 7/8 2 . . . . 0 1 . . COP See discussion in Interrupt Processing Sequence section.
JML absolute indirect DC 6 3 JMLW -> PC, B-PB
JMP absolute 4C 3 3 . . . . . . . . JMP W -> PC
JMP absolute indirect 6C 5 3 . . . . . . . . JMP W -> PC
JMP absolute indexed indirect 7C 6 3 . . . . . . . . JMP W -> PC
JMP absolute long 5C 4 4 JMP W -> PC, B -> PB
JSL absolute long 22 8 4 . . . . . . . . JSL PB -> Bs, S-1 -S, PC -> Ws, S-2 -> S, W -> PC, B -> PB
JSR absolute 20 6 3 . . . . . . . JSR PC -> Ws, S-2 -> S, W -> PC
JSR absolute indexed indirect FC 6 3 . . . . . . . . JSR PC -> Ws, S-2 -> S, W -> PC
MVN block 54 7/byte 3 . . . . . . . . MVN See discussion in Addressing Mode section
MVP block 44 7/byte 3 . . . . . . . . MVP
REP immediate C2 3 2 N V M X D I Z C REP P /\ /B -> P
RTI stack 40 6/7 1 N V M X D I Z C RTI S+1 -> S, Bs -> P, S+2 -> S, Ws -> PC,
if E=0 then S+1 -> S, Bs -> PB
RTL stack 6B 6 1 . . . . . . . . RTL S+2 -> S, Ws~1 -> PC, S+1 -> S, Bs -> PB
RTS stack 60 6 1 . . . . . . . . RTS S+2 -> S, Ws+1 -> PC
SEP immediate E2 3 2 N V M X D I Z C SEP PVB -> P
STP implied DB 3+ 1 . . . . . . . . STP Stop the clock. Requires reset to continue.
WAI implied CB 3+ 1 . . . . . . . . WAI Wait for inte-rupt. RDY held low until Interrupt.
XBA implied EB 3 1 N . . . . . Z . XBA Swap AH and AL. Status bits reflect final condition of AL.
Notes on page 13.
16

View File

@ -0,0 +1,61 @@
Interrupt Processing Sequence
The interrupt processing sequence is initiated as the direct result of hard-
vare Abort, Interrupt Request, Non-Maskable Interrupt, or Reset inputs.
The interrupt sequence can also be initiated as a result of the Break or
Co-Processor instructions within the software. The following listings
describe the function of each cycle in the interrupt processing sequence:
Hardware Interrupt /ABORT, /IRQ, /NMI, /RES Inputs
Cycle No.
E = 0 E = 1 Address Data R/W SYNC VDA VPA VP Description
1 1 PC X 1 1 1 1 1 Internal Operation
2 2 PC X 1 0 0 0 1 Internal Operation
3 [1] S PB 0 0 1 0 1 Write PB to Stack, S-1ÑS
4 3 S PCH [2] 0[3] 0 1 0 1 Write PCH to Stack, S-1ÑS
5 4 S PCL 12] 0[3] 0 1 0 1 Write PCL to Stack, S-1ÑS
6 5 S P [4] 0[3] 0 1 0 1 Write P to Stack, S-1ÑS
7 6 VL (VL) 1 0 1 0 0 Read Vector Low Byte,
0->PD, 1->P1, OO->PB
8 7 VH (VH) 1 0 1 0 0 Read Vector High 8yte
Software Interrupt - BRK, COP Instructions
Cycle No.
E = 0 E = 1 Address Data R/W SYNC VDA VPA VP Description
1 1 PC-2 X 1 1 1 1 1 Opcode
2 2 PC-1 X 1 0 0 1 1 Signature
3 111 S PB 0 0 1 0 1 Write PB to Stack, S-1ÑS
4 3 S PCH 0 0 1 0 1 Write PCH to Stack, S-1 - S
5 4 S PCL 0 0 1 0 1 Write PCL to Stack, S-1ÑS
6 5 S P 0 0 1 0 1 Write P to Stack, S-1ÑS
7 6 VL (VL) 1 0 1 0 0 Read Vector Low Byte,
0ÑPo, 1ÑPl, 00ÑPB
8 7 VH (VH) 1 0 1 0 0 Read Vector High Byte
Notes:
[1] Delete this cycle in Emulation mode.
[2] Abort writes address of aborted opcode.
[3] R/W remains in the high state during Reset.
[4] In Emulation mode, bit 4 written to stack is changed to 0.
Table 3. Vector Locations
Emulation Native Priority
Name Source (E = 1) (E = 0) Level
ABORT Hardware 00FFF8,9 00FFE8,9 2
BRK Software 00FFFE,F 00FFE6,7 N/A
COP Software 00FFF4,5 00FFE4,5 N/A
IRQ Hardware 00FFFE,F 00FFEE,F 4
NMI Hardware 00FFFA,B 00FFEA,B 3
RES Hardware 00FFFC.D 00FFFC,D 1

View File

@ -0,0 +1,117 @@
Table 4. G65SC802 and G65SC816 Instruction Set -- Alphabetical Sequence
ADC Add Memory to Accumulator with Carry
AND "AND" Memory with Accumulator
ASL Shift One Bit Left, Memory or Accumulator
BCC* Branch on Carry Clear (Pe = O)
BCS* Branch on Carry Set (Pe = 1)
BEQ Branch if Equal (Pz = 1)
BIT Bit Test
BMI Branch if Result Minus (PN = 1)
BNE Branch if Not Equal (Pz = 0)
BPL Branch if Result Plus (PN = 0)
BRA Branch Always
BRK Force Break
BRL Branch Always Long
BVC Branch on Overflow Clear (Pv = 0)
BVS Branch on Overflow Set (Pv = 1)
CLC Clear Carry Flag
CLD Clear Decimal Mode
CLI Clear Interrupt Disable Bit
CLV Clear Overflow Flag
CMP* Compare Memory and Accumulator
COP Coprocessor
CPX Compare Memory and Index X
CPY Compare Memory and Index Y
DEC* Decrement Memory or Accumulator by One
DEX Decrement Index X by One
DEY Decrement Index Y by One
EOR Exclusive "OR" Memory with Accumulator
INC* Increment Memory or Accumulator by One
INX Increment Index X by One
INY Increment Index Y by One
JML** Jump Long
JMP Jump to New Location
JSL** Jump Subroutine Long
JSR Jump to New Location Saving Return Address
LDA Load Accumulator with Memory
LDX Load Index X with Memory
LDY Load Index Y with Memory
LSR Shift One Bit Right (Memory or Accumulator)
MVN Block Move Negative
MVP Block Move Positive
NOP No Operation
ORA "OR" Memory with Accumulator
PEA Push Effective Absolute Address on Stack (or Push Immediate Data on Stack)
PEI Push Effective Indirect Address on Stack (add one cycle if DL f 0)
PER Push Effective Program Counter Relative Address on Stack
PHA Push Accumulator on Stack
PHB Push Data Bank Register on Stack
PHD Push Direct Register on Stack
PHK Push Program Bank Register on Stack
PHP Push Processor Status on Stack
PHX Push Index X on Stack
PHY Push index Y on Stack
PLA Pull Accumulator from Stack
PLB Pull Data Bank Register from Stack
PLD Pull Direct Register from Stack
PLP Pull Processor Status from Stack
PLX Pull Index X from Stack
PLY Pull Index Y form Stack
REP Reset Status Bits
ROL Rotate One Bit Left (Memory or Accumulator)
ROR Rotate One Bit Right (Memory or Accumulator)
RTI Return from Interrupt
RTL Return from Subroutine Long
RTS Return from Subroutine
SBC Subtract Memory from Accumulator with Borrow
SEC Set Carry Flag
SED Set Decimal Mode
SEI Set Interrupt Disable Status
SEP Set Processor Status Bits
STA Store Accumulator in Memory
STP Stop the Clock
STX Store Index X in Memory
STY Store Index Y in Memory
STZ Store Zero in Memory
TAX Transfer Accumulator to Index X
TAY Transfer Accumulator to Index Y
TCD* Transfer Accumulator to Direct Register
TCS* Transfer Accumulator to Stack Pointer Register
TDC* Transfer Direct Register to Accumulator
TRB Test and Reset Bit
TSB Test and Set Bit
TSC* Transfer Stack Pointer Register to Accumulator
TSX Transfer Stack Pointer Register to Index X
TXA Transfer Index X to Accumulator
TXS Transfer Index X to Stack Polnter Register
TXY Transfer Index X to Index Y
TYA Transfer Index Y to Accumulator
TYX Transfer Index Y to Index X
WAI Wait for Interrupt
XBA* Exchange AH and AL
XCE Exchange Carry and Emulation Bits
*) Common Mnemonic Aliases
Mnemonic Alias
BCC BLT
BCS BGE
CMP CPA
DEC A DEA
INC A INA
TCD TAD
TCS TAS
TDC TDA
TSC TSA
XBA SWA
**) JSL should be recognized as equivalent to JSR
when it is specified with long absolute addresses.
JML is equivalent to JMP with long addressing forced.
-13-

Some files were not shown because too many files have changed in this diff Show More