mirror of
https://github.com/digistump/DigistumpArduino.git
synced 2025-09-17 17:32:25 -07:00
change folder names, remove duplicate DigiJoystick folder
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
This is the Readme file for the libs-device directory. This directory contains
|
||||
code snippets which may be useful for USB device firmware.
|
||||
|
||||
|
||||
WHAT IS INCLUDED IN THIS DIRECTORY?
|
||||
===================================
|
||||
|
||||
osccal.c and osccal.h
|
||||
This module contains a function which calibrates the AVR's built-in RC
|
||||
oscillator based on the USB frame clock. See osccal.h for a documentation
|
||||
of the API.
|
||||
|
||||
osctune.h
|
||||
This header file contains a code snippet for usbconfig.h. With this code,
|
||||
you can keep the AVR's internal RC oscillator in sync with the USB frame
|
||||
clock. This is a continuous synchronization, not a single calibration at
|
||||
USB reset as with osccal.c above. Please note that this code works only
|
||||
if D- is wired to the interrupt, not D+.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
(c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH.
|
||||
http://www.obdev.at/
|
@@ -0,0 +1,63 @@
|
||||
/* Name: osccal.c
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-10
|
||||
* 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: osccal.c 762 2009-08-12 17:10:30Z cs $
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#ifndef uchar
|
||||
#define uchar unsigned char
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* ------------------------ Oscillator Calibration ------------------------- */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
/* Calibrate the RC oscillator. Our timing reference is the Start Of Frame
|
||||
* signal (a single SE0 bit) repeating every millisecond immediately after
|
||||
* a USB RESET. We first do a binary search for the OSCCAL value and then
|
||||
* optimize this value with a neighboorhod search.
|
||||
*/
|
||||
void calibrateOscillator(void)
|
||||
{
|
||||
uchar step = 128;
|
||||
uchar trialValue = 0, optimumValue;
|
||||
int x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
|
||||
|
||||
/* do a binary search: */
|
||||
do{
|
||||
OSCCAL = trialValue + step;
|
||||
x = usbMeasureFrameLength(); /* proportional to current real frequency */
|
||||
if(x < targetValue) /* frequency still too low */
|
||||
trialValue += step;
|
||||
step >>= 1;
|
||||
}while(step > 0);
|
||||
/* We have a precision of +/- 1 for optimum OSCCAL here */
|
||||
/* now do a neighborhood search for optimum value */
|
||||
optimumValue = trialValue;
|
||||
optimumDev = x; /* this is certainly far away from optimum */
|
||||
for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
|
||||
x = usbMeasureFrameLength() - targetValue;
|
||||
if(x < 0)
|
||||
x = -x;
|
||||
if(x < optimumDev){
|
||||
optimumDev = x;
|
||||
optimumValue = OSCCAL;
|
||||
}
|
||||
}
|
||||
OSCCAL = optimumValue;
|
||||
}
|
||||
/*
|
||||
Note: This calibration algorithm may try OSCCAL values of up to 192 even if
|
||||
the optimum value is far below 192. It may therefore exceed the allowed clock
|
||||
frequency of the CPU in low voltage designs!
|
||||
You may replace this search algorithm with any other algorithm you like if
|
||||
you have additional constraints such as a maximum CPU clock.
|
||||
For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g.
|
||||
ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in
|
||||
both regions.
|
||||
*/
|
@@ -0,0 +1,106 @@
|
||||
GAS LISTING C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s page 1
|
||||
|
||||
|
||||
1 .file "osccal.c"
|
||||
2 __SREG__ = 0x3f
|
||||
3 __SP_H__ = 0x3e
|
||||
4 __SP_L__ = 0x3d
|
||||
5 __CCP__ = 0x34
|
||||
6 __tmp_reg__ = 0
|
||||
7 __zero_reg__ = 1
|
||||
8 .text
|
||||
9 .global calibrateOscillator
|
||||
10 .type calibrateOscillator, @function
|
||||
11 calibrateOscillator:
|
||||
12 0000 FF92 push r15
|
||||
13 0002 0F93 push r16
|
||||
14 0004 1F93 push r17
|
||||
15 0006 CF93 push r28
|
||||
16 0008 DF93 push r29
|
||||
17 /* prologue: function */
|
||||
18 /* frame size = 0 */
|
||||
19 000a 80E8 ldi r24,lo8(-128)
|
||||
20 000c F82E mov r15,r24
|
||||
21 000e 00E0 ldi r16,lo8(0)
|
||||
22 0010 C0E0 ldi r28,lo8(0)
|
||||
23 0012 D0E0 ldi r29,hi8(0)
|
||||
24 .L4:
|
||||
25 0014 102F mov r17,r16
|
||||
26 0016 1F0D add r17,r15
|
||||
27 0018 11BF out 81-32,r17
|
||||
28 001a 00D0 rcall usbMeasureFrameLength
|
||||
29 001c 29E0 ldi r18,hi8(2356)
|
||||
30 001e 8433 cpi r24,lo8(2356)
|
||||
31 0020 9207 cpc r25,r18
|
||||
32 0022 04F0 brlt .L2
|
||||
33 0024 102F mov r17,r16
|
||||
34 .L2:
|
||||
35 0026 F694 lsr r15
|
||||
36 0028 2196 adiw r28,1
|
||||
37 002a C830 cpi r28,8
|
||||
38 002c D105 cpc r29,__zero_reg__
|
||||
39 002e 01F0 breq .L3
|
||||
40 0030 012F mov r16,r17
|
||||
41 0032 00C0 rjmp .L4
|
||||
42 .L3:
|
||||
43 0034 1150 subi r17,lo8(-(-1))
|
||||
44 0036 11BF out 81-32,r17
|
||||
45 0038 1F5F subi r17,lo8(-(1))
|
||||
46 003a 012F mov r16,r17
|
||||
47 003c EC01 movw r28,r24
|
||||
48 003e 00C0 rjmp .L5
|
||||
49 .L8:
|
||||
50 0040 00D0 rcall usbMeasureFrameLength
|
||||
51 0042 8453 subi r24,lo8(-(-2356))
|
||||
52 0044 9940 sbci r25,hi8(-(-2356))
|
||||
53 0046 97FF sbrs r25,7
|
||||
54 0048 00C0 rjmp .L6
|
||||
55 004a 9095 com r25
|
||||
56 004c 8195 neg r24
|
||||
57 004e 9F4F sbci r25,lo8(-1)
|
||||
GAS LISTING C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s page 2
|
||||
|
||||
|
||||
58 .L6:
|
||||
59 0050 8C17 cp r24,r28
|
||||
60 0052 9D07 cpc r25,r29
|
||||
61 0054 04F4 brge .L7
|
||||
62 0056 01B7 in r16,81-32
|
||||
63 0058 EC01 movw r28,r24
|
||||
64 .L7:
|
||||
65 005a 81B7 in r24,81-32
|
||||
66 005c 8F5F subi r24,lo8(-(1))
|
||||
67 005e 81BF out 81-32,r24
|
||||
68 .L5:
|
||||
69 0060 21B7 in r18,81-32
|
||||
70 0062 30E0 ldi r19,lo8(0)
|
||||
71 0064 812F mov r24,r17
|
||||
72 0066 90E0 ldi r25,lo8(0)
|
||||
73 0068 0196 adiw r24,1
|
||||
74 006a 8217 cp r24,r18
|
||||
75 006c 9307 cpc r25,r19
|
||||
76 006e 04F4 brge .L8
|
||||
77 0070 01BF out 81-32,r16
|
||||
78 /* epilogue start */
|
||||
79 0072 DF91 pop r29
|
||||
80 0074 CF91 pop r28
|
||||
81 0076 1F91 pop r17
|
||||
82 0078 0F91 pop r16
|
||||
83 007a FF90 pop r15
|
||||
84 007c 0895 ret
|
||||
85 .size calibrateOscillator, .-calibrateOscillator
|
||||
GAS LISTING C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s page 3
|
||||
|
||||
|
||||
DEFINED SYMBOLS
|
||||
*ABS*:00000000 osccal.c
|
||||
C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s:2 *ABS*:0000003f __SREG__
|
||||
C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s:3 *ABS*:0000003e __SP_H__
|
||||
C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s:4 *ABS*:0000003d __SP_L__
|
||||
C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s:5 *ABS*:00000034 __CCP__
|
||||
C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s:6 *ABS*:00000000 __tmp_reg__
|
||||
C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s:7 *ABS*:00000001 __zero_reg__
|
||||
C:\Users\Erik\AppData\Local\Temp/ccabieCZ.s:11 .text:00000000 calibrateOscillator
|
||||
|
||||
UNDEFINED SYMBOLS
|
||||
usbMeasureFrameLength
|
@@ -0,0 +1,65 @@
|
||||
/* Name: osccal.h
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-04-10
|
||||
* 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: osccal.h 762 2009-08-12 17:10:30Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
General Description:
|
||||
This module contains a function which calibrates the AVR's internal RC
|
||||
oscillator so that the CPU runs at F_CPU (F_CPU is a macro which must be
|
||||
defined when the module is compiled, best passed in the compiler command
|
||||
line). The time reference is the USB frame clock of 1 kHz available
|
||||
immediately after a USB RESET condition. Timing is done by counting CPU
|
||||
cycles, so all interrupts must be disabled while the calibration runs. For
|
||||
low level timing measurements, usbMeasureFrameLength() is called. This
|
||||
function must be enabled in usbconfig.h by defining
|
||||
USB_CFG_HAVE_MEASURE_FRAME_LENGTH to 1. It is recommended to call
|
||||
calibrateOscillator() from the reset hook in usbconfig.h:
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#include <avr/interrupt.h> // for sei()
|
||||
extern void calibrateOscillator(void);
|
||||
#endif
|
||||
#define USB_RESET_HOOK(resetStarts) if(!resetStarts){cli(); calibrateOscillator(); sei();}
|
||||
|
||||
/*
|
||||
This routine is an alternative to the continuous synchronization described
|
||||
in osctune.h.
|
||||
|
||||
Algorithm used:
|
||||
calibrateOscillator() first does a binary search in the OSCCAL register for
|
||||
the best matching oscillator frequency. Then it does a next neighbor search
|
||||
to find the value with the lowest clock rate deviation. It is guaranteed to
|
||||
find the best match among neighboring values, but for version 5 oscillators
|
||||
(which have a discontinuous relationship between OSCCAL and frequency) a
|
||||
better match might be available in another OSCCAL region.
|
||||
|
||||
Limitations:
|
||||
This calibration algorithm may try OSCCAL values of up to 192 even if the
|
||||
optimum value is far below 192. It may therefore exceed the allowed clock
|
||||
frequency of the CPU in low voltage designs!
|
||||
Precision depends on the OSCCAL vs. frequency dependency of the oscillator.
|
||||
Typical precision for an ATMega168 (derived from the OSCCAL vs. F_RC diagram
|
||||
in the data sheet) should be in the range of 0.4%. Only the 12.8 MHz and
|
||||
16.5 MHz versions of V-USB (with built-in receiver PLL) can tolerate this
|
||||
deviation! All other frequency modules require at least 0.2% precision.
|
||||
*/
|
||||
|
||||
#ifndef __OSCCAL_H_INCLUDED__
|
||||
#define __OSCCAL_H_INCLUDED__
|
||||
|
||||
//void calibrateOscillator(void);
|
||||
/* This function calibrates the RC oscillator so that the CPU runs at F_CPU.
|
||||
* It MUST be called immediately after the end of a USB RESET condition!
|
||||
* Disable all interrupts during the call!
|
||||
* It is recommended that you store the resulting value in EEPROM so that a
|
||||
* good guess value is available after the next reset.
|
||||
*/
|
||||
|
||||
|
||||
#endif /* __OSCCAL_H_INCLUDED__ */
|
Binary file not shown.
@@ -0,0 +1,88 @@
|
||||
/* Name: osctune.h
|
||||
* Author: Christian Starkjohann
|
||||
* Creation Date: 2008-10-18
|
||||
* 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: osctune.h 692 2008-11-07 15:07:40Z cs $
|
||||
*/
|
||||
|
||||
/*
|
||||
General Description:
|
||||
This file is declared as C-header file although it is mostly documentation
|
||||
how the RC oscillator can be kept in sync to the USB frame rate. The code
|
||||
shown here must be added to usbconfig.h or this header file is included from
|
||||
there. This code works only if D- is wired to the interrupt, not D+!!!
|
||||
|
||||
This is an alternative to the osccal routine in osccal.c. It has the advantage
|
||||
that the synchronization is done continuously and that it has more compact
|
||||
code size. The disadvantages are slow synchronization (it may take a while
|
||||
until the driver works), that messages immediately after the SOF pulse may be
|
||||
lost (and need to be retried by the host) and that the interrupt is on D-
|
||||
contrary to most examples.
|
||||
|
||||
You may want to store a good calibration value in EEPROM for the next startup.
|
||||
You know that the calibration value is good when the first USB message is
|
||||
received. Do not store the value on every received message because the EEPROM
|
||||
has a limited endurance.
|
||||
|
||||
Notes:
|
||||
(*) You must declare the global character variable "lastTimer0Value" in your
|
||||
main code.
|
||||
|
||||
(*) Timer 0 must be free running (not written by your code) and the prescaling
|
||||
must be consistent with the TIMER0_PRESCALING define.
|
||||
|
||||
(*) Good values for Timer 0 prescaling depend on how precise the clock must
|
||||
be tuned and how far away from the default clock rate the target clock is.
|
||||
For precise tuning, choose a low prescaler factor, for a broad range of tuning
|
||||
choose a high one. A prescaler factor of 64 is good for the entire OSCCAL
|
||||
range and allows a precision of better than +/-1%. A prescaler factor of 8
|
||||
allows tuning to slightly more than +/-6% of the default frequency and is
|
||||
more precise than one step of OSCCAL. It is therefore not suitable to tune an
|
||||
8 MHz oscillator to 12.5 MHz.
|
||||
|
||||
Thanks to Henrik Haftmann for the idea to this routine!
|
||||
*/
|
||||
|
||||
#define TIMER0_PRESCALING 64 /* must match the configuration for TIMER0 in main */
|
||||
#define TOLERATED_DEVIATION_PPT 5 /* max clock deviation before we tune in 1/10 % */
|
||||
/* derived constants: */
|
||||
#define EXPECTED_TIMER0_INCREMENT ((F_CPU / (1000 * TIMER0_PRESCALING)) & 0xff)
|
||||
#define TOLERATED_DEVIATION (TOLERATED_DEVIATION_PPT * F_CPU / (1000000 * TIMER0_PRESCALING))
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
macro tuneOsccal
|
||||
push YH ;[0]
|
||||
in YL, TCNT0 ;[2]
|
||||
lds YH, lastTimer0Value ;[3]
|
||||
sts lastTimer0Value, YL ;[5]
|
||||
sub YL, YH ;[7] time passed since last frame
|
||||
subi YL, EXPECTED_TIMER0_INCREMENT ;[8]
|
||||
#if OSCCAL > 0x3f /* outside I/O addressable range */
|
||||
lds YH, OSCCAL ;[6]
|
||||
#else
|
||||
in YH, OSCCAL ;[6] assembler modle uses __SFR_OFFSET == 0
|
||||
#endif
|
||||
cpi YL, TOLERATED_DEVIATION + 1 ;[10]
|
||||
brmi notTooHigh ;[11]
|
||||
subi YH, 1 ;[12] clock rate was too high
|
||||
; brcs tuningOverflow ; optionally check for overflow
|
||||
rjmp osctuneDone ;[13]
|
||||
notTooHigh:
|
||||
cpi YL, -TOLERATED_DEVIATION ;[13]
|
||||
brpl osctuneDone ;[14] not too low
|
||||
inc YH ;[15] clock rate was too low
|
||||
; breq tuningOverflow ; optionally check for overflow
|
||||
osctuneDone:
|
||||
#if OSCCAL > 0x3f /* outside I/O addressable range */
|
||||
sts OSCCAL, YH ;[12-13] store tuned value
|
||||
#else
|
||||
out OSCCAL, YH ;[12-13] store tuned value
|
||||
#endif
|
||||
tuningOverflow:
|
||||
pop YH ;[17]
|
||||
endm ;[19] max number of cycles
|
||||
#endif
|
||||
|
||||
#define USB_SOF_HOOK tuneOsccal
|
Reference in New Issue
Block a user