diff options
-rw-r--r-- | firmware/libs-device/osccal.h | 8 | ||||
-rw-r--r-- | firmware/usbdrv/usbdrvasm.S | 200 |
2 files changed, 203 insertions, 5 deletions
diff --git a/firmware/libs-device/osccal.h b/firmware/libs-device/osccal.h index 6f443a5..bfc5530 100644 --- a/firmware/libs-device/osccal.h +++ b/firmware/libs-device/osccal.h @@ -22,11 +22,11 @@ calibrateOscillator() from the reset hook in usbconfig.h: */ #ifndef __ASSEMBLER__ -extern void calibrateOscillator(void); -//extern void calibrateOscillatorASM(void); +//extern void calibrateOscillator(void); +extern void calibrateOscillatorASM(void); #endif -#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillator(); } -//#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM(); } +//#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillator(); } +#define USB_RESET_HOOK(resetStarts) if(!resetStarts){ calibrateOscillatorASM(); } /* This routine is an alternative to the continuous synchronization described diff --git a/firmware/usbdrv/usbdrvasm.S b/firmware/usbdrv/usbdrvasm.S index b03b709..29c634a 100644 --- a/firmware/usbdrv/usbdrvasm.S +++ b/firmware/usbdrv/usbdrvasm.S @@ -282,7 +282,81 @@ usbCrc16Append: #undef scratch -#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH +#if USB_CFG_HAVE_MEASURE_FRAME_LENGTHx +#ifdef __IAR_SYSTEMS_ASM__ +/* Register assignments for usbMeasureFrameLength 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". + */ +# define resL r16 +# define resH r17 +# define cnt16L r30 +# define cnt16H r31 +# define cntH r18 + +#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 resL r24 +# define resH r25 +# define cnt16L r24 +# define cnt16H r25 +# define cntH r26 +#endif +# define cnt16 cnt16L + +; extern unsigned usbMeasurePacketLength(void); +; returns time between two idle strobes in multiples of 7 CPU clocks +.global usbMeasureFrameLength +usbMeasureFrameLength: + ldi cntH, 6 ; wait ~ 10 ms for D- == 0 + clr cnt16L + clr cnt16H +usbMFTime16: + dec cntH + breq usbMFTimeout +usbMFWaitStrobe: ; first wait for D- == 0 (idle strobe) + sbiw cnt16, 1 ;[0] [6] + breq usbMFTime16 ;[2] + sbic USBIN, USBMINUS ;[3] + rjmp usbMFWaitStrobe ;[4] +usbMFWaitIdle: ; then wait until idle again + sbis USBIN, USBMINUS ;1 wait for D- == 1 + rjmp usbMFWaitIdle ;2 + ldi cnt16L, 1 ;1 represents cycles so far + clr cnt16H ;1 +usbMFWaitLoop: + in cntH, USBIN ;[0] [7] + adiw cnt16, 1 ;[1] + breq usbMFTimeout ;[3] + andi cntH, USBMASK ;[4] + brne usbMFWaitLoop ;[5] +usbMFTimeout: +#if resL != cnt16L + mov resL, cnt16L + mov resH, cnt16H +#endif + ret + +#undef resL +#undef resH +#undef cnt16 +#undef cnt16L +#undef cnt16H +#undef cntH + +#endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */ + + +#if USB_CFG_HAVE_MEASURE_FRAME_LENGTHx #ifdef __IAR_SYSTEMS_ASM__ /* Register assignments for usbMeasureFrameLengthDecreasing on IAR cc */ /* Calling conventions on IAR: @@ -350,6 +424,130 @@ usbDFWaitLoop: #endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */ + + +#if USB_CFG_HAVE_MEASURE_FRAME_LENGTH +#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". + */ + +# define resL r16 +# define resH r17 +# define cnt16L r30 +# define cnt16H r31 +# define cntH r18 + +#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 i, 10 ; 10 iterations + + ldi opD, 255 + + ldi try, 128 ; calibration start value + ldi stp, 64 ; initial step width + +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) +#define usbok +#endif + +#if (F_CPU == 12800000) + ldi cnt16L, lo8(2557) + ldi cnt16H, hi8(2557) +#define usbok +#endif + +#ifndef usbok + #error "calibrateOscillatorASM: no delayvalues defined for this F_CPU setting" +#endif +#undef usbok + +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 usbCOstepnotzero + cp opD, cnt16L + brcs usbCOnoimprovement + in opV, OSCCAL + mov opD, cnt16L +usbCOnoimprovement: + ldi stp, 1 +usbCOstepnotzero: + 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 + + +#endif /* USB_CFG_HAVE_MEASURE_FRAME_LENGTH */ + + + ;---------------------------------------------------------------------------- ; Now include the clock rate specific code ;---------------------------------------------------------------------------- |