📄 mjoy.asm
字号:
pop R26
pop temp3
pop temp2
EndInt0HandlerPOP:
pop USBBufptrY
pop ByteCount
mov bitcount,backupbitcount ;restore bitcount register
EndInt0HandlerPOP2:
pop temp1
pop temp0
out SREG,backupSREG
ldi shiftbuf,1<<INTF0 ;zero interruptu flag INTF0
out GIFR,shiftbuf
reti ;otherwise finish (was only SOF - every millisecond)
USBBeginPacket:
mov backupbitcount,bitcount ;backup bitcount register
in shiftbuf,inputport ;if yes load it as zero bit directly to shift register
USBloopBegin:
push ByteCount ;additional backup of registers (save of time)
push USBBufptrY
ldi bitcount,6 ;initialization of bits counter in byte
ldi ByteCount,MAXUSBBYTES ;initialization of max number of received bytes in packet
ldi USBBufptrY,InputShiftBufferBegin ;set the input buffer
USBloop1_6:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;unmask low 2 bits
breq USBloopEnd ;if they are zeros - end of USB packet
ror inputbuf ;transfer Data+ to shift register
rol shiftbuf
dec bitcount ;decrement bits counter
brne USBloop1_6 ;if it isn't zero - repeat filling of shift register
nop ;otherwise is necessary copy shift register to buffer
USBloop7:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;unmask low 2 bits
breq USBloopEnd ;if they are zeros - end of USB packet
ror inputbuf ;transfer Data+ to shift register
rol shiftbuf
ldi bitcount,7 ;initialization of bits counter in byte
st Y+,shiftbuf ;copy shift register into buffer and increment pointer to buffer
USBloop0: ;and start receiving next byte
in shiftbuf,inputport ;zero bit directly to shift register
cbr shiftbuf,USBpinmask ;unmask low 2 bits
breq USBloopEnd ;if they are zeros - end of USB packet
dec bitcount ;decrement bits counter
nop ;
dec ByteCount ;if not reached maximum buffer
brne USBloop1_6 ;then receive next
rjmp EndInt0HandlerPOP ;otherwise repeat back from begin
USBloopEnd:
cpi USBBufptrY,InputShiftBufferBegin+3 ;if at least 3 byte not received
brcs EndInt0HandlerPOP ;then finish
lds temp0,InputShiftBufferBegin+0 ;identifier of packet to temp0
lds temp1,InputShiftBufferBegin+1 ;address to temp1
brne TestDataPacket ;if is length different from 3 - then this can be only DataPaket
TestIOPacket:
andi temp1,0xFE ;MMM mask out bit 0 of address to avoid conflict with endpoint 1
cp temp1,MyAddress ;if this isn't assigned (address) for me
brne TestDataPacket ;then this can be still DataPacket
TestSetupPacket: ;test to SETUP packet
cpi temp0,nNRZISETUPPID
brne TestOutPacket ;if this isn't Setup PID - decode other packet
ldi State,SetupState
rjmp EndInt0HandlerPOP ;if this is Setup PID - receive consecutive Data packet
TestOutPacket: ;test for OUT packet
cpi temp0,nNRZIOUTPID
brne TestInPacket ;if this isn't Out PID - decode other packet
ldi State,OutState
rjmp EndInt0HandlerPOP ;if this is Out PID - receive consecutive Data packet
TestInPacket: ;test on IN packet
cpi temp0,nNRZIINPID
brne TestDataPacket ;if this isn't In PID - decode other packet
rjmp AnswerToInRequest
TestDataPacket: ; test for DATA0 and DATA1 packet
cpi temp0,nNRZIDATA0PID
breq Data0Packet ;if this isn't Data0 PID - decode other packet
cpi temp0,nNRZIDATA1PID
brne NoMyPacked ;if this isn't Data1 PID - decode other packet
Data0Packet:
cpi State,SetupState ;if was state Setup
breq ReceiveSetupData ;receive it
cpi State,OutState ;if was state Out
breq ReceiveOutData ;receive it
NoMyPacked:
ldi State,BaseState ;zero state
rjmp EndInt0HandlerPOP ;and receive consecutive Data packet
AnswerToInRequest:
push temp2 ;backup next registers and continue
push temp3
push R26
push ACC
; this might be Endpoint1 interrupt query
lds temp1,InputShiftBufferBegin+1 ;address to temp1
lds temp2,InputShiftBufferBegin+2 ;endpoint and CRC to temp2
ror temp1 ; move bit 0 to carry
ror temp2 ; bring bit 7 to carry
swap temp2
sbrs temp1, 0 ; check bit 1 (6) of address
rjmp AddrBit6Zero
com temp2
AddrBit6Zero:
andi temp2, 0x0F
cpi temp2, 0x0A
breq ProcessEndpoint0
cpi temp2, 0x05
breq ProcessEndpoint1
rjmp EndInt0Handler
ProcessEndpoint0:
cpi ActionFlag,DoReadySendAnswer ;if isn't prepared answer
brne NoReadySend ;then send NAK
rcall SendPreparedUSBAnswer ;transmitting answer back
and MyUpdatedAddress,MyUpdatedAddress ;if is MyUpdatedAddress nonzero
brne SetMyNewUSBAddress_2 ;then is necessary to change USB address
ldi State,InState
ldi ActionFlag,DoPrepareOutContinuousBuffer
rjmp EndInt0Handler ;and repeat - wait for next response from USB
ReceiveSetupData:
push temp2 ;backup next registers and continue
push temp3
push R26
push ACC
rcall SendACK ;accept Setup Data packet
rcall FinishReceiving ;finish receiving
ldi ActionFlag,DoReceiveSetupData
rjmp EndInt0Handler
ReceiveOutData:
push temp2 ;backup next registers and continue
push temp3
push R26
push ACC
cpi ActionFlag,DoReceiveSetupData ;if is currently in process command Setup
breq NoReadySend ;then send NAK
rcall SendACK ;accept Out packet
clr ActionFlag
rjmp EndInt0Handler
NoReadySend:
rcall SendNAK ;still I am not ready to answer
rjmp EndInt0Handler ;and repeat - wait for next response from USB
SetMyNewUSBAddress_2:
rjmp SetMyNewUSBAddress
;*******************************************************************************************
;*
;* ENDPOINT 1
;*
;*******************************************************************************************
ProcessEndpoint1: ; on Endpoint1 In we have interrupt handler which is sending reports of joystick data
; Check if we have joystick data ready
sbrs JoystickFlags, JoystickDataReadyBit
rjmp NoJoystickDataReady
; Backup Control pipe buffer pointers to save Control pipe state
mov temp0, OutputBufferLength
sts BkpOutputBufferLength,temp0
mov temp0, OutBitStuffNumber
sts BkpOutBitStuffNumber,temp0
; Retrieve Joystick buffer parameters
lds temp0,JoyOutBitStuffNumber
mov OutBitStuffNumber, temp0
lds ByteCount,JoyOutputBufferLength ;length of answer
ldi USBBufptrY,JoystickBufferBegin ;pointer to start of transmition buffer
rcall SendUSBBuffer
; Restore Control pipe buffer pointers
lds temp0, BkpOutputBufferLength
mov OutputBufferLength, temp0
lds temp0, BkpOutBitStuffNumber
mov OutBitStuffNumber,temp0
; flip data PID
lds temp0, JoystickBufferBegin + 1
cpi temp0, DATA0PID
breq FlipToDATA1PID
ldi temp0, DATA0PID
rjmp FlipDone
FlipToDATA1PID:
ldi temp0, DATA1PID
FlipDone:
sts JoystickBufferBegin + 1,temp0
ldi temp0,JoystickDataRequest
or JoystickFlags,temp0 ;JoystickDataRequest ; request new joystick data
rjmp EndInt0Handler ;and complete
NoJoystickDataReady:
; rcall SendNAK ;still I am not ready to answer
rjmp EndInt0Handler ;and repeat - wait for next response from USB
;--END--ENDPOINT1
;------------------------------------------------------------------------------------------
SetMyNewUSBAddress: ;set new USB address in NRZI coded
clr MyAddress ;original answer state - of my nNRZI USB address
ldi temp2,0b00000001 ;mask for xoring
ldi temp3,8 ;bits counter
SetMyNewUSBAddressLoop:
mov temp0,MyAddress ;remember final answer
ror MyUpdatedAddress ;to carry transmitting bit LSB (in direction firstly LSB then MSB)
brcs NoXORBit ;if one - don't change state
eor temp0,temp2 ;otherwise state will be changed according to last bit of answer
NoXORBit:
ror temp0 ;last bit of changed answer to carry
rol MyAddress ;and from carry to final answer to the LSB place (and reverse LSB and MSB order)
dec temp3 ;decrement bits counter
brne SetMyNewUSBAddressLoop ;if bits counter isn't zero repeat transmitting with next bit
clr MyUpdatedAddress ;zero addresses as flag of its next unchanging
; mask out bit 0 to avoid conflict with endpoints
mov temp2, MyAddress
andi temp2,0xFE
mov MyAddress, temp2
rjmp EndInt0Handler
;------------------------------------------------------------------------------------------
FinishReceiving: ;corrective actions for receive termination
cpi bitcount,7 ;transfer to buffer also last not completed byte
breq NoRemainingBits ;if were all bytes transfered, then nothing transfer
inc bitcount
ShiftRemainingBits:
rol shiftbuf ;shift remaining not completed bits on right position
dec bitcount
brne ShiftRemainingBits
st Y+,shiftbuf ;and copy shift register bo buffer - not completed byte
NoRemainingBits:
mov ByteCount,USBBufptrY
subi ByteCount,InputShiftBufferBegin-1 ;in ByteCount is number of received bytes (including not completed bytes)
mov InputBufferLength,ByteCount ;and save for use in main program
ldi USBBufptrY,InputShiftBufferBegin ;pointer to begin of receiving shift buffer
ldi R26,InputBufferBegin+1 ;data buffer (leave out SOP)
push XH ;save RS232BufptrX Hi index
clr XH
MoveDataBuffer:
ld temp0,Y+
st X+,temp0
dec ByteCount
brne MoveDataBuffer
pop XH ;restore RS232BufptrX Hi index
ldi ByteCount,nNRZISOPbyte
sts InputBufferBegin,ByteCount ;like received SOP - it is not copied from shift buffer
ret
;------------------------------------------------------------------------------------------
;********************************************************************
;* Other procedures
;********************************************************************
;------------------------------------------------------------------------------------------
USBReset: ;iinitialization of USB state engine
ldi temp0,nNRZIADDR0 ;initialization of USB address
mov MyAddress,temp0
clr State ;initialization of state engine
clr BitStuffInOut
clr OutBitStuffNumber
clr ActionFlag
clr RAMread ;will be reading from ROM
sts ConfigByte,RAMread ;unconfigured state
ret
;------------------------------------------------------------------------------------------
SendPreparedUSBAnswer: ;transmitting by NRZI coding OUT buffer with length OutputBufferLength to USB
mov ByteCount,OutputBufferLength ;length of answer
SendUSBAnswer: ;transmitting by NRZI coding OUT buffer to USB
ldi USBBufptrY,OutputBufferBegin ;pointer to begin of transmitting buffer
SendUSBBuffer: ;transmitting by NRZI coding given buffer to USB
ldi temp1,0 ;incrementing pointer (temporary variable)
mov temp3,ByteCount ;byte counter: temp3 = ByteCount
ldi temp2,0b00000011 ;mask for xoring
ld inputbuf,Y+ ;load first byte to inputbuf and increment pointer to buffer
;USB as output:
cbi outputport,DATAplus ;down DATAPLUS : idle state of USB port
sbi outputport,DATAminus ;set DATAMINUS : idle state of USB port
sbi USBdirection,DATAplus ;DATAPLUS as output
sbi USBdirection,DATAminus ;DATAMINUS as output
in temp0,outputport ;idle state of USB port to temp0
SendUSBAnswerLoop:
ldi bitcount,7 ;bits counter
SendUSBAnswerByteLoop:
nop ;delay because timing
ror inputbuf ;to carry transmiting bit (in direction first LSB then MSB)
brcs NoXORSend ;if that it is one - don't change USB state
eor temp0,temp2 ;iotherwise state will be changed
NoXORSend:
out outputport,temp0 ;send out to USB
dec bitcount ;decrement bits counter - according to carry flag
brne SendUSBAnswerByteLoop ; if bits counter isn't zero - repeat transmiting with next bit
sbrs inputbuf,0 ;if is transmiting bit one - don't change USB state
eor temp0,temp2 ;otherwise state will be changed
NoXORSendLSB:
dec temp3 ;decrement bytes counter
ld inputbuf,Y+ ;load next byte and increment pointer to buffer
out outputport,temp0 ;transmit to USB
brne SendUSBAnswerLoop ;repeat for all buffer (till temp3=0)
mov bitcount,OutBitStuffNumber ;bits counter for bitstuff
cpi bitcount,0 ;if not be needed bitstuff
breq ZeroBitStuf
SendUSBAnswerBitstuffLoop:
ror inputbuf ;to carry transmiting bit (in direction first LSB then MSB)
brcs NoXORBitstuffSend ;if is one - don't change state on USB
eor temp0,temp2 ;otherwise state will be changed
NoXORBitstuffSend:
out outputport,temp0 ;transmit to USB
nop ;delay because of timing
dec bitcount ;decrement bits counter - according to carry flag
brne SendUSBAnswerBitstuffLoop ;if bits counter isn't zero - repeat transmiting with next bit
ld inputbuf,Y ;delay 2 cycle
ZeroBitStuf:
nop ;delay 1 cycle
cbr temp0,3
out outputport,temp0 ;transmit EOP on USB
ldi bitcount,5 ;delay counter: EOP shouls exists 2 bits (16 cycle at 12MHz)
SendUSBWaitEOP:
dec bitcount
brne SendUSBWaitEOP
sbi outputport,DATAminus ;set DATAMINUS : idle state on USB port
sbi outputport,DATAminus ;delay 2 cycle: Idle should exists 1 bit (8 cycle at 12MHz)
cbi USBdirection,DATAplus ;DATAPLUS as input
cbi USBdirection,DATAminus ;DATAMINUS as input
cbi outputport,DATAminus ;reset DATAMINUS : the third state on USB port
ret
;------------------------------------------------------------------------------------------
ToggleDATAPID:
lds temp0,OutputBufferBegin+1 ;load last PID
cpi temp0,DATA1PID ;if last was DATA1PID byte
ldi temp0,DATA0PID
breq SendData0PID ;then send zero answer with DATA0PID
ldi temp0,DATA1PID ;otherwise send zero answer with DATA1PID
SendData0PID:
sts OutputBufferBegin+1,temp0 ;DATA0PID byte
ret
;------------------------------------------------------------------------------------------
ComposeZeroDATA1PIDAnswer:
ldi temp0,DATA0PID ;DATA0 PID - in the next will be toggled to DATA1PID in load descriptor
sts OutputBufferBegin+1,temp0 ;load to output buffer
ComposeZeroAnswer:
ldi temp0,SOPbyte
sts OutputBufferBegin+0,temp0 ;SOP byte
rcall ToggleDATAPID ;change DATAPID
ldi temp0,0x00
sts OutputBufferBegin+2,temp0 ;CRC byte
sts OutputBufferBegin+3,temp0 ;CRC byte
ldi ByteCount,2+2 ;length of output buffer (SOP and PID + CRC16)
ret
;------------------------------------------------------------------------------------------
;------------------------------------------------------------------------------------------
InitJoystickBufffer:
; ldi ZH, high(JoystickAnswer<<1) ;ROMpointer to answer
; ldi ZL, low(JoystickAnswer<<1)
ldi temp0,JoystickReport1Size ;number of my bytes answers to temp0
mov TotalBytesToSend, temp0
ldi temp0,SOPbyte
sts OutputBufferBegin+0,temp0 ;SOP byte
ldi temp0,DATA0PID
sts OutputBufferBegin+1,temp0 ;DATA0PID byte
mov temp3,TotalBytesToSend ;otherwise send only given number of bytes
mov ByteCount,TotalBytesToSend;
ldi USBBufptrY,OutputBufferBegin+2 ;to transmitting buffer
LoadDescriptorFromROM_2:
lpm ;load from ROM position pointer to R0 <- (ZH:ZL)
st Y+,R0 ;R0 save to buffer and increment buffer (Y) <- R0, Y++
adiw ZH:ZL,1 ;increment index to ROM ; Z++
dec ByteCount ;till are not all bytes
brne LoadDescriptorFromROM_2 ;then load next
ldi ByteCount,2 ;length of output buffer (only SOP and PID)
add ByteCount,temp3 ;+ number of bytes
rcall AddCRCOut ;addition of CRC to buffer
inc ByteCount ;length of output buffer + CRC16
inc ByteCount
inc BitStuffInOut ;transmitting buffer - insertion of bitstuff bits
ldi USBBufptrY,OutputBufferBegin ;to transmitting buffer
rcall BitStuff
mov OutputBufferLength,ByteCount ;length of answer store for transmiting
clr BitStuffInOut ;receiving buffer - deletion of bitstuff bits
; copy to Joystick buffer
sts JoyOutputBufferLength, OutputBufferLength
sts JoyOutBitStuffNumber, OutBitStuffNumber
mov ByteCount, OutputBufferLength
; ldi ZH, high(OutputBufferBegin<<1) ;pointer to answer
clr ZH
ldi ZL, OutputBufferBegin
ldi USBBufptrY,JoystickBufferBegin ;to transmitting buffer
CopyToJoyBufferLoop:
ld R0, Z+ ;load from RAM position pointer to R0 <- (ZH:ZL)
st Y+,R0 ;R0 save to buffer and increment buffer (Y)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -