Shop OBEX P1 Docs P2 Docs Learn Events
4 cog 4 serial — Parallax Forums

4 cog 4 serial

luigi_dipluigi_dip Posts: 9
edited 2013-04-09 02:13 in Propeller 1
Hi,
i'm using 4 cog for receive simultaneusly from 4 serial trasmitter after the same trigger.
After that, i've to send all the data (4 bytes for serial) to another serial.
My problem is to syncronize all the data: i wish that the trasmission begin when all the 4 rx serial have finished.
I attach the code i'm using for receive the data and send it. This is an extrapolation of the FullDuplexSerial Object.
I don't know how to set a flag in the 4 cog that could be read from the hub and start the transmission.
Any suggestions???

Gigi

Comments

  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-02 08:33
    You've certainly picked a complex way of trying to solve your problem. First of all, there's a 4 port serial object in the OBEX (here) that, like FullDuplexSerial, has a method that either returns a character or a -1 to indicate that there have been no characters received. A loop like this would read one character from each port and exit when all 4 ports have provided a character:
    var long port, count, char[4]
    obj serial : "fullDuplexSerial4port"
    ' ... initialization, etc.
    longfill(@char, -1, 4)   ' Initialize char
    repeat
       count := 0
       repeat port from 0 to 3
          if char[port] == -1   ' If character not received yet
             char[port] := serial.rxcheck(port)   ' Check port
          if char[port] <> -1
             count++  ' Number of characters received
    until count == 4
    ' Here's where we can transmit the packet
    
  • luigi_dipluigi_dip Posts: 9
    edited 2013-04-03 06:00
    This is an interesting project, but i need to solve the problem in another way because i need more speed. So i need to know how to set a flag in the asm routine and read it in the hub routine. I need a flag each serial receiver.
    For example i wish to set a counter at the end of the reading procedure that start from 4 to 0. When this counter goes to zero i set this flag; after that i've read all the 4 flag setted, I clear it in the spin part of the code. How can i do it? i'm not able to pass easily a variable from asm to spin. I've read many example and try it but these doesn't work.
    For example at the end of the receiver routine i use this counter cnt1. Every time I pass from there I subtract 1. When this counter became 0 i set the flag. Can you explain me how to do it?


    I declare a variable in the spin part

    long ptr_flag1
    ...........

    ptr_flag1:=@flag1
    .............

    rdlong t2,par 'save received byte and inc head
    add t2,rxbuff
    wrbyte rxdata,t2
    sub t2,rxbuff
    add t2,#1
    and t2,#$03
    wrlong t2,par

    rdlong temp,flag1
    sub cnt1,#1
    cmp cnt1, #0 wz
    if_nz mov cnt1,#4
    if_nz mov temp, #1

    wrlong temp,flag1

    jmp #receive 'byte done, receive next byte



    temp long 0
    flag1 long 0

    This doesn't work.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-03 06:41
    First of all, you need to say more about what you're trying to do and what the timing constraints might be. When do you consider the input characters received? Some serial routines store the character at the midpoint of the bit cell of the last bit and some routines check for a valid stop bit at the midpoint of the bit cell of the stop bit before considering the character as finished. How much time do you then have before the output characters start transmitting? What do you mean by synchronize? What are the timing constraints on that?

    The issue here is that you're proposing a solution before you've laid out the problem to be solved. For example, your packet size is 22 bytes and represents 4 successive bytes from each of 4 serial ports. How often are the triggers expected? I ask because you're transmitting more than you're receiving and you'll run out of transmit buffer space if the triggers come in too quickly. What happens if the data gets out of sync? What if there's noise on one of the data lines and a byte is dropped?

    My bias is to leave the assembly language stuff alone, maybe write another assembly routine (for a separate cog) that essentially implements the loop I wrote above, but, rather than calling rxcheck, implements the equivalent by checking the buffer pointers directly to see whether there are characters in the buffer. This cog could even implement your main loop completely if your timing constraints are tight enough.
  • luigi_dipluigi_dip Posts: 9
    edited 2013-04-03 07:06
    Ok. I'll try to explain better all the problems. In my system there is an external trigger that give the start to 4 sensors. These 4 sensors send by separate serial channels 4 bytes each to propeller.In total 16 byte. This trigger is every 2,8ms.
    So i've to take this 4 byte (380us in parallel at 115200) from every sensor by serial. Simultaneously I've to take a packet of 20 bytes from another sensor by SPI (about 400us). I've maximum 500us since the trigger to take all these informations. After that i've to create a packet to send.
    In reality i've to send this packet by a parallel bus 8 bit/1Mhz on request before that arrive another trigger. So i've only to set high a pin to give the information of a data_ready to another microcontroller and wait for the clock on another pin to send the data.
    Obviously i've to syncronize all the pkt that arrive after the trigger for sure. I can discard all the pkt received before the trigger.
    Note that I receive from serial a pkt without markers so i recognise that a byte it's arrived only from the bit start.
    Do you need other information?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-03 07:46
    I think it would be simplest to have one cog for each serial line with a single purpose receive routine in assembly that waits for the trigger, then looks for 4 bytes which are stored as a single long when all the bytes are received. You would have only one routine that's initialized with the I/O pin to use, the address of a long to use as a buffer, and the address of a long to use as a flag indicating that the buffer has a value in it. Another cog will manage the SPI bus and receive (and format) the 20 bytes, ready for transmission. All of these assembly routines would wait for the trigger independently and set a separate flag to indicate that they've completed their work. Another cog would wait for the trigger, then begin checking the 5 flags waiting for them all to be true (A and B and C and D and E). It would then send the data on the 8-bit bus. That's 6 cogs. One more cog would be running Spin, would do the initialization of the others, and could be used for debugging once all the other cogs are started. It could monitor the various buffers and format the data for display using the 8th cog for either a TV video driver or FullDuplexSerial for connection to a PC.
  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-03 07:57
    Attached is a Spin-only serial driver that's too slow in Spin, but would be a good model for something in assembly that would work (the rx routine with a loop to assemble the 4 bytes into a long). How does this scheme sound?
  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-03 09:30
    Here's an example of such a serial input routine. I haven't tested it, but it looks right. Obviously this needs to be embedded in a larger program.
  • luigi_dipluigi_dip Posts: 9
    edited 2013-04-04 07:24
    I've try with your example.spin.
    It's just what i'm looking for but unfortunately it doesn't work!!!
    This is the spin i've prove. I've only change the pins. I send the trigger and the serial pkt in the right way (i've seen it with an oscilloscope)
    what's wrong?? The code appears good!
    The flags are never been set. I've try with this code to take a look at the flags but all the serial vector has value 0x80...every byte
  • Mike GreenMike Green Posts: 23,101
    edited 2013-04-04 09:31
    I made a mistake in the code. There's a line " or dira,recvMsk ' make I/O pin an input". Remove it. It sets the I/O pin to output mode. Sorry.

    I made some corrections to your program as well
  • luigi_dipluigi_dip Posts: 9
    edited 2013-04-05 01:25
    Still doesn't work :(
  • kuronekokuroneko Posts: 3,623
    edited 2013-04-05 02:49
    FWIW, the example posted in #10 works just fine after the following changes:
    • change any pin 23 reference to triggerPin (5x)
    • change any long[@paramAddr][?] expression to long[paramAddr][?] (3x)
  • luigi_dipluigi_dip Posts: 9
    edited 2013-04-05 03:21
    Fine! This works now. Now i'll try to send the data received by parallel port using the bus_slave function started in another cog. I'll post the project when finished
  • luigi_dipluigi_dip Posts: 9
    edited 2013-04-08 03:51
    Could you help me to change the number of byte to receive in a variable and save it in a buffer of byte? I've try to do it but unsuccesfull :(
  • luigi_dipluigi_dip Posts: 9
    edited 2013-04-09 02:13
    I've integrated the 4 serials with the parallel transmission. Now the mission is to integrate also the spi communication in another cog. This routine works stand alone but if i activate its cog in the full project the bus_slave and the serial doesn't work.
Sign In or Register to comment.