Cremulus

QAD code for bit-banging a load of MIDI UARTs...

Sep 1st, 2023 (edited)
105
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 16.78 KB | Source Code | 0 0
  1. // Unless you're the sort of coder who can write assembler fluently, leave this the fuck alone.
  2. // Receive state-machine removed from my standard UART, this drives 8-N,1 @ 31250 baud.
  3. // Queued high priority bytes are sent before low priority ones, but this does not handle ordering MIDI events yet.
  4.  
  5. .thumb
  6. .syntax unified
  7.  
  8. // Define the addresses
  9. .equ PERIPH_BASE,0x40000000
  10. .equ AHB1PERIPH_BASE,PERIPH_BASE + 0x00020000
  11. .equ GPIOA_BASE,AHB1PERIPH_BASE + 0x0000
  12. .equ GPIOB_BASE,AHB1PERIPH_BASE + 0x0400
  13. .equ GPIOC_BASE,AHB1PERIPH_BASE + 0x0800
  14. .equ GPIOD_BASE,AHB1PERIPH_BASE + 0x0C00
  15. .equ GPIOE_BASE,AHB1PERIPH_BASE + 0x1000
  16. .equ GPIOF_BASE,AHB1PERIPH_BASE + 0x1400
  17. .equ GPIOG_BASE,AHB1PERIPH_BASE + 0x1800
  18. .equ GPIOH_BASE,AHB1PERIPH_BASE + 0x1C00
  19. .equ GPIOI_BASE,AHB1PERIPH_BASE + 0x2000
  20. .equ GPIOJ_BASE,AHB1PERIPH_BASE + 0x2400
  21. .equ GPIOK_BASE,AHB1PERIPH_BASE + 0x2800
  22.  
  23. .equ u32MODER,0x00
  24. .equ u32OTYPER,0x04
  25. .equ u32OSPEEDR,0x08
  26. .equ u32PUPDR,0x0C
  27. .equ u32IDR,0x10
  28. .equ u32ODR,0x14
  29. .equ u16BSRRL,0x18
  30. .equ u16BSRRH,0x1A
  31. .equ u32BSRR,0x18
  32. .equ u32LCKR,0x1C
  33. .equ u32AFR0,0x20
  34. .equ u32AFR1,0x24
  35.  
  36. .equ u16FlagMask,0x0002
  37. .equ u16FlagMask2,0x0000
  38.  
  39. // Offsets the TSOFT_UART
  40.  
  41. .equ u8ID,0
  42. .equ sRxState,4
  43. .equ u8SampleCnt,8
  44. .equ u8ActiveCnt,12
  45. .equ u8BitCnt,16
  46. .equ u16RxData,20
  47. .equ u16RxMask,24
  48. .equ pRxData,28
  49. .equ pRxHandler,32
  50. .equ pRxErrorHandler,36
  51. .equ sTxState,40
  52. .equ u16TxData,44
  53. .equ u16Tx_pIn,48
  54. .equ u16Tx_pOut,52
  55. .equ u8TxData,56
  56. .equ u16TxHP_pIn,1080
  57. .equ u16TxHP_pOut,1084
  58. .equ u8TxHPData,1088
  59. .equ pTxEnableTXI,1104
  60. .equ sizeofTUART,1108
  61.  
  62. .equ HardUARTCnt,7
  63. .equ SoftUARTCnt,10
  64. .equ TotalUARTCnt,17
  65.  
  66. .equ skipharduarts,sizeofTUART * 6
  67.  
  68. // Setup the soft-uart
  69.  
  70. .global vSU_Init
  71. .thumb_func
  72. vSU_Init: push {r4,lr} // Save
  73.  
  74. ldr r0,=sSoftUARTs // Point at the structure
  75. mov r1,#TotalUARTCnt // How many we have
  76. mov r3,#0 // 0
  77.  
  78. // Setup the vectors
  79.  
  80. vSUInitLp: ldr r2,=vTxIdle // Set a safe vector
  81. str r2,[r0,sTxState] //
  82. // ldr r2,=vRxIdle // Set a safe vector
  83. // str r2,[r0,sRxState] //
  84.  
  85. str r3,[r0,u16TxHP_pIn] // Flush the TxHP buffer
  86. str r3,[r0,u16TxHP_pOut]//
  87.  
  88. str r3,[r0,u16Tx_pIn] // Flush the Tx buffer
  89. str r3,[r0,u16Tx_pOut] //
  90.  
  91. // Loop
  92.  
  93. vSUInitNext: ldr r2,=sizeofTUART //
  94. add r0,r2 //
  95.  
  96. subs r1,#1 //
  97. cmp r1,#0 //
  98. it ne //
  99. bne vSUInitLp //
  100.  
  101. pop {r4,pc} // Restore
  102.  
  103. // This is the soft-uart RX event, we need to put data into our circular-buffer here
  104.  
  105. .global vSU_IRQ
  106. .thumb_func
  107. vSU_IRQ: push {r4,r5,lr} // Save
  108.  
  109. // Write the output data
  110.  
  111. ldr r2,=u16TxFastOutData//
  112. ldr r1,=GPIOI_BASE+u32ODR// Write the output data
  113. ldrh r5,[r2] // Read the required output data
  114. str r5,[r1] // And write to the port
  115. dmb // Synchronise
  116.  
  117. // Handle all the Tx ports
  118.  
  119. mov r3,#0x03FF // u16TxFastOutData|=0x03FF;
  120. orr r5,r3 //
  121.  
  122. mov r1,#0xFFFE // Mask
  123. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*0 //
  124. bl vSU_HandleTx //
  125.  
  126. mov r1,#0xFFFD // Mask
  127. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*1 //
  128. bl vSU_HandleTx //
  129.  
  130. mov r1,#0xFFFB // Mask
  131. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*2 //
  132. bl vSU_HandleTx //
  133.  
  134. mov r1,#0xFFF7 // Mask
  135. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*3 //
  136. bl vSU_HandleTx //
  137.  
  138. mov r1,#0xFFEF // Mask
  139. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*4 //
  140. bl vSU_HandleTx //
  141.  
  142. mov r1,#0xFFDF // Mask
  143. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*5 //
  144. bl vSU_HandleTx //
  145.  
  146. mov r1,#0xFFBF // Mask
  147. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*6 //
  148. bl vSU_HandleTx //
  149.  
  150. mov r1,#0xFF7F // Mask
  151. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*7 //
  152. bl vSU_HandleTx //
  153.  
  154. mov r1,#0xFEFF // Mask
  155. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*8 //
  156. bl vSU_HandleTx //
  157.  
  158. mov r1,#0xFDFF // Mask
  159. ldr r0,=sSoftUARTs + skipharduarts + sizeofTUART*9 //
  160. bl vSU_HandleTx //
  161.  
  162. // Save the output states
  163.  
  164. ldr r1,=u16TxFastOutData//Save the states for next time
  165. str r5,[r1] //
  166.  
  167. // Increment the system timer
  168. ldr r0,=u32Tick_31250 //
  169. ldr r1,[r0] //
  170. add r1,#1 //
  171. str r1,[r0] //
  172.  
  173. // Handle the LED brightness
  174.  
  175. ldr r0,=u32LED_Brightness//
  176. ldr r1,[r0] //
  177. ldr r2,[r0,4] //
  178. adds r2,r1 //
  179. str r2,[r0,4] //
  180.  
  181. ldr r0,=GPIOD_BASE //
  182.  
  183. ite cs //
  184. movcs r2,#0x00000800UL //
  185. movcc r2,#0x08000000UL //
  186.  
  187. str r2,[r0,u32BSRR] // Set or clear the bit
  188.  
  189. // Now, drive the 10mS flag
  190.  
  191. // This is called at 31250
  192. ldr r0,=u16Tick10mSCnt //
  193.  
  194. ldrh r1,[r0] //
  195. subs r1,#1 //
  196.  
  197. it eq //
  198. ldreq r1,=312 // Reset the counter
  199.  
  200. strh r1,[r0] //
  201.  
  202. it ne // Bugger off if it's not set
  203. bne TxStateEnd //
  204.  
  205. // Set the flag
  206. ldr r0,=bTime_10mS //
  207. strb r2,[r0] //
  208.  
  209. // Done
  210.  
  211. .thumb_func
  212. TxStateEnd:
  213. pop {r4,r5,pc} // Restore
  214.  
  215. // The transmit encoder r5 = OUTPUTS(High by default) r1=BIT MASK, r0 = pSU
  216.  
  217. .thumb_func
  218. vSU_HandleTx: ldr.w pc,[r0,sTxState] // Jump to the transmit state
  219.  
  220. // Handlers
  221.  
  222. .thumb_func
  223. vTxIdle: ldrh.w r2,[r0,u16TxHP_pIn] // Point at the input ptr
  224. ldrh.w r3,[r0,u16TxHP_pOut] // Point at the output ptr
  225. cmp r2,r3 // Anything waiting?
  226. it eq // Nothing to do it they are the same
  227. beq vTxIdleTestLP // Test the low priority buffer...
  228.  
  229. // There's something in the HP buffer
  230.  
  231. // We have something, read this byte
  232. mov r2,r0 // Copy the structure base
  233. add r2,#u8TxHPData // Base+start of buffer
  234. ldrb r4,[r2,r3] // Read the byte
  235.  
  236. // Increment the pointer
  237. add r3,#1 // ++
  238. mov r2,#0x0F // Fast wrap-around, buffer MUST be 16!
  239. and r3,r2 // Wrap
  240. strh.w r3,[r0,u16TxHP_pOut] // Store it
  241.  
  242. // Setup the transmit data
  243. strh r4,[r0,u16TxData] // Store this
  244.  
  245. // Set the next state
  246. ldr r2,=vTxStart //
  247. str r2,[r0,sTxState] // Set the state
  248. mov pc,lr // Done
  249.  
  250. // We don't have any HP byes, do we have any LP ones?
  251.  
  252. vTxIdleTestLP: ldrh.w r2,[r0,u16Tx_pIn] // Point at the input ptr
  253. ldrh.w r3,[r0,u16Tx_pOut] // Point at the output ptr
  254. cmp r2,r3 // Anything waiting?
  255. it eq // Nothing to do it they are the same
  256. beq vTxIdleTestNoBytes // Test for pending events
  257.  
  258. // We have something, read this byte
  259. mov r2,r0 // Copy the structure base
  260. add r2,#u8TxData // Base+start of buffer
  261. ldrb r4,[r2,r3] // Read the byte
  262.  
  263. // Increment the pointer
  264. add r3,#1 // ++
  265. mov r2,#0x3FF // Fast wrap-around, buffer MUST be 1024!
  266. and r3,r2 // Wrap
  267. strh.w r3,[r0,u16Tx_pOut] // Store it
  268.  
  269. // Setup the transmit data
  270. strh r4,[r0,u16TxData] // Store this
  271.  
  272. // Set the next state
  273. ldr r2,=vTxStart //
  274. str r2,[r0,sTxState] // Set the state
  275. mov pc,lr // Done
  276.  
  277. // We have no bytes waiting, we need to see if there are events to schedule...
  278.  
  279. .thumb_func
  280. vTxIdleTestNoBytes: mov pc,lr // Return
  281.  
  282. // I'll tidy this code up later... check for alignment advantages and see if it's worth rotating data
  283. // instead of thrashing the cache like this.
  284.  
  285. .thumb_func
  286. vTxStart: and r5,r1 // Take the bit low
  287.  
  288. // Set the next state
  289.  
  290. ldr r2,=vTxBit0 //
  291. str r2,[r0,sTxState] // Set the state
  292.  
  293. mov pc,lr // Done
  294.  
  295. .thumb_func
  296. vTxBit0: ldr r2,=vTxBit1 // Set the next state
  297. str r2,[r0,sTxState] // Set the state
  298.  
  299. ldrh r2,[r0,u16TxData] // Check this bit
  300. ands r2,#0x0001 //
  301.  
  302. it ne //
  303. movne pc,lr // Done if it's high
  304.  
  305. and r5,r1 // Take the bit low
  306.  
  307. mov pc,lr // Done
  308.  
  309. .thumb_func
  310. vTxBit1: ldr r2,=vTxBit2 // Set the next state
  311. str r2,[r0,sTxState] // Set the state
  312.  
  313. ldrh r2,[r0,u16TxData] // Check this bit
  314. ands r2,#0x0002 //
  315.  
  316. it ne //
  317. movne pc,lr // Done if it's high
  318.  
  319. and r5,r1 // Take the bit low
  320.  
  321. mov pc,lr // Done
  322.  
  323.  
  324. .thumb_func
  325. vTxBit2: ldr r2,=vTxBit3 // Set the next state
  326. str r2,[r0,sTxState] // Set the state
  327.  
  328. ldrh r2,[r0,u16TxData] // Check this bit
  329. ands r2,#0x0004 //
  330.  
  331. it ne //
  332. movne pc,lr // Done if it's high
  333.  
  334. and r5,r1 // Take the bit low
  335.  
  336. mov pc,lr // Done
  337.  
  338. .thumb_func
  339. vTxBit3: ldr r2,=vTxBit4 // Set the next state
  340. str r2,[r0,sTxState] // Set the state
  341.  
  342. ldrh r2,[r0,u16TxData] // Check this bit
  343. ands r2,#0x0008 //
  344.  
  345. it ne //
  346. movne pc,lr // Done if it's high
  347.  
  348. and r5,r1 // Take the bit low
  349.  
  350. mov pc,lr // Done
  351.  
  352. .thumb_func
  353. vTxBit4: ldr r2,=vTxBit5 // Set the next state
  354. str r2,[r0,sTxState] // Set the state
  355.  
  356. ldrh r2,[r0,u16TxData] // Check this bit
  357. ands r2,#0x0010 //
  358. cmp r2,#0 //
  359.  
  360. it ne //
  361. movne pc,lr // Done if it's high
  362.  
  363. and r5,r1 // Take the bit low
  364.  
  365. mov pc,lr // Done
  366.  
  367. .thumb_func
  368. vTxBit5: ldr r2,=vTxBit6 // Set the next state
  369. str r2,[r0,sTxState] // Set the state
  370.  
  371. ldrh r2,[r0,u16TxData] // Check this bit
  372. ands r2,#0x0020 //
  373.  
  374. it ne //
  375. movne pc,lr // Done if it's high
  376.  
  377. and r5,r1 // Take the bit low
  378.  
  379. mov pc,lr // Done
  380.  
  381.  
  382. .thumb_func
  383. vTxBit6: ldr r2,=vTxBit7 // Set the next state
  384. str r2,[r0,sTxState] // Set the state
  385.  
  386. ldrh r2,[r0,u16TxData] // Check this bit
  387. ands r2,#0x0040 //
  388.  
  389. it ne //
  390. movne pc,lr // Done if it's high
  391.  
  392. and r5,r1 // Take the bit low
  393.  
  394. mov pc,lr // Done
  395.  
  396. .thumb_func
  397. vTxBit7: ldr r2,=vTxStop1 // Set the next state
  398. str r2,[r0,sTxState] // Set the state
  399.  
  400. ldrh r2,[r0,u16TxData] // Check this bit
  401. ands r2,#0x0080 //
  402.  
  403. it ne //
  404. movne pc,lr // Done if it's high
  405.  
  406. and r5,r1 // Take the bit low
  407.  
  408. mov pc,lr // Done
  409.  
  410. .thumb_func
  411. vTxStop1: ldr r2,=vTxIdle // Set the next state
  412. str r2,[r0,sTxState] // Set the state
  413.  
  414. mov pc,lr // Done
  415.  
  416. .thumb_func
  417. vTxStop2: ldr r2,=vTxIdle // Set the next state
  418. str r2,[r0,sTxState] // Set the state
  419.  
  420. mov pc,lr // Done
  421.  
Add Comment
Please, Sign In to add comment