SCB UART mark/space recognition

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hi,

   

I'd like to use the SCB UART of a 4200 PSoC4 with the possibility to recognize the states (begin and end) between the transmitted data on the receiver side: IDLE (mark) and SPACE (break).  Further, I need the possibility to send the break level for the defined time on the transmitter side. Obviously these all are standard functionalities of each simple UART chips but I couldn’t find the way to solve it with the SCB UART. Can anyone help?

   

regards

   

wadak

0 Likes
16 Replies
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

Welcome in the forum, Wadak!

   

The UDB version of the UART (v2.50) has got the ability to use a defined length of break signal transmission, the SCB version does have not.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

Hi Bob,

   

Yes, I already tried to use UDB UART. The UDB version of UART consumes more resources than the SCB and it make not possible to fit all other needed components as 4xPWM, DieTemp and ADC SAR Seq (I would like to make a RGBW LED bar with DMX512 interface and RDM functionality).

   

wadak

0 Likes
ETRO_SSN583
Level 9
Level 9
250 likes received 100 sign-ins 5 likes given

Not sure if this will help but the UDB PWM version has a dual

   

PWM capability, vs the SCB version is a single channel. Or the

   

PSOC 4 M version which has 8 tcpwm blocks.

   

 

   

Regards, Dana.

0 Likes
Anonymous
Not applicable

Dear Dana,

   

It was not possible to fit a project with two dual PWM components, UDB UART and ADC SAR into PSoC 42 project. But the problem is not how to fit the UDB UART: the main problem is why we have to miss simple and standard functionalities in so universal serial block such as SCB? On the other hand it has more not really useful functions than I can expect. Is there any possibility to change the functions within a component? I have some hundreds of 4200 PCoC4 on stock and it would be very nice to use it in my new project and not to have spent money for new “better” devices.

   

Regards, Wadak

0 Likes
Bob_Marlowe
Level 10
Level 10
First like given 50 questions asked 10 questions asked

You could overwrite the UART's output pin state using the APIs in UART_tx.h. There you can easily force a break signal of defined length.

   

 

   

Bob

0 Likes
Anonymous
Not applicable

This is a very good idea – I will do it! It will solve my transmitter problem. For the receiver I will make the following workaround: manually setting of UART_INTR_RX_BREAK_DETECT  bit in the rx interrupt registers (mask and set) and setting the break width to maximum of 0xF (16 bits) in the UART_RX_CTRL_REG. I hope it will work.

   

Thank you!

   

Wadak

0 Likes
Anonymous
Not applicable

Hi Wadak,

   

I'm working on a similar project. Did you managed to use SCB UART for DMX Rx. I would appreciate if you could share the code..

   

BR

   

Metin

0 Likes
Anonymous
Not applicable

Hi Metin,

   

yes, I build the working prototype of the DMX-512 receiver with SCB UART on P4. The whole project code is not finished due to my other activities. The project contains more than only the UART handling and is property of my company. If you can wait, I could create a new DMX receiver project to share the code with you, because I have other things to do at this moment. For this please contact me via contact(at)wadak.de.

   

Best regards

   

Wadak

0 Likes
alli_264371
Level 4
Level 4
25 replies posted 10 replies posted 10 questions asked

I'm using the simple way to build DMX receiver, the break detected by frame error interrupt ant the starting bit by GPIO raise interrupt.It work well in the PSOC1 and PSOC3 devices, but now I need the same solution in PSOC4 ,but the frame error interrupt not working here . I'm set checkbox to SCB frame error interrupt, in the interrupt routine I check the frame error mask, and if it occur incremented counter. So when DMX signal streamed no counter change at all. Only if I'm connect or disconnect the signal - the counter may increment by 1 ..no more  
 


I cannot confirm email and add messages due to a bug on your site, the email section is not active
0 Likes
Anonymous
Not applicable

Hi maagalex,

   

Your ISR is working correct: you see frame errors only if you make frame errors by disconnecting serial connector.  The DMX frames (512 bytes) are not divided by frame errors caused by one defected byte. You need to recognize the break level to check the start of the DMX frame. Frame errors are not the same as break level and they cannot be use for that purpose.

   

As I wrote before, you can manually set the break detect mask and get the break interrupt:

   

//--------- initializing

   

Comm_Start();

   

Comm_UART_RX_CTRL_REG  |= 0xF0000; // set break width to maximum of 17 bits 

   

Comm_INTR_RX_MASK_REG  = (Comm_INTR_RX_BREAK_DETECT | Comm_INTR_RX_NOT_EMPTY);

   

Comm_INTR_RX_SET_REG   = (Comm_INTR_RX_BREAK_DETECT | Comm_INTR_RX_NOT_EMPTY);

   

CyGlobalIntEnable;  

   

And then you can see the break interrupt within your ISR:

   

//---------- Uart ISR

   

CY_ISR(DmxUartIsr)

   

{

   

 uint32 rxData;

   

 uint32 tmpStatus;

   

 tmpStatus = Comm_INTR_RX_MASKED_REG;

   

 //------------------------- check errors

   

 if (tmpStatus & Comm_UART_RX_ERROR_MASK) // new begin after each error

   

 {

   

  Comm_CLEAR_RX_FIFO; // clear fifo

   

  s->state = DMX_WAIT_BREAK; // wait for DMX frame end

   

 }

   

 //------------------------- check break level

   

 else if (tmpStatus & Comm_INTR_RX_BREAK_DETECT) // end of old DMX frame or begin of new DMX frame

   

 {

   

  Comm_CLEAR_RX_FIFO; // clear all received bytes

   

  s->state = DMX_RECEIVE_START;

   

 }

   

  //------------------------- receive data in the state machine

   

 else if (tmpStatus & Comm_INTR_RX_NOT_EMPTY) // byte(s) in fifo available

   

 {

   

  switch (s->state)

   

….

   

I hope, it will help

   

Best regards

   

Wadak

0 Likes

Thank you Wadak, You are suggest to use SCB UART and the two empy bytes or more detect as a break?..Please explain the principe..
Maybe you mean the UDB uart using, but it not the solution..I need UDB for other purposes.. 
Anyway I solved the problem by other way.I take the RC filter with diode||Rand connect them between DMX input and other input pin.
So when break received i have the faling gpio interrupt ,and then switch the mode to raise interrupt and after receive the raise interrupt I'm enable the UART and receive the DMX bytes..  


I cannot confirm email and add messages due to a bug on your site, the email section is not active
0 Likes
Anonymous
Not applicable

Dear maagalex,

   

I mean what I wrote: these thread is about how to recognize “mark” and “space” level with SCB UART and not with UDB UART. These is not the right place to explain the principles of the serial data communication in asynchronous mode -  please read any documentation of an UART and get basics of start, data, parity and stop bits, mark and space levels and error types.

   

SPACE level is also called BREAK. The BREAK level is not the same as “two empty bytes” as you suggested. It is possible to set interrupt for detecting the break level (with SCB UART). The next received byte after you get the BREAK interrupt is the first byte of the DMX frame. Note that “frame error” refer to the “frame” of one single byte in asynchronous mode and should not be related to DMX “frame” contained 512 bytes.

   

You write, you have already solved your problem in other way. If you have still problems with BREAK recognition you can use my working sample code from previous post.

   

Best regards

   

wadak

0 Likes
alli_264371
Level 4
Level 4
25 replies posted 10 replies posted 10 questions asked

Thanks Wadak.
About the serial data and the frame error, as I know ,the lengh of the first period of the signal level are depended of the bit rate, and if that period very long (like the DMX break) ,the frame error interrupt occur .
That way working well on PSOC1 and PSOC3 RX modules, but not work at PSOC4..
I mean to explain of your method to break detection and not general data byte format ,the break detection functionality not present into the SCB module, so you are change the internal constants of the user module itself?

   

 Thank you for the code, maybe I can find the registers from your code in the PSoC Creator libraries and then can understand the principe ..

   

Alex 


I cannot confirm email and add messages due to a bug on your site, the email section is not active
0 Likes
Anonymous
Not applicable

Dear Alex,

   

Well, „my method“, is the standard way to detect the BREAK level by setting the appropriate bits in the interrupt register. The only problem was that the register and the needed bit sets are not directly accessible via SCB component menu and they have to be set manually:

   

Comm_UART_RX_CTRL_REG  |= 0xF0000;

   

Comm_INTR_RX_MASK_REG  = (Comm_INTR_RX_BREAK_DETECT | Comm_INTR_RX_NOT_EMPTY);

   

Comm_INTR_RX_SET_REG   = (Comm_INTR_RX_BREAK_DETECT | Comm_INTR_RX_NOT_EMPTY);

   

Where “Comm” in my sample code corresponds to the name of the SCB module. All constants are defined by the creator in the file “Comm.h”

   

If the name your SCB module is for example “dmxrec”, then the code above should be as follow:

   

dmxrec_UART_RX_CTRL_REG  |= 0xF0000;

   

dmxrec_INTR_RX_MASK_REG  = (dmxrec_INTR_RX_BREAK_DETECT | dmxrec_INTR_RX_NOT_EMPTY);

   

dmxrec_INTR_RX_SET_REG   = (dmxrec_INTR_RX_BREAK_DETECT | dmxrec_INTR_RX_NOT_EMPTY);

   

You will find your constants within your project in file “dmxrec.h”.

   

Best regards

   

wadak

0 Likes

Hi, Do you have a small project with just the RX code? I would be interested to look over the whole thing. I am having trouble implementing the code in your post.

   

Regards,
Tom

0 Likes

Here is my ISR code, it detects the break, but never gets to teh RX_NOT_EMPTY unless I comment out the break check:

   

// ISR For Break
CY_ISR(InterruptHandlerDMXIn)
{
    int status = 0;
    int test = 0;
    
    // Stores first run status 
    static uint8 isFirst = FALSE;
    
    // index of dmxReadPtr in array DMXbuffer
    ptrdiff_t ptrIndex = 0;
    
    // Read status, and clear interrupt
    status = UART_DMX_RX_INTR_RX_MASK_REG;

   

    // Get location of pointer
    ptrIndex = dmxReadPtr - DMXReadBuffer;
    
    // Check for error
    if(status & UART_DMX_RX_UART_RX_ERROR_MASK)
    {
        // Clear fifo
        UART_DMX_RX_CLEAR_RX_FIFO; 
        
        state = DMX_WAIT_BREAK;
    }   
    
    // Check for break
    else if(status & UART_DMX_RX_INTR_RX_BREAK_DETECT)
    {
        // Reset pointer
        dmxReadPtr = DMXReadBuffer;
        
        // Set state
        state = DMX_RECEIVE_START;
        
        // Clear buffer
        UART_DMX_RX_CLEAR_RX_FIFO; 
    }
    
    // If data ready, read data
    else if(status & UART_DMX_RX_INTR_RX_NOT_EMPTY)
    {       
        // If less than DMX buffer size, read data into buffer
        if(ptrIndex < DMX_SIZE){*dmxReadPtr++ = UART_DMX_RX_SpiUartReadRxData();}
        else{
            // Clear buffer
            UART_DMX_RX_CLEAR_RX_FIFO;    
        }
    }
    
    // Clear RX interrupt
    UART_DMX_RX_ClearRxInterruptSource(status);
}

   

Thank you,
Tom

0 Likes