Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Unless you're the sort of coder who can write assembler fluently, leave this the fuck alone.
- // Receive state-machine removed from my standard UART, this drives 8-N,1 @ 31250 baud.
- // Queued high priority bytes are sent before low priority ones, but this does not handle ordering MIDI events yet.
- .thumb
- .syntax unified
- // Define the addresses
- .equ PERIPH_BASE,0x40000000
- .equ AHB1PERIPH_BASE,PERIPH_BASE + 0x00020000
- .equ GPIOA_BASE,AHB1PERIPH_BASE + 0x0000
- .equ GPIOB_BASE,AHB1PERIPH_BASE + 0x0400
- .equ GPIOC_BASE,AHB1PERIPH_BASE + 0x0800
- .equ GPIOD_BASE,AHB1PERIPH_BASE + 0x0C00
- .equ GPIOE_BASE,AHB1PERIPH_BASE + 0x1000
- .equ GPIOF_BASE,AHB1PERIPH_BASE + 0x1400
- .equ GPIOG_BASE,AHB1PERIPH_BASE + 0x1800
- .equ GPIOH_BASE,AHB1PERIPH_BASE + 0x1C00
- .equ GPIOI_BASE,AHB1PERIPH_BASE + 0x2000
- .equ GPIOJ_BASE,AHB1PERIPH_BASE + 0x2400
- .equ GPIOK_BASE,AHB1PERIPH_BASE + 0x2800
- .equ u32MODER,0x00
- .equ u32OTYPER,0x04
- .equ u32OSPEEDR,0x08
- .equ u32PUPDR,0x0C
- .equ u32IDR,0x10
- .equ u32ODR,0x14
- .equ u16BSRRL,0x18
- .equ u16BSRRH,0x1A
- .equ u32BSRR,0x18
- .equ u32LCKR,0x1C
- .equ u32AFR0,0x20
- .equ u32AFR1,0x24
- .equ u16FlagMask,0x0002
- .equ u16FlagMask2,0x0000
- // Offsets the TSOFT_UART
- .equ u8ID,0
- .equ sRxState,4
- .equ u8SampleCnt,8
- .equ u8ActiveCnt,12
- .equ u8BitCnt,16
- .equ u16RxData,20
- .equ u16RxMask,24
- .equ pRxData,28
- .equ pRxHandler,32
- .equ pRxErrorHandler,36
- .equ sTxState,40
- .equ u16TxData,44
- .equ u16Tx_pIn,48
- .equ u16Tx_pOut,52
- .equ u8TxData,56
- .equ u16TxHP_pIn,1080
- .equ u16TxHP_pOut,1084
- .equ u8TxHPData,1088
- .equ pTxEnableTXI,1104
- .equ sizeofTUART,1108
- .equ HardUARTCnt,7
- .equ SoftUARTCnt,10
- .equ TotalUARTCnt,17
- .equ skipharduarts,sizeofTUART * 6
- // Setup the soft-uart
- .global vSU_Init
- .thumb_func
- vSU_Init: push {r4,lr} // Save
- ldr r0,=sSoftUARTs // Point at the structure
- mov r1,#TotalUARTCnt // How many we have
- mov r3,#0 // 0
- // Setup the vectors
- vSUInitLp: ldr r2,=vTxIdle // Set a safe vector
- str r2,[r0,sTxState] //
- // ldr r2,=vRxIdle // Set a safe vector
- // str r2,[r0,sRxState] //
- str r3,[r0,u16TxHP_pIn] // Flush the TxHP buffer
- str r3,[r0,u16TxHP_pOut]//
- str r3,[r0,u16Tx_pIn] // Flush the Tx buffer
- str r3,[r0,u16Tx_pOut] //
- // Loop
- vSUInitNext: ldr r2,=sizeofTUART //
- add r0,r2 //
- subs r1,#1 //
- cmp r1,#0 //
- it ne //
- bne vSUInitLp //
- pop {r4,pc} // Restore
- // This is the soft-uart RX event, we need to put data into our circular-buffer here
- .global vSU_IRQ
- .thumb_func
- vSU_IRQ: push {r4,r5,lr} // Save
- // Write the output data
- ldr r2,=u16TxFastOutData//
- ldr r1,=GPIOI_BASE+u32ODR// Write the output data
- ldrh r5,[r2] // Read the required output data
- str r5,[r1] // And write to the port
- dmb // Synchronise
- // Handle all the Tx ports
- mov r3,#0x03FF // u16TxFastOutData|=0x03FF;
- orr r5,r3 //
- mov r1,#0xFFFE // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*0 //
- bl vSU_HandleTx //
- mov r1,#0xFFFD // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*1 //
- bl vSU_HandleTx //
- mov r1,#0xFFFB // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*2 //
- bl vSU_HandleTx //
- mov r1,#0xFFF7 // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*3 //
- bl vSU_HandleTx //
- mov r1,#0xFFEF // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*4 //
- bl vSU_HandleTx //
- mov r1,#0xFFDF // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*5 //
- bl vSU_HandleTx //
- mov r1,#0xFFBF // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*6 //
- bl vSU_HandleTx //
- mov r1,#0xFF7F // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*7 //
- bl vSU_HandleTx //
- mov r1,#0xFEFF // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*8 //
- bl vSU_HandleTx //
- mov r1,#0xFDFF // Mask
- ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*9 //
- bl vSU_HandleTx //
- // Save the output states
- ldr r1,=u16TxFastOutData//Save the states for next time
- str r5,[r1] //
- // Increment the system timer
- ldr r0,=u32Tick_31250 //
- ldr r1,[r0] //
- add r1,#1 //
- str r1,[r0] //
- // Handle the LED brightness
- ldr r0,=u32LED_Brightness//
- ldr r1,[r0] //
- ldr r2,[r0,4] //
- adds r2,r1 //
- str r2,[r0,4] //
- ldr r0,=GPIOD_BASE //
- ite cs //
- movcs r2,#0x00000800UL //
- movcc r2,#0x08000000UL //
- str r2,[r0,u32BSRR] // Set or clear the bit
- // Now, drive the 10mS flag
- // This is called at 31250
- ldr r0,=u16Tick10mSCnt //
- ldrh r1,[r0] //
- subs r1,#1 //
- it eq //
- ldreq r1,=312 // Reset the counter
- strh r1,[r0] //
- it ne // Bugger off if it's not set
- bne TxStateEnd //
- // Set the flag
- ldr r0,=bTime_10mS //
- strb r2,[r0] //
- // Done
- .thumb_func
- TxStateEnd:
- pop {r4,r5,pc} // Restore
- // The transmit encoder r5 = OUTPUTS(High by default) r1=BIT MASK, r0 = pSU
- .thumb_func
- vSU_HandleTx: ldr.w pc,[r0,sTxState] // Jump to the transmit state
- // Handlers
- .thumb_func
- vTxIdle: ldrh.w r2,[r0,u16TxHP_pIn] // Point at the input ptr
- ldrh.w r3,[r0,u16TxHP_pOut] // Point at the output ptr
- cmp r2,r3 // Anything waiting?
- it eq // Nothing to do it they are the same
- beq vTxIdleTestLP // Test the low priority buffer...
- // There's something in the HP buffer
- // We have something, read this byte
- mov r2,r0 // Copy the structure base
- add r2,#u8TxHPData // Base+start of buffer
- ldrb r4,[r2,r3] // Read the byte
- // Increment the pointer
- add r3,#1 // ++
- mov r2,#0x0F // Fast wrap-around, buffer MUST be 16!
- and r3,r2 // Wrap
- strh.w r3,[r0,u16TxHP_pOut] // Store it
- // Setup the transmit data
- strh r4,[r0,u16TxData] // Store this
- // Set the next state
- ldr r2,=vTxStart //
- str r2,[r0,sTxState] // Set the state
- mov pc,lr // Done
- // We don't have any HP byes, do we have any LP ones?
- vTxIdleTestLP: ldrh.w r2,[r0,u16Tx_pIn] // Point at the input ptr
- ldrh.w r3,[r0,u16Tx_pOut] // Point at the output ptr
- cmp r2,r3 // Anything waiting?
- it eq // Nothing to do it they are the same
- beq vTxIdleTestNoBytes // Test for pending events
- // We have something, read this byte
- mov r2,r0 // Copy the structure base
- add r2,#u8TxData // Base+start of buffer
- ldrb r4,[r2,r3] // Read the byte
- // Increment the pointer
- add r3,#1 // ++
- mov r2,#0x3FF // Fast wrap-around, buffer MUST be 1024!
- and r3,r2 // Wrap
- strh.w r3,[r0,u16Tx_pOut] // Store it
- // Setup the transmit data
- strh r4,[r0,u16TxData] // Store this
- // Set the next state
- ldr r2,=vTxStart //
- str r2,[r0,sTxState] // Set the state
- mov pc,lr // Done
- // We have no bytes waiting, we need to see if there are events to schedule...
- .thumb_func
- vTxIdleTestNoBytes: mov pc,lr // Return
- // I'll tidy this code up later... check for alignment advantages and see if it's worth rotating data
- // instead of thrashing the cache like this.
- .thumb_func
- vTxStart: and r5,r1 // Take the bit low
- // Set the next state
- ldr r2,=vTxBit0 //
- str r2,[r0,sTxState] // Set the state
- mov pc,lr // Done
- .thumb_func
- vTxBit0: ldr r2,=vTxBit1 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0001 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxBit1: ldr r2,=vTxBit2 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0002 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxBit2: ldr r2,=vTxBit3 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0004 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxBit3: ldr r2,=vTxBit4 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0008 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxBit4: ldr r2,=vTxBit5 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0010 //
- cmp r2,#0 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxBit5: ldr r2,=vTxBit6 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0020 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxBit6: ldr r2,=vTxBit7 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0040 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxBit7: ldr r2,=vTxStop1 // Set the next state
- str r2,[r0,sTxState] // Set the state
- ldrh r2,[r0,u16TxData] // Check this bit
- ands r2,#0x0080 //
- it ne //
- movne pc,lr // Done if it's high
- and r5,r1 // Take the bit low
- mov pc,lr // Done
- .thumb_func
- vTxStop1: ldr r2,=vTxIdle // Set the next state
- str r2,[r0,sTxState] // Set the state
- mov pc,lr // Done
- .thumb_func
- vTxStop2: ldr r2,=vTxIdle // Set the next state
- str r2,[r0,sTxState] // Set the state
- mov pc,lr // Done
Add Comment
Please, Sign In to add comment