📄 mjoy.asm
字号:
ror temp1 ; get lowest bit to top
andi temp1,0b11100000
or temp3, temp1
sts JoystickBufferBegin+5,temp3
;;;;;;;;;;;;;;;;;;;;;;;;;
; Process Hat switch
mov temp0, temp2
lsl temp0
swap temp0
andi temp0, 0b00001111
ldi ZH, high(HatValues << 1)
ldi ZL, low(HatValues << 1)
ldi temp1, 0
add ZL, temp0
adc ZH, temp1
lpm temp0, Z ; read value from memory mapping
sts JoystickBufferBegin+6,temp0
call RestoreUpperRegisters
ldi temp3,JoystickReport2Size ;Joystick report size
SendJoystickReport:
ldi temp0, JoystickReportID ; flip report ID
eor JoystickFlags, temp0
rcall CheckAxisRanges
; simulate call to AddCRCOut
; simply push point of return onto stack
ldi temp0, low(AddCRCOutReturn) ;ROMpointer to descriptor
push temp0
ldi temp0, high(AddCRCOutReturn)
push temp0
ldi USBBufptrY,JoystickBufferBegin
ldi ByteCount,2 ;length of output buffer (only SOP and PID)
add ByteCount,temp3 ;+ number of bytes
push USBBufptrY
push ByteCount
rjmp AddCRCOut_2 ;addition of CRC to buffer
ReadButtonsRow:
nop ; for synchronization
in temp0,PIND
andi temp0,0b01111011 ;mask out PD2 and PD7 which is INT0 and Column 4
in temp1,PINB
andi temp1,0b00000100 ;extract bit PB2
or temp0,temp1 ;merge values
com temp0
andi temp0,0b01111111
ret
;*********************************************************************
;* Start the ADC conversion cycle
;*
;* Input: r18 - number of ADC channel
;*
;* Registers used:
;* r18
;*********************************************************************
StartADC10:
andi r18, 0b00000111
sts ADCChanStarted,r18 ; set last ADC channel number
ori r18, 0b01000000 ;AVCC refernce, clear ADLAR for 10 bit conversion
out ADMUX, r18
sbi ADCSRA, ADSC ; start conversion
ret
;*********************************************************************
;* Read 10bit unsigned value from ADC
;*
;* Input: r16 - number of ADC channel
;*
;* Output: r17:r16 - 10bit ADC value
;* Registers used:
;* r16, r17
;*********************************************************************
ReadADC10:
lds r17, ADCChanStarted
cp r16, r17
breq WaitForADC10 ; if conversion was started earlier then go and wait for the result
andi r16, 0b00000111 ; otherwise start the conversion
ori r16, 0b01000000 ;AVCC refernce, clear ADLAR for 10 bit conversion
out ADMUX, r16
sbi ADCSRA, ADSC ; start conversion
WaitForADC10:
sbic ADCSRA, ADSC
rjmp WaitForADC10
ldi r16, 0xFF
sts ADCChanStarted,r16 ; reset last ADC channel number
in r16,ADCL
in r17,ADCH
ret
;*********************************************************************
;* Initialize 8 bit asymmetrical Axis data from EEPROM
;*
;* Input: Z - address of 8 bit asymmetric axis structure
;* Y - EEPROM address
;*********************************************************************
Init8AsymAxis:
; Reset Update Counter
ldi r16,0
std Z + s_UpdateCntL, r16
std Z + s_UpdateCntH, r16
lds r16, EEPROMFlags
tst r16
brne LoadDefaults8
; ADC Min
movw r19:r18, ZH:ZL ; backup structure pointer
movw r21:r20, YH:YL ; backup structure pointer
adiw ZH:ZL, s_EEPROMStructStart ; point to start od EEPROM part
ldi r17, Asym8EEStructSize
call LoadStructFromEEPROM
movw ZH:ZL, r19:r18 ; restore structure pointer
movw YH:YL, r21:r20 ; restore structure pointer
; check if eeprom is valid
ldd r16, Z + s_MaxH
cpi r16, 4
brlo RetInit8
; out of range
; load range defaults
LoadDefaults8:
ldi r16, 0
std Z + s_MaxL, r16
std Z + s_MaxH, r16
ldi r16, 3
std Z + s_MinL, r16
ldi r16, 0xFF
std Z + s_MinH, r16
; Calculate Initial Coeficient
RetInit8:
call CalcCoef
ret
;*********************************************************************
;* Initialize 10 bit symmetrical Axis data from EEPROM
;*
;* Input: R17:R16 - 10bit unsigned ADC input value (center)
;* Z - address of 10 bit symmetric axis structure
;* Y - EEPROM address
;*********************************************************************
Init10SymAxis:
; store ADC Center value
std Z + s_CenterH, r17
std Z + s_CenterL, r16
; Reset Update Counter
ldi r16,0
std Z + s_UpdateCntL, r16
std Z + s_UpdateCntH, r16
lds r16, EEPROMFlags
tst r16
brne LoadDefaults10
; ADC Min
movw r19:r18, ZH:ZL ; backup structure pointer
movw r21:r20, YH:YL ; backup structure pointer
adiw ZH:ZL, s_EEPROMStructStart ; point to start od EEPROM part
ldi r17, Sym10EEStructSize
call LoadStructFromEEPROM
movw ZH:ZL, r19:r18 ; restore structure pointer
movw YH:YL, r21:r20 ; restore structure pointer
; check if eeprom is valid
ldd r16, Z + s_MaxH
cpi r16, 4
brlo ContInit10
; out of range
LoadDefaults10:
; load range defaults
ldi r16, 0
std Z + s_MaxL, r16
std Z + s_MaxH, r16
ldi r16, 3
std Z + s_MinL, r16
ldi r16, 0xFF
std Z + s_MinH, r16
ContInit10:
ldd r17, Z + s_CenterH
ldd r16, Z + s_CenterL
; Check if Center is in the range and update accordingly
; chek Lower Margin
ldd r19, Z + s_MinH
ldd r18, Z + s_MinL
cp r16, r18 ; check if value exceeds MINIMUM range
cpc r17, r19
brsh Init10Check_Max
std Z + s_MinH, r17
std Z + s_MinL, r16
ldi r17, 0 ; mark that update was made
ldi r16, 1
std Z + s_UpdateCntH, r17
std Z + s_UpdateCntL, r16
Init10Check_Max:
ldd r19, Z + s_MaxH
ldd r18, Z + s_MaxL
cp r18, r16 ; check if value exceeds MAXIMUM range
cpc r19, r17
brsh Init10Check_End
std Z + s_MaxH, r17
std Z + s_MaxL, r16
ldi r17, 0 ; mark that update was made
ldi r16, 1
std Z + s_UpdateCntH, r17
std Z + s_UpdateCntL, r16
;call CalcPosCoef
Init10Check_End:
; Calculate Initial Coeficients
call CalcNegCoef
call CalcPosCoef
ret
;************************************************************************
; Process 10 bit symmetric axis ADC value scaling it by appropriate coeficients
;
; Input: Z - address of 10 bit symmetric axis structure (size = 10)
; r17:r16 - 10 bit unsigned value from ADC
; Output; r17:r16 - 10 bit signed value
;************************************************************************
Process10SymAxis:
; Step 1 : Check Min and Max ranges. If the value exceeds any of them update it
;and recalculate coeficients
ldd r19, Z + s_MinH
ldd r18, Z + s_MinL
cp r16, r18 ; check if value exceeds MINIMUM range
cpc r17, r19
brsh Check_Max
std Z + s_MinH, r17
std Z + s_MinL, r16
sts ADCValueH, r17 ; backup ADC value
sts ADCValueL, r16
ldi r17, 0 ; mark that update was made
ldi r16, 1
std Z + s_UpdateCntH, r17
std Z + s_UpdateCntL, r16
call CalcNegCoef
lds r17, ADCValueH ; restore ADC value
lds r16, ADCValueL
Check_Max:
ldd r19, Z + s_MaxH
ldd r18, Z + s_MaxL
cp r18, r16 ; check if value exceeds MAXIMUM range
cpc r19, r17
brsh Check_End
std Z + s_MaxH, r17
std Z + s_MaxL, r16
sts ADCValueH, r17 ; backup ADC value
sts ADCValueL, r16
ldi r17, 0 ; mark that update was made
ldi r16, 1
std Z + s_UpdateCntH, r17
std Z + s_UpdateCntL, r16
call CalcPosCoef
lds r17, ADCValueH ; restore ADC value
lds r16, ADCValueL
Check_End:
; Step 2 : Offset
ldd r19, Z + s_CenterH
ldd r18, Z + s_CenterL
sub r16, r18 ; subtract 16-bit center offset value
sbc r17, r19
; Step 3 : Multiply by coeficient
movw r23:r22, r17:r16
sbrs r23,7
rjmp TakePosCoef
sbr r25,128 ; mark negative range
; negate the number
com r22
com r23
subi r22, $FF
sbci r23, $FF
ldd r21, Z + s_NegCoefH ; negative range coeficient
ldd r20, Z + s_NegCoefL
rjmp MulCoef
TakePosCoef:
cbr r25,128 ; mark positive range
ldd r21, Z + s_PosCoefH ;positive range coeficient
ldd r20, Z + s_PosCoefL
MulCoef:
call mul16x16_16
; Step 4: Divide by 128
lsl r16
rol r17
rol r18
mov r16, r17
mov r17, r18 ; the result is in r17:r16 register
andi r17, 1
sbrs r25,7 ;check if value was negative
rjmp Scaling_End
; negate the number
com r16
com r17
subi r16, $FF
sbci r17, $FF
andi r17, $01 ; make it 10bit signed value
sbr r17, 2
Scaling_End:
; result is in r17:r16
ret
;************************************************************************
; Process 8 bit asymmetric axis ADC value scaling it by appropriate coeficients
;
; Input: Z - address of 8 bit ssymmetric axis structure (size = 6)
; r17:r16 - 10 bit unsigned value from ADC
; Output; r16 - 8 bit signed value
;************************************************************************
Process8AsymAxis:
; Step 1 : Check Min and Max ranges. If the value exceeds any of them update it
;and recalculate coeficients
cbr r20, 1 ; clear update bit
ldd r19, Z + s_MinH
ldd r18, Z + s_MinL
cp r16, r18 ; check if value exceeds MINIMUM range
cpc r17, r19
brsh Check_Max8
std Z + s_MinH, r17
std Z + s_MinL, r16
sbr r20, 1 ; update required
Check_Max8:
ldd r19, Z + s_MaxH
ldd r18, Z + s_MaxL
cp r18, r16 ; check if value exceeds MAXIMUM range
cpc r19, r17
brsh Check_End8
std Z + s_MaxH, r17
std Z + s_MaxL, r16
sbr r20, 1 ; update required
Check_End8:
sbrs r20,0 ; skip recalculation if update is not required
rjmp Proc8Offset
sts ADCValueH, r17 ; backup ADC value
sts ADCValueL, r16
ldi r17, 0 ; mark that update was made
ldi r16, 1
std Z + s_UpdateCntH, r17
std Z + s_UpdateCntL, r16
call CalcCoef
lds r17, ADCValueH ; restore ADC value
lds r16, ADCValueL
; Step 2 : Offset
Proc8Offset:
ldd r19, Z + s_MinH
ldd r18, Z + s_MinL
sub r16, r18 ; subtract 16-bit minimum value
sbc r17, r19
; Step 3 : Multiply by coeficient
movw r23:r22, r17:r16
ldd r21, Z + s_CoefH ; range coeficient
ldd r20, Z + s_CoefL
movw r19:r18, r1:r0 ; backup r1, r0
call mul16x16_16
mov r16, r17 ; the result is in r16 register
movw r1:r0, r19:r18 ; restore r1, r0
; result is 8 bit signed value in r16 register
subi r16, 128
ret
;************************************************************************
; Process 10 bit asymmetric axis ADC value scaling it by appropriate coeficients
;
; Input: Z - address of 8 bit ssymmetric axis structure (size = 6)
; r17:r16 - 10 bit unsigned value from ADC
; Output; r17:r16 - 10 bit signed value
;************************************************************************
Process10AsymAxis:
; Step 1 : Check Min and Max ranges. If the value exceeds any of them update it
;and recalculate coeficients
cbr r20, 1 ; clear update bit
ldd r19, Z + s_MinH
ldd r18, Z + s_MinL
cp r16, r18 ; check if value exceeds MINIMUM range
cpc r17, r19
brsh Check_MaxA10
std Z + s_MinH, r17
std Z + s_MinL, r16
sbr r20, 1 ; update required
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -