I am still at work on a project using the DMX RS485 protocol used for lighting systems. Basically what this application does is receive the data (512 bytes) in, shift it over depending on the address requested by two capsense buttons, and send it back out starting at that address.
The problem I am having is that the data streams need to be continuous, at least for all 512 bytes plus some start of stream indication. The two ISRs are constantly firing for each byte because it takes to long either to read it all in, and then to write it all out at once and causes jerky reaction from the lights.
My question is if there is a way to have the receiving ISR go until its buffer is full, then turn off, and turn on the transmit ISR. The transmit ISR would then transmit it's 512 bytes, and turn off, turning back on the receive ISR.
I may be going about this in a very convoluted way, please let me know if that is the case as well.
Thank you, see attached project.
Without looking at the project: you are using the component-internal ISRs? They are doing byte-wise transfer into a buffer, right.
What you could do:
(I would suggest #1 first, then #3)
With looking at the project 😉 I would suggest to increase the buffer sizes for Rx and Tx to 600. This will enable an internal interrupt for the handling and - as a consequence - disable your interrupts for Rx Byte Received and Tx On FIFO Empty which you are using right now. Do not use them in this configuration! You can get notified when the transmission of your 512 bytes is done and when there is an Rx break. Additionally you may check the number of bytes received so far. Transmission and recept is done by the UART component "in the Background" which is truly interrupt driven in both directions.
When a buffer is received you may read it and move the result to the Tx-buffer using the blocking functions which usually will not block due to the large buffer size.
Ah, and looking into your code: The reason for any strange behaving of the interrupts may be caused by violating rule #! for handlers:
#1 Never (ever) use a delay within an interrupt handler, neither directly nor indirectly!
Thanks for all the tips! I have a few questions and comments:
Thank you for your help!
You will not learn much about DMA, since PSoC4 hasn't got DMA (yet).
When increasing the buffer of the UART you will see that the "internal" interrupt switches on. There is no need (and you should not) use this internal interrupt. It just cares that your Rx buffer gets filled and your Tx buffer gets transmitted without any action of yours. In main() you may check for progress with the APIs GetRxBufferSize() which does not return the size of the buffer, but the number of characters in the buffer. Same for GetTxBufferSize() which returns 0 (zero) when all required bytes have been sent.
There is a function to send a break and a status bit telling a break was received.
I took 600 bytes buffer size because it is fairly larger than your 512 bytes stream length.
Is there a way to mass copy the RX buffer to a software buffer to tweak and then send back out? For transmitting, can I just use a mass transmit such as PutArray?
Sorry about the DMA reference, I did not regocnize the question was about PSoC4. (DMA will only be in the upcoming PSoC4M).
Regarding the internal interrupt: it will be enabled as soon as the receiver or transmit buffers are larger than 8 bytes (for the SCB UART) or 4 bytes (for the UDB based UART). But be careful with the buffer sizes, the PSoC4 has not that much memory...
If you have interrupt problem, maybe you can set the Capsense interrupt priority higher to ensure it gets handled faster.
No, you have to kling to the API-pattern of the component and read the buffer byte-wise. You may think about directly after the read performing the operation with the data and concurrently send the new values out when you are in a hurry.
When you enable the internal interrupt, you can look at the generated source code for the UART component. The internal ISR should show you where the internal buffer is exactly, sou you could access it directly.
Its probably a circular buffer, so it won't be a simple memcpy operation. You also will bind yourself to the implementation - if it changes, you need to change your code.