![]() |
Forum Index : Microcontroller and PC projects : 3rd UART via PIO
![]() ![]() ![]() ![]() |
|||||
Author | Message | ||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
Hi Thomas, Please find attached MMBasic program demonstrating a UART running on PIO. In this case it uses GP0 for TX and GP1 for RX. When you connect both together, you see the send string (a$) received correctly. When there are questions, feel free to ask. Technically this could also work for a 4'th UART, but MMBasic only supports a single DMA RX and DMA TX. The RX and TX buffers are layed out for 128 characters, but could be extended to 255 (string size). Please understand you need MMBasic 6.00.02 beta 0 to run the PIO ASSEMBLER. 'PIO 8n1 UART based on RP2040 datasheet 3.6.3 and 3.6.4 'requires PicoMite MMBasic 6.00.02 beta 0 to PIO assemble 'version control ' v0.0 sending from individual fifo writes works ' v0.1 sending from DMA works. ' v0.2 faster TX conversion string to dma fifo (idea: Peter) ' v0.3 UART RX experiments 8 deep fifo (needs V6.00.02b0 or newer) ' v0.4 UART_RX using DMA works, even at 115200 ' v0.5 cleanup of the code option default integer 'PIO program uses 2 state machines, one for RX and one for TX baud_rate = 19200 '115200 'memory buffer reservation 'DMA buffers (packed) for 128 characters maximum dim tx_pck%(63) 'packed TX array, 2 char per integer const tx_pck_ad%=peek(varaddr tx_pck%()) 'memory address of array start dim rx_pck%(63) 'packed RX array, 2 char per integer const rx_pck_ad%=peek(varaddr rx_pck%()) 'memory address of array start dim rx$ 'string for received characters const rx_ad%=peek(varaddr rx$) 'memory address of string 'make sure all fifo's and program memory are cleared, then program PIO pio clear 1 INIT_PIO '---------------------------- example code ------------------------------- 'test text string a$ = "Hello World, admire your beautiful beaches" + chr$(13) 'main loop: send string repeatedly do '---------------------- send a string ----------------- UART_TX (a$) pause 50 '--------------------- receive a string ---------------- 'print characters in the receive buffer if any print UART_RX$() loop '-------------------------- subs ------------------------------------------- 'sends string using DMA to PIO TX sub UART_TX (tx$) 'get start and size of string to be sent tx_l=len(tx$):tx_ad%=peek(varaddr tx$) 'pack string for sending to UART memory copy tx_ad%+1,tx_pck_ad%,tx_l,1,4 'start the DMA pio dma tx 1,0,tx_l,tx_pck%(), end sub 'get data from DMA buffer and restart DMA sub RdyInt 'unpack RX buffer to string memory copy rx_pck_ad%,rx_ad%+1,LOF%,4,1 'fill string characters poke byte rx_ad%,LOF% 'fill len(string) 'restart the DMA pio dma rx 1,1,128,rx_pck%(),RdyInt,32 'start the PIO with DMA end sub function UART_RX$() UART_RX$="" 'check for characters in the receive buffer LOF% = (Pio(DMA RX POINTER) - rx_pck_ad%) / 4 'in characters 'when data in buffer, get it if LOF% > 0 then PIO DMA RX OFF 'stop the DMA, generates a RdyInt UART_RX$ = rx$ 'continue after RdyInt, result is in rx$ end if end function 'program PIO 1 SM0 and 1, and start the UART sub INIT_PIO 'State machine 0 is UART TX SetPin GP0,pio1 ' note: side enable is implemented as the msb side_set bit since assembler ' instruction bits 12 11 10 9 8 ' use side_en side_set delay PIO ASSEMBLE 1,".program uart_tx" 'uart tx program from RP2040 datasheet PIO ASSEMBLE 1,".side_set 1 opt" 'side set 1 bit + opt=side enable pio assemble 1,".line 0" 'start of PIO program memory PIO ASSEMBLE 1,"set pindirs, 1" 'gp0 is output PIO ASSEMBLE 1,".wrap target" 'return point for wrap PIO ASSEMBLE 1,"pull block side 1 [7]" 'get data from fifo PIO ASSEMBLE 1,"set x, 7 side 0 [7]" 'bit counter 7,6,5,....,0 PIO ASSEMBLE 1,"bitloop:" 'label PIO ASSEMBLE 1,"out pins, 1" 'shift 1 bit out PIO ASSEMBLE 1,"jmp x-- bitloop [6]" 'check if 0, then decrement PIO ASSEMBLE 1,".wrap" 'wrap to target PIO ASSEMBLE 1,".end program"' list" 'write program and list hex values 'configure pio0 StateMachine 0 f0=baud_rate*8 ' a b c d e f g 'a,e=side set c,g=OUT b,f=set p0=Pio(PINCTRL 2,1,1, ,gp0,gp0,gp0) 'note:2=include side enable bit e0=Pio(execctrl gp1,Pio(.wrap target),Pio(.wrap),0,1 )'1=side set only when defined s0=Pio(shiftctrl 0,0,0,0,0,1,0,0) 'shift OUT direction LSB first 'write the configuration PIO init machine 1,0,f0,p0,e0,s0,0 'SM0 start at address 0 'Statemachine 1 = UART RX PIO ASSEMBLE 1,".program uart_rx" 'uart tx program from RP2040 datasheet pio assemble 1,".line 5" '5=start of PIO program memory RX PIO ASSEMBLE 1,"start:" 'label PIO ASSEMBLE 1,".wrap target" 'outer loop return PIO ASSEMBLE 1,"wait 0 pin 0" 'wait for a start bit PIO ASSEMBLE 1,"set x,7 [10]" 'set counter to 7,wait 10 cycles (=mid lsb) PIO ASSEMBLE 1,"bitloop2:" 'inner loop PIO ASSEMBLE 1,"in pins,1" 'shif in 1 bit PIO ASSEMBLE 1,"jmp x-- bitloop2 [6]" 'if x>0 next bit, delay 6, then x-- PIO ASSEMBLE 1,"jmp pin good_stop" 'if valid stop bit -> good_stop PIO ASSEMBLE 1,"irq 4 rel" '?? flag for ARM ?? PIO ASSEMBLE 1,"wait 1 pin 0" 'wait for a valid stop PIO ASSEMBLE 1,"jmp start" 'then goto wait for new start (loop) PIO ASSEMBLE 1,"good_stop:" 'label PIO ASSEMBLE 1,"in null,24" 'shift the data to LSB in the ISR PIO ASSEMBLE 1,"push" 'shift data to fifo PIO ASSEMBLE 1,".wrap" 'outer loop for new character PIO ASSEMBLE 1,".end program"' list" 'configure pio0 StateMachine 1 f1=baud_rate*8 ' a b c d e f g 'a,e=side set c,g=OUT b,f=set p1=Pio(PINCTRL 0, , ,gp1, , , ) 'gp1 = IN pin e1=Pio(execctrl gp1,Pio(.wrap target),Pio(.wrap)) 'gp1 = JMP pin s1=Pio(shiftctrl 0,0,0,0,1,0,0,0) 'shift IN LSB first 'write the configuration PIO init machine 1,1,f1,p1,e1,s1,5 'SM0 start at address 5 ' start the PIO UART pio dma rx 1,1,128,rx_pck%(),RdyInt,32 'start the RX PIO with DMA pio start 1,0 'start the TX UART end sub Volhout PicomiteVGA PETSCII ROBOTS |
||||
karlelch![]() Senior Member ![]() Joined: 30/10/2014 Location: GermanyPosts: 235 |
Hi Volout, Wow! Thanks a lot! I think this may be an important mean to get around the two-hardware-UART limitation even in the PR2350. ![]() I will test it soon. For my specific problem, I got an I2C solution to work, but I kept my UART code in the program and can enable it with a single switch ... Best Thomas |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
Hi Thomas, This UART is usable in a question/answer application. It’s weak point is that when you read data from its RX buffer, the DMA is stopped momentarily, and restarted. Any character received during this action is lost. I will investigate a solution using a ring buffer, not stopping the DMA, but that needs more time. When I am closer to final, I will also release a version that communicates framing errors to mmbasic level, and runs on other PIO and older mmbasic versions. I appreciate feedback on this UART core to proceed. Volhout Edited 2025-01-18 17:49 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2606 |
Excellent! Even at this stage it is very usable. > RUN '''World, admire your beautiful beaches Hello World, admire your beautiful beaches Hello World, admire your beautiful beaches Hello World, admire your beautiful beaches Hello World, admire your beautiful beaches > > INIT_PIO > a$= "The quick brown fox jumps over the lazy dog." > UART_TX (a$) : pause 50: print UART_RX$() The quick brown fox jumps over the lazy dog. > > a$= "This UART is usable in a question/answer application. Its weak point is that when you read data from its RX buffer," > UART_TX (a$) : pause 50: print UART_RX$() This UART is usable in a question/answer application. Its weak point is that when you read data > |
||||
PhenixRising Guru ![]() Joined: 07/11/2023 Location: United KingdomPosts: 1360 |
Heck YEAH ![]() ![]() |
||||
karlelch![]() Senior Member ![]() Joined: 30/10/2014 Location: GermanyPosts: 235 |
Hi Volhout, works like a charm! That would be very useful - or at least some flag that indicates that data was lost? Or both? For general use, the final code would do great in a library. Thanks again and best Thomas |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
Hi Thomas, phil99, Thanks for testing. Below is the functional version for PIO1 on GP0 and GP1. Also still needs V6.00.02b0 to assemble. This version uses the ring buffer, so should be full duplex. It has increased robustness against bitrate variations (increased RX PIO clock speed and tuned internal delays), and reports framing errors (communicated via the IRQ flag register). Later this week I will compact the PIO assembler code into an array, so the MMBasic source becomes more compact. I didn't do that yet so I could still make changes easier. But now I am becomming more confident. 'PIO 8n1 UART based on RP2040 datasheet 3.6.3 and 3.6.4 'requires PicoMite MMBasic 6.00.02 beta 0 to PIO assemble 'version control ' v0.0 sending from individual fifo writes works ' v0.1 sending from DMA works. ' v0.2 faster TX conversion string to dma fifo (idea: Peter) ' v0.3 UART RX experiments 8 deep fifo (needs V6.00.02b0 or newer) ' v0.4 UART_RX using DMA works, even at 115200 ' v0.5 cleanup of the code ' v0.6 RX ringbuffer ' v0.7 improve RX robustness v0.6=+1/-5% 0.7=+4/-4% (16*rx_bau_rate) ' v0.8 Communicate framing errors through IRQ register option default integer 'PIO program uses 2 state machines, one for RX and one for TX 'baud_rate = 19200 '115200 rx_buf_size = 128 '256 'characters tx_buf_size = 128 '256 'characters tx_baud_rate = 19200 rx_baud_rate = tx_baud_rate '19200*0.96 to test robustness 'memory buffer reservation 'DMA buffers (packed) for 128 characters maximum dim tx_pck%(tx_buf_size/2 - 1) 'packed TX array, 2 char per integer const tx_pck_ad%=peek(varaddr tx_pck%()) 'memory address of array start dim rx_pck% 'packed RX array, 2 char per integer PIO make ring buffer rx_pck%,rx_buf_size*4 'as ring buffer, size in bytes const rx_pck_ad%=peek(varaddr rx_pck%()) 'memory address of array start dim old_rx% = rx_pck_ad% 'old read pointer, default at start const rx_pck_end%=rx_pck_ad%+rx_buf_size*4'last location of rx buffer in bytes dim rx$ 'string for received characters const rx_ad%=peek(varaddr rx$) 'memory address of string 'make sure all fifo's and program memory are cleared, then program PIO pio clear 1 INIT_PIO '---------------------------- example code ------------------------------- 'test text string a$ = "Hello World, I admire your beautiful beaches" + chr$(13) 'main loop: send string repeatedly do '---------------------- send a string ----------------- UART_TX (a$) pause 50 '--------------------- receive a string ---------------- 'print characters in the receive buffer if no framing error 'UART_RX%() uses the global variable rx$ to assemble all data in. if UART_RX%() then print rx$ 'print the received string else print "framing error" poke word pio_1_irq,255 'clear framing error end if loop '-------------------------- subs ------------------------------------------- 'sends string using DMA to PIO TX sub UART_TX (tx$) 'get start and size of string to be sent tx_l% = len(tx$) : tx_ad% = peek(varaddr tx$) 'pack string for sending to UART memory copy tx_ad%+1, tx_pck_ad%, tx_l%, 1, 4 'start the DMA pio dma tx 1, 0, tx_l%, tx_pck%(), end sub function UART_RX%() local LOF%, LOF1%, LOF2%, new_rx% new_rx% = Pio(DMA RX POINTER) 'get current position in ring buffer select case new_rx%-old_rx% case 0 'no new data rx$="" case >0 'new data, no wrap around LOF% = (new_rx% - old_rx%) \ 4 'unpack RX buffer to string memory copy old_rx%,rx_ad%+1,LOF%,4,1 'fill string characters poke byte rx_ad%,LOF% 'fill len(string) case <0 'new data, with wrap around, needs split copying. LOF1% = (rx_pck_end% - old_rx%) \ 4 'begin text until end of buffer LOF2% = (new_rx% - rx_pck_ad%) \ 4 'start buffer to end of text LOF% = LOF1% + LOF2% 'total size of text 'unpack RX buffer to string memory copy old_rx%,rx_ad%+1,LOF1%,4,1 'fill start string characters memory copy rx_pck_ad%,rx_ad%+1+LOF1%,LOF2%,4,1 'fill end string characters poke byte rx_ad%,LOF% 'fill len(string) end select old_rx% = new_rx% 'reposition read pointer UART_RX% = (peek(word pio_1_irq)=0) 'UART status 1=0kay, 0=framing error end function 'program PIO 1 SM0 and 1, and start the UART sub INIT_PIO 'use PIO IRQ register to transfer framing errors pio_1_irq% = &h30 + &h50300000 'register + PIO1 offset poke word pio_1_irq,255 'erase all flag 'State machine 0 is UART TX SetPin GP0,pio1 ' note: side enable is implemented as the msb side_set bit since assembler ' instruction bits 12 11 10 9 8 ' use side_en side_set delay PIO ASSEMBLE 1,".program uart_tx" 'uart tx program from RP2040 datasheet PIO ASSEMBLE 1,".side_set 1 opt" 'side set 1 bit + opt=side enable pio assemble 1,".line 0" 'start of PIO program memory PIO ASSEMBLE 1,"set pindirs, 1" 'gp0 is output PIO ASSEMBLE 1,".wrap target" 'return point for wrap PIO ASSEMBLE 1,"pull block side 1 [7]" 'get data from fifo PIO ASSEMBLE 1,"set x, 7 side 0 [7]" 'bit counter 7,6,5,....,0 PIO ASSEMBLE 1,"bitloop:" 'label PIO ASSEMBLE 1,"out pins, 1" 'shift 1 bit out PIO ASSEMBLE 1,"jmp x-- bitloop [6]" 'check if 0, then decrement PIO ASSEMBLE 1,".wrap" 'wrap to target PIO ASSEMBLE 1,".end program"' list" 'write program and list hex values 'configure pio0 StateMachine 0 f0=tx_baud_rate*8 ' a b c d e f g 'a,e=side set c,g=OUT b,f=set p0=Pio(PINCTRL 2,1,1, ,gp0,gp0,gp0) 'note:2=include side enable bit e0=Pio(execctrl gp1,Pio(.wrap target),Pio(.wrap),0,1 )'1=side set only when defined s0=Pio(shiftctrl 0,0,0,0,0,1,0,0) 'shift OUT direction LSB first 'write the configuration PIO init machine 1,0,f0,p0,e0,s0,0 'SM0 start at address 0 'Statemachine 1 = UART RX PIO ASSEMBLE 1,".program uart_rx" 'uart tx program from RP2040 datasheet pio assemble 1,".line 5" '5=start of PIO program memory RX PIO ASSEMBLE 1,"start:" 'label PIO ASSEMBLE 1,".wrap target" 'outer loop return PIO ASSEMBLE 1,"wait 0 pin 0" 'wait for a start bit PIO ASSEMBLE 1,"set x,7 [20]" 'set counter to 7,wait 10 cycles (=mid lsb) PIO ASSEMBLE 1,"bitloop2:" 'inner loop PIO ASSEMBLE 1,"in pins,1" 'shif in 1 bit PIO ASSEMBLE 1,"jmp x-- bitloop2 [14]" 'if x>0 next bit, delay 6, then x-- PIO ASSEMBLE 1,"jmp pin good_stop" 'if valid stop bit -> good_stop PIO ASSEMBLE 1,"irq set 0" 'was "irq 4 rel" set flag for ARM PIO ASSEMBLE 1,"wait 1 pin 0" 'wait for a valid stop PIO ASSEMBLE 1,"jmp start" 'then goto wait for new start (loop) PIO ASSEMBLE 1,"good_stop:" 'label PIO ASSEMBLE 1,"in null,24" 'shift the data to LSB in the ISR PIO ASSEMBLE 1,"push" 'shift data to fifo PIO ASSEMBLE 1,".wrap" 'outer loop for new character PIO ASSEMBLE 1,".end program"' list" 'configure pio0 StateMachine 1 f1=rx_baud_rate*16 ' a b c d e f g 'a,e=side set c,g=OUT b,f=set p1=Pio(PINCTRL 0, , ,gp1, , , ) 'gp1 = IN pin e1=Pio(execctrl gp1,Pio(.wrap target),Pio(.wrap)) 'gp1 = JMP pin s1=Pio(shiftctrl 0,0,0,0,1,0,0,0) 'shift IN LSB first 'write the configuration PIO init machine 1,1,f1,p1,e1,s1,5 'SM1 start at address 5 ' start the PIO UART pio dma rx 1,1,0,rx_pck%(),,32,rx_buf_size% 'start the RX PIO with DMA ringbuffer pio start 1,0 'start the TX UART end sub Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2606 |
Version 0.8 communicating with COM2. Very nice. '---------------------------- example code ------------------------------- 'test text string a$ = "Hello World, I admire your beautiful beaches" '+ Chr$(13) SetPin gp5,gp4, COM2 : Open "COM2:19200" As #5 'gp1 & gp5 joined, gp4 & gp2 joined Dim n%, dat$, b$= "The quick brown fox jumps over the lazy dog. " 'main loop: send string repeatedly Do Inc n% '---------------------- send a string ----------------- UART_TX(Str$(n%)+" "+a$) : Pause 50: dat$ = Input$(128, #5) :Print dat$ Pause 50 Inc n% '--------------------- receive a string ---------------- Print #5, Str$(n%)+" Hello, "; b$+b$ : Pause 60 'print characters in the receive buffer if no framing error 'UART_RX%() uses the global variable rx$ to assemble all data in. If UART_RX%() Then Print rx$ 'print the received string Else Print "framing error" Poke word pio_1_irq,255 'clear framing error End If Pause 1000 Loop > RUN Don't know where the non-printable character comes from. Always before line 2.1 Hello World, I admire your beautiful beaches �2 Hello, The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 3 Hello World, I admire your beautiful beaches 4 Hello, The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 5 Hello World, I admire your beautiful beaches 6 Hello, The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 7 Hello World, I admire your beautiful beaches 8 Hello, The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. > Edit. If the pauses are shorter than the transmission time funny things happen. Edit 2. More playing. The non-printable character is chr$(252) > RUN 1 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 framing error UART_RX%() 0 3 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 4 Hello, 16:31:37 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 5 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 6 Hello, 16:31:39 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. > The non-printable character is gone, along with the rest of line 2. Edited 2025-01-20 16:01 by phil99 |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
Hi phill, The weird character can be explained (line 2). You start the RX PIO with ring buffer, and then setpin of the COM 2. This will cause a transition, that will be seen by the runnin PIO The last listing is causing me grey hairs. Someone reads data from an area where they should not. Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2606 |
Moving COM2 setup to the setup area fixed both issues. 'PIO program uses 2 state machines, one for RX and one for TX 'baud_rate = 19200 '115200 rx_buf_size = 128 '256 'characters tx_buf_size = 128 '256 'characters tx_baud_rate = 19200 '230400 '115200 '38400 '19200 rx_baud_rate = tx_baud_rate' * .96 'to test robustness SetPin gp5,gp4, COM2 : Open "COM2:tx_baud_rate" As #5 'gp1 & gp5 joined, gp4 & gp2 joined 'memory buffer reservation 'DMA buffers (packed) for 128 characters maximum Dim tx_pck%(tx_buf_size/2 - 1) 'packed TX array, 2 char per integer Const tx_pck_ad%=Peek(varaddr tx_pck%()) 'memory address of array start Dim rx_pck% 'packed RX array, 2 char per integer PIO make ring buffer rx_pck%,rx_buf_size*4 'as ring buffer, size in bytes Const rx_pck_ad%=Peek(varaddr rx_pck%()) 'memory address of array start Dim old_rx% = rx_pck_ad% 'old read pointer, default at start Const rx_pck_end%=rx_pck_ad%+rx_buf_size*4'last location of rx buffer in bytes Dim rx$ 'string for received characters Const rx_ad%=Peek(varaddr rx$) 'memory address of string 'make sure all fifo's and program memory are cleared, then program PIO PIO clear 1 INIT_PIO '---------------------------- example code ------------------------------- 'test text string a$ = "Hello World, I admire your beautiful beaches " '+ Chr$(13) Dim n%=-1, dat$, b$= "The quick brown fox jumps over the lazy dog. " 'main loop: send string repeatedly Do Inc n% '---------------------- send a string ----------------- UART_TX(Str$(n%)+" "+a$+" Rx Baud Rate "+Str$(Rx_baud_rate)) :Pause 90 : dat$=Input$(128, #5) :Print dat$ Pause 100 Inc n% '--------------------- receive a string ---------------- Print #5, Str$(n%)+" Hello, ";Time$;" "; b$+b$ : Pause 90 'print characters in the receive buffer if no framing error 'UART_RX%() uses the global variable rx$ to assemble all data in. If UART_RX%() Then Print rx$, Asc(rx$) 'print the received string Else Print "framing error UART_RX%()"; UART_RX%() Poke word pio_1_irq,255 'clear framing error End If Pause 1000 Loop > RUN 0 Hello World, I admire your beautiful beaches Rx Baud Rate 19200 1 Hello, 17:38:23 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 49 2 Hello World, I admire your beautiful beaches Rx Baud Rate 19200 3 Hello, 17:38:24 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 51 4 Hello World, I admire your beautiful beaches Rx Baud Rate 19200 5 Hello, 17:38:26 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 53 6 Hello World, I admire your beautiful beaches Rx Baud Rate 19200 7 Hello, 17:38:27 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 55 > 0 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 1 Hello, 17:40:02 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 49 2 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 3 Hello, 17:40:03 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. 51 4 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 5 Hello, 17:40:04 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over the lazy dog. Edited 2025-01-20 16:41 by phil99 |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
Hi Phill, There may still be an issue when starting a new TX DMA when the old one is not yet finsihed. Needs investigation. Maybe a forced PIO TX DMA STOP before issuing a new one. I will look into that later. Thank you for helping me debug the UART. Working together is nice, and I remember you where interested in PIO as well (A+ score at the PIO training). For you this is not "black magic". Again, thanks... Volhout Edited 2025-01-20 17:15 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2606 |
Yes, when Stop is added to the start of Tx and Rx the text just gets truncated if the pause is too short. 'sends string using DMA to PIO TX Sub UART_TX(tx$) PIO stop 1,0 ... End Sub Function UART_RX%() PIO stop 1,0 Purging the residual text in the buffer would finish the job. > RUN That was with Pause 4 in each direction.0 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 1 Hello, 18:43:06 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over th 49 2 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 e lazy dog. 3 Hello, 18:43:08 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over t 101 4 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 he lazy dog. 5 Hello, 18:43:09 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over t 104 6 Hello World, I admire your beautiful beaches Rx Baud Rate 230400 he lazy dog. 7 Hello, 18:43:10 The quick brown fox jumps over the lazy dog. The quick brown fox jumps over t 104 > . Edited 2025-01-20 17:52 by phil99 |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
Hi Phill, Why do you stop PIO 1.0 (TX DMA) in UART_RX ? I would not do that. And do not stop PIO 1.1 (RX DMA) since keeping RX DMA running is the guarantee that you do not miss any characters. @Thomas: Although you may put this (later, when finished) in a library, be alert that this UART requires some resources that become unavaiable for your main program. And this is not very clear when "hidden" in a library. Volhout Edited 2025-01-20 18:12 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2606 |
No logic was used at all, just trial and error. Too hot for thinking. Yes, that was doing nothing. |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7857 |
Do you fancy a bit of weather equalization, Phil? 3°C and very overcast here, with a bit of rain forecast. :) Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
phil99![]() Guru ![]() Joined: 11/02/2018 Location: AustraliaPosts: 2606 |
Ok I will stop grumbling. If it has to be one or the other this is better, up to a point. |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
@Mick, The text of the sunny beaches was mine. That is how much I long for to see them. Phil added the neutral "fox jumps over the lazy dog". So it is me to blaim, being under the same overcast and cold sky for weeks. Volhout PicomiteVGA PETSCII ROBOTS |
||||
Mixtel90![]() Guru ![]() Joined: 05/10/2019 Location: United KingdomPosts: 7857 |
Phil: I can't imagine that it's too hot for you to think too, Volhout. :) I'd go out and fly a little drone but it's drizzling now. Not a good combination, drones, drizzle and a remarkably muddy dog-walking field. Mick Zilog Inside! nascom.info for Nascom & Gemini Preliminary MMBasic docs & my PCB designs |
||||
karlelch![]() Senior Member ![]() Joined: 30/10/2014 Location: GermanyPosts: 235 |
Hi Volhout, hi Phill, thanks for doing all the testing ![]() (I am currently very busy at work and probably won't find time for more testing before the next weekend.) True, but I am not thinking necessarily of a library that is "always" there. I think more of "drivers". For my robot, I have several "drivers" that I sequentially load as libraries and they follow a standard format (see below). These "drivers" could announce their hardware requirements on load (for example, see below). Cheers Thomas ' lib_bno055.bas v0.1.1 ' --------------------- ' BNO055 MNU driver ' 2024-02-04 - v0.1.1 - Fewer constant declarations to save global ' variable slots ' Example: ' BNO055.init ' BNO055.getEuler v() ' Print "h="+Str$(v(0),3,0)+" p="+Str$(v(1),3,0)+" r="+Str$(v(2),3,0) ' BNO055.getSystemStatus ' BNO055.close ' --------------------------------------------------------------------------- Option Base 0 Option Explicit Option Escape Option Default Float ' Constants Const BNO_ID = &HA0 ' Device ID Const BNO_ADDR = &H28 ' I2C address 'Const BNO_CHIP_ID_ADDR = &H00 ' Register addresses 'Const BNO_PAGE_ID_ADDR = &H07 'Const BNO_OPR_MODE_ADDR = &H3D 'Const BNO_PWR_MODE_ADDR = &H3E 'Const BNO_SYS_TRIG_ADDR = &H3F 'Const BNO_SYS_STAT_ADDR = &H39 'Const BNO_STEST_RES_ADDR = &H36 'Const BNO_SYS_ERR_ADDR = &H3A 'Const BNO_OPR_MODE_CONF = &H00 ' Operation mode(s) 'Const BNO_OPR_MODE_NDOF = &H0C 'Const BNO_PWR_MODE_NORM = &H00 ' Power mode(s) ' Global variables Dim integer BNO055.ready = 0, BNO055.mode = &H0C Dim integer BNO055.sys_status, BNO055.test_res, BNO055.sys_err print "BNO055 sensor driver in library" print "| Hardware requirements: I2C2" ' --------------------------------------------------------------------------- Sub BNO055.init sda, scl ' Initialize BNO055 sensor Local integer res Print "Initializing BNO055 orientation sensor ..." ' Open I2C2 for sensor SetPin sda, scl, I2C2 I2C2 Open 400, 1000 Pause 850 res = BNO055._read1(&H00) Print "| Device "+Choice(res = BNO_ID, "", "not ") +"found." BNO055.ready = res = BNO_ID If BNO055.ready Then ' Reset and configure BNO055._write1 &H3D, &H00 Print "| Resetting "; BNO055._write1 &H3F, &H20 : Pause 30 Do While Not(BNO055._read1(&H00) = BNO_ID) Print "."; Pause 50 Loop Pause 50 BNO055._write1 &H3E, &H00 : Pause 10 BNO055._write1 &H07, &H00 BNO055._write1 &H3F, &H00 : Pause 10 BNO055._write1 &H3D, BNO055.mode : Pause 20 Print "| Ready." EndIf End Sub Sub BNO055.getEuler v() ' Get Euler vector -> `v(2)` heading, pitch, roll Static integer buf(5) = (0,0,0,0,0,0), w(2) Local string s$ length 2 I2C2 Write BNO_ADDR, 0, 1, &H1A I2C2 Read BNO_ADDR, 0, 6, buf() w(0) = buf(0) Or (buf(1) << 8) s$ = Chr$(buf(2))+Chr$(buf(3)) w(1) = Str2bin(int16, s$) s$ = Chr$(buf(4))+Chr$(buf(5)) w(2) = Str2bin(int16, s$) Math Scale w(), 1/16, v() End Sub Sub BNO055.getSystemStatus ' Get system status BNO055._write1 &H07, &H00 BNO055.sys_status = BNO055._read1(&H39) BNO055.test_res = BNO055._read1(&H36) BNO055.sys_err = BNO055._read1(&H3A) Print BNO055.sys_status, BNO055.test_res, BNO055.sys_err End Sub Sub BNO055.close ' Close connection to BNO055 sensor I2C2 Close BNO055.ready = 0 End Sub Function BNO055._read1(reg%) As integer I2C2 Write BNO_ADDR, 0, 1, reg% I2C2 Read BNO_ADDR, 0, 1, BNO055._read1 End Function Sub BNO055._write1 reg%, val% I2C2 Write BNO_ADDR, 0, 2, reg%, val% End Sub Function _b2s$(a%(), n) As String Local integer i Local string s$ = "" For i=0 To n-1 : _b2s$ = _b2s$ +Hex$(a%(i),2) : Next End Function ' --------------------------------------------------------------------------- |
||||
Volhout Guru ![]() Joined: 05/03/2018 Location: NetherlandsPosts: 5054 |
I think I have included all fixes. PIO_UART_09 is the version that live assembles the PIO code, and needs v6.00.02b0 or newer to run. PIO_UART_10 the assembly is removed, just the binaries are included. This version should run on 6.00.01 and earlier (later than 5.07.04b27) PIO_UART_09.zip PIO_UART_010.zip Additional comprimations can be done by replacing the PIO(SHIFTCTRL xxxx) and others with the corresponding number. But that would remove flexibility (what pins to use, what PIO to use). It is up to you. If you put this in your application / library, please also publish the code here. I would also like to learn... Thank you, Volhout Edited 2025-01-27 22:40 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
![]() ![]() ![]() ![]() |
![]() |
![]() |
The Back Shed's forum code is written, and hosted, in Australia. | © JAQ Software 2025 |