diff options
Diffstat (limited to 'firmware/libs-device')
| -rw-r--r-- | firmware/libs-device/Readme.txt | 22 | ||||
| -rw-r--r-- | firmware/libs-device/osccal.c | 183 | ||||
| -rw-r--r-- | firmware/libs-device/osccal.h | 57 | ||||
| -rw-r--r-- | firmware/libs-device/osccalASM.S | 228 | ||||
| -rw-r--r-- | firmware/libs-device/osctune.h | 88 | 
5 files changed, 0 insertions, 578 deletions
| diff --git a/firmware/libs-device/Readme.txt b/firmware/libs-device/Readme.txt deleted file mode 100644 index 76518dc..0000000 --- a/firmware/libs-device/Readme.txt +++ /dev/null @@ -1,22 +0,0 @@ -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/ diff --git a/firmware/libs-device/osccal.c b/firmware/libs-device/osccal.c deleted file mode 100644 index 8debe49..0000000 --- a/firmware/libs-device/osccal.c +++ /dev/null @@ -1,183 +0,0 @@ -/* 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> -#include <avr/interrupt.h> -#ifndef uchar -#define uchar   unsigned char -#endif - -int usbMeasureFrameLengthDecreasing(int); - -/* ------------------------------------------------------------------------- */ -/* ------------------------ 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.  - * - *  - * Optimized version by cpldcpu@gmail.com, Nov 3rd 2013. - * - * Benefits: - *	  - Codesize reduced by 54 bytes. - *    - Improved robustness due to removing timeout from frame length measurement and  - *	    inserted NOP after OSCCAL writes. - * - * Changes: - *    - The new routine performs a combined binary and neighborhood search - *      in a single loop. - *      Note that the neighborhood search is necessary due to the quasi-monotonic  - *      nature of OSCCAL. (See Atmel application note AVR054). - *	  - Inserted NOP after writes to OSCCAL to avoid CPU errors during oscillator - *      stabilization.  - *    - Implemented new routine to measure frame time "usbMeasureFrameLengthDecreasing". - *		This routine takes the target time as a parameter and returns the deviation. - *	  - usbMeasureFrameLengthDecreasing measures in multiples of 5 cycles and is thus - *	    slighly more accurate. - *	  - usbMeasureFrameLengthDecreasing does not support time out anymore. The original - *	    implementation returned zero in case of time out, which would have caused the old - *      calibrateOscillator() implementation to increase OSSCAL to 255, effictively - *      overclocking and most likely crashing the CPU. The new implementation will enter - *		an infinite loop when no USB activity is encountered. The user program should - *      use the watchdog to escape from situations like this. -  *  - * This routine will work both on controllers with and without split OSCCAL range. - * The first trial value is 128 which is the lowest value of the upper OSCCAL range - * on Attiny85 and will effectively limit the search to the upper range, unless the - * RC oscillator frequency is unusually high. Under normal operation, the highest  - * tested frequency setting is 192. This corresponds to ~20 Mhz core frequency and  - * is still within spec for a 5V device. - */ - -void    calibrateOscillator(void) -{ -	uchar       step, trialValue, optimumValue; -	int         x, targetValue; -	uchar		optimumDev; -	uchar		i,xl; -	 -	targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5);  /* Time is measured in multiples of 5 cycles. Target is 0.999µs */ -    optimumDev = 0xff;    -  //  optimumValue = OSCCAL;  -	step=64; -	trialValue = 128; -	 -	cli(); // disable interrupts -	 -	/* -		Performs seven iterations of a binary search (stepwidth decreasing9 -		with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum) -	*/ - -	for(i=0; i<10; i++){ -		OSCCAL = trialValue; -		asm volatile(" NOP"); -	 -		x = usbMeasureFrameLengthDecreasing(targetValue); - -		if(x < 0)             /* frequency too high */ -		{ -			trialValue -= step; -			xl=(uchar)-x; -		} -		else                  /* frequency too low */ -		{ -			trialValue += step;			 -			xl=(uchar)x; -		} -		 -		/* -			Halve stepwidth to perform binary search. Logical oring with 1 to ensure step is never equal to zero.  -			This results in a neighborhood search with stepwidth 1 after binary search is finished.			 -			Once the neighbourhood search stage is reached, x will be smaller than +-255, hence more code can be -			saved by only working with the lower 8 bits. -		*/ -		 -		step >>= 1; -		 -		if (step==0) -		{ -			step=1;			 -			if(xl <= optimumDev){ -				optimumDev = xl; -				optimumValue = OSCCAL; -			} -		} - -	} - -	OSCCAL = optimumValue; -	asm volatile(" NOP"); -	 -	sei(); // enable interrupts -} - -void    calibrateOscillator_old(void) -{ -	uchar       step, trialValue, optimumValue; -	int         x, optimumDev, targetValue; -	uchar		i; -	 -	targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5);  /* Time is measured in multiples of 5 cycles. Target is 0.999µs */ -    optimumDev = 0x7f00;   // set to high positive value -    optimumValue = OSCCAL;  -	step=64; -	trialValue = 128; -	 -	/* -		Performs seven iterations of a binary search (stepwidth decreasing9 -		with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum) -	*/ - -	for(i=0; i<10; i++){ -		OSCCAL = trialValue; -		asm volatile(" NOP"); -	 -		x = usbMeasureFrameLengthDecreasing(targetValue); - -		if(x < 0)             /* frequency too high */ -		{ -			trialValue -= step; -			x = -x; -		} -		else                  /* frequency too low */ -		{ -			trialValue += step;			 -		} -		 -		/* -			Halve stepwidth to perform binary search. Logical oring with 1 to ensure step is never equal to zero.  -			This results in a neighborhood search with stepwidth 1 after binary search is finished.			 -		*/ -		 -		step >>= 1; -		step |=1;	 - -		if(x < optimumDev){ -			optimumDev = x; -			optimumValue = OSCCAL; -		} -	} - -	OSCCAL = optimumValue; -	asm volatile(" NOP"); -} - -/* -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. -*/ diff --git a/firmware/libs-device/osccal.h b/firmware/libs-device/osccal.h deleted file mode 100644 index af37a43..0000000 --- a/firmware/libs-device/osccal.h +++ /dev/null @@ -1,57 +0,0 @@ -/* Name: osccal.h - * Author: Christian Starkjohann - * Creation Date: 2008-04-10 - * Changes 2013-11-04 cpldcpu@gmail.com - * Tabsize: 4 - * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - */ - -/* -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.  -The size optimized assembler implementation includes its own implementation -of usbMeasureFrameLength. Therefore USB_CFG_HAVE_MEASURE_FRAME_LENGTH should  -be set to 0 to avoid including unused code sections. It is recommended to call -calibrateOscillatorASM() from the reset hook in usbconfig.h by including osccal.h: - -#include "osccal.h" - -This routine is an alternative to the continuous synchronization described -in osctune.h. - -Algorithm used:  See osccalASM.x - -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__ - -#ifndef __ASSEMBLER__ -	void calibrateOscillatorASM(void); -#	define USB_RESET_HOOK(resetStarts)  if(!resetStarts){ calibrateOscillatorASM();} -#	define USB_CFG_HAVE_MEASURE_FRAME_LENGTH   0 -#endif	 -/* 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__ */ diff --git a/firmware/libs-device/osccalASM.S b/firmware/libs-device/osccalASM.S deleted file mode 100644 index 9a317f1..0000000 --- a/firmware/libs-device/osccalASM.S +++ /dev/null @@ -1,228 +0,0 @@ -/* Name: osccalASM.S - * Author: cpldcpu@gmail.com - * Creation Date: 2013-11-3 - * Tabsize: 4 - * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt) - */ - -/* 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.  - * - * - * Benefits: - *	  - Codesize reduced by 90 bytes. - *    - Improved robustness due to removing timeout from frame length measurement and  - *	    inserted NOP after OSCCAL writes. - * - * Changes: - *    - The new routine performs a combined binary and neighborhood search - *      in a single loop. - *      Note that the neighborhood search is necessary due to the quasi-monotonic  - *      nature of OSCCAL. (See Atmel application note AVR054). - *	  - Inserted NOP after writes to OSCCAL to avoid CPU errors during oscillator - *      stabilization.  - *    - Implemented new routine to measure frame time "usbMeasureFrameLengthDecreasing". - *		This routine takes the target time as a parameter and returns the deviation. - *	  - usbMeasureFrameLengthDecreasing measures in multiples of 5 cycles and is thus - *	    slighly more accurate. - *	  - usbMeasureFrameLengthDecreasing does not support time out anymore. The original - *	    implementation returned zero in case of time out, which would have caused the old - *      calibrateOscillator() implementation to increase OSSCAL to 255, effictively - *      overclocking and most likely crashing the CPU. The new implementation will enter - *		an infinite loop when no USB activity is encountered. The user program should - *      use the watchdog to escape from situations like this. -  *  - * This routine will work both on controllers with and without split OSCCAL range. - * The first trial value is 128 which is the lowest value of the upper OSCCAL range - * on Attiny85 and will effectively limit the search to the upper range, unless the - * RC oscillator frequency is unusually high. Under normal operation, the highest  - * tested frequency setting is 192. This corresponds to ~20 Mhz core frequency and  - * is still within spec for a 5V device. - */ -  - -#define __SFR_OFFSET 0      /* used by avr-libc's register definitions */ -#include "./usbdrv/usbdrv.h"         /* for common defs */ - -#ifdef __IAR_SYSTEMS_ASM__ -/* Register assignments for usbMeasureFrameLengthDecreasing on IAR cc */ -/* Calling conventions on IAR: - * First parameter passed in r16/r17, second in r18/r19 and so on. - * Callee must preserve r4-r15, r24-r29 (r28/r29 is frame pointer) - * Result is passed in r16/r17 - * In case of the "tiny" memory model, pointers are only 8 bit with no - * padding. We therefore pass argument 1 as "16 bit unsigned". - */ - -//Untested - -#   define i		r20	 -#   define opV		r19 -#   define opD		r18 -#   define try		r21 -#   define stp		r22 - -#   define cnt16L   r30 -#   define cnt16H   r31 - - -#else  /* __IAR_SYSTEMS_ASM__ */  -/* Register assignments for usbMeasureFrameLength on gcc */ -/* Calling conventions on gcc: - * First parameter passed in r24/r25, second in r22/23 and so on. - * Callee must preserve r1-r17, r28/r29 - * Result is passed in r24/r25 - */ - -#   define i		r20	 -#   define opV		r19 -#   define opD		r18 -#   define try		r27 -#   define stp		r26 -#   define cnt16L   r24 -#   define cnt16H   r25 -#endif -#   define cnt16    cnt16L - -; extern void calibrateOscillatorASM(void); - -.global calibrateOscillatorASM -calibrateOscillatorASM: - -	cli -	ldi		opD, 255	 - -	ldi		try, 128	; calibration start value -	ldi		stp, 64		; initial step width -	ldi		i, 10		; 10 iterations - -usbCOloop: - -	out		OSCCAL, try -	nop - -	; Delay values = F_CPU * 999e-6 / 5 + 0.5 -	 -#if (F_CPU == 16500000) -	ldi		cnt16L, lo8(3297) -	ldi		cnt16H, hi8(3297) -#elif (F_CPU == 12800000) -	ldi		cnt16L, lo8(2557) -	ldi		cnt16H, hi8(2557) -#else -	#error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting" -#endif - -usbCOWaitStrobe:            ; first wait for D- == 0 (idle strobe) -    sbic    USBIN, USBMINUS ; -    rjmp    usbCOWaitStrobe ; -usbCOWaitIdle:              ; then wait until idle again -    sbis    USBIN, USBMINUS ;1 wait for D- == 1 -    rjmp    usbCOWaitIdle   ;2 -usbCOWaitLoop: -	sbiw	cnt16,1			;[0] [5] -    sbic    USBIN, USBMINUS ;[2]  -    rjmp    usbCOWaitLoop   ;[3] - -	sbrs	cnt16H, 7		;delay overflow? -	rjmp	usbCOclocktoolow -	sub		try, stp -	neg		cnt16L -	rjmp	usbCOclocktoohigh -usbCOclocktoolow: -	add		try, stp -usbCOclocktoohigh: -	lsr		stp -	brne	usbCOnoneighborhoodsearch -	cp		opD, cnt16L -	brcs	usbCOnoimprovement -	in		opV, OSCCAL -	mov		opD, cnt16L -usbCOnoimprovement: -	ldi		stp, 1 -usbCOnoneighborhoodsearch: -	subi	i, 1 -	brne	usbCOloop - -	out		OSCCAL, opV -	nop -	sei -    ret - -#undef i -#undef opV -#undef opD -#undef try -#undef stp -#undef cnt16 -#undef cnt16L -#undef cnt16H - -/* ------------------------------------------------------------------------- */ -/* ------ Original C Implementation of improved calibrateOscillator -------- */ -/* ----------------------   for Reference only ----------------------------- */ -/* ------------------------------------------------------------------------- */ - -#if 0 -void    calibrateOscillator(void) -{ -	uchar       step, trialValue, optimumValue; -	int         x, targetValue; -	uchar		optimumDev; -	uchar		i,xl; -	 -	targetValue = (unsigned)((double)F_CPU * 999e-6 / 5.0 + 0.5);  /* Time is measured in multiples of 5 cycles. Target is 0.999µs */ -    optimumDev = 0xff;    -  //  optimumValue = OSCCAL;  -	step=64; -	trialValue = 128; -	 -	cli(); // disable interrupts -	 -	/* -		Performs seven iterations of a binary search (stepwidth decreasing9 -		with three additional steps of a neighborhood search (step=1, trialvalue will oscillate around target value to find optimum) -	*/ - -	for(i=0; i<10; i++){ -		OSCCAL = trialValue; -		asm volatile(" NOP"); -	 -		x = usbMeasureFrameLengthDecreasing(targetValue); - -		if(x < 0)             /* frequency too high */ -		{ -			trialValue -= step; -			xl=(uchar)-x; -		} -		else                  /* frequency too low */ -		{ -			trialValue += step;			 -			xl=(uchar)x; -		} -		 -		/* -			Halve stepwidth to perform binary search. At step=1 the mode changes to neighbourhood search. -			Once the neighbourhood search stage is reached, x will be smaller than +-255, hence more code can be -			saved by only working with the lower 8 bits. -		*/ -		 -		step >>= 1; -		 -		if (step==0)   // Enter neighborhood search mode -		{ -			step=1;			 -			if(xl <= optimumDev){ -				optimumDev = xl; -				optimumValue = OSCCAL; -			} -		} -	} - -	OSCCAL = optimumValue; -	asm volatile(" NOP"); -	 -	sei(); // enable interrupts -} -#endif
\ No newline at end of file diff --git a/firmware/libs-device/osctune.h b/firmware/libs-device/osctune.h deleted file mode 100644 index c751648..0000000 --- a/firmware/libs-device/osctune.h +++ /dev/null @@ -1,88 +0,0 @@ -/* 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 | 
