diff options
author | cpldcpu <cpldcpu@gmail.com> | 2013-11-04 05:11:22 +0100 |
---|---|---|
committer | cpldcpu <cpldcpu@gmail.com> | 2013-11-04 05:11:22 +0100 |
commit | d7360925c1170acbc3a7b98c50e48350ac80fbc7 (patch) | |
tree | 6c4be92ab12aab00d17e264ef1796f05dec574f3 /firmware/usbdrv | |
parent | 819ce8ac705e9a336cb60fdb6f525a17cbc9dcb3 (diff) | |
download | micronucleus-d7360925c1170acbc3a7b98c50e48350ac80fbc7.tar.gz micronucleus-d7360925c1170acbc3a7b98c50e48350ac80fbc7.tar.bz2 micronucleus-d7360925c1170acbc3a7b98c50e48350ac80fbc7.zip |
assembler version of calibrateoscillator - 1952 bytes
still needs cleaning up
Diffstat (limited to 'firmware/usbdrv')
-rw-r--r-- | firmware/usbdrv/usbdrvasm.S | 200 |
1 files changed, 199 insertions, 1 deletions
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 ;---------------------------------------------------------------------------- |