Shop OBEX P1 Docs P2 Docs Learn Events
Uart buffer — Parallax Forums

Uart buffer

Zachary LewisZachary Lewis Posts: 6
edited 2008-05-23 04:45 in General Discussion
I had a quick question about extending the Uart buffer beyond its standard size.

I am communicating with a C328 Camera module. I was counting on being able to control package sizes and not overfill the serial buffer before I could read all of the image data I needed. I recently found out though that if I'm retrieving an uncompressed image file (which I am) that it does not operate in package mode. Instead, it will send all 5kb+ (depending on what I set the resolution to). There is no way to stop the camera from continuing to send data if the buffer is close to filled or filled. No handshaking pin and there is no command that I can find that is recognized by the C328 that will stop transmission.

Here is the really short users manual for the C328 camera module:
http://www.electronics123.net/amazon/datasheet/C328R_UM.pdf

In the Uart class itself I COULD go in and change the stdBufferSize property. This breaks some of the other code in the Uart object though and probably isn't recommended to try and change those classes in the first place.

In a perfect world this camera module would actually have some form of handshaking to start and stop transmission.

Is there any way to get around this on the Javelin?

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-29 02:32
    The original Uart class, as distributed with the JIDE software, has the buffer declared
    as an array of 128 integers. In my adapted uart class (downloadable from the Yahoo group)
    I redefined it to be a char array of 256 characters. This speeds up code as it is no longer
    necessary to split integers. However, the buffer size cannot exceed 256 bytes
    because the JVM uses a byte for its head and tail pointers.
    So your options are :
    1. Get an external buffer that can hold all the bytes and that presents handshake signals to
    the javelin.
    2. Try baudrate 7200 (seems to be the lowest possible baud, else try 2400 or even 1200 baud)
    Use a tight loop to read received characters and put them in· a userdefined character array.
    The throughput of such a tight loop is about 10kbps, so 7200 baud might just work.

    char buf = new char[noparse][[/noparse]5000];
    for (int i=0; i< 5000; i++) { //read in data after issueing a Get Picture command
    · buf[noparse][[/noparse]i] = (char)rx.receiveByte();
    }

    regards peter
  • barichards21barichards21 Posts: 7
    edited 2008-01-29 07:03
    Any chance you could direct me towards something that would work as a basic serial buffer with handshaking?

    This is the same person that posted this message I just forgot my groupmate was still logged in.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-29 08:29
    How much memory are we talking about? This kind of solution is
    usually not cheap.

    http://www3.sympatico.ca/photologic/fi.htm
    http://www.wut.de/e-88642-ww-daus-000.php

    regards peter

    Post Edited (Peter Verkaik) : 1/29/2008 8:35:43 AM GMT
  • barichards21barichards21 Posts: 7
    edited 2008-01-29 21:38
    Tried doing it at 7200 baud and it would still overflow the buffer before I could read everything from it. Could only get 156 bytes of the picture. I'm looking at around 5k-10k bytes for the picture size.

    Also one weird question about the receieveByte() method in the Uart class. It returns an integer. Is that integer just padded in a way to where if I cast it to a char it will be just one byte of information that was sent from the camera? Or does it actually return two bytes of information from the character in one int? Is this something that's more clear if I use your modified Uart?

    I found some older serial buffers on ebay and such that might do the trick. Do external serial buffers in this situation mainly just provide me a way to use the handshaking bit with the Uart class to stop and start transmission based on the amount of space left in my Uart buffer?

    Sorry, I guess I included about 50 questions all in one post.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-29 22:16
    The receiveByte() returns an int as type but values 0-255 so it really is a byte.
    If you are using the original Uart, the receiveByte() is

    · /**
    ·· * Receives a byte from a receive Uart. This method will block until a
    ·· * byte is available.
    ·· *
    ·· * @return the next byte in the receive buffer.
    ·· */
    · public int receiveByte() {
    ··· int b;
    ··· if ( vpBank == NOT_INSTALLED ) {
    ····· return -1 ;
    ··· }
    ··· while ( true ) {
    ····· int headPointer = CPU.readRegister( vpBank|nmUartHead );
    ····· int tailPointer = CPU.readRegister( vpBank|nmUartTail );
    ····· if ( headPointer != tailPointer ) {
    ······· int index = tailPointer>>1;
    ······· if ( (tailPointer&1) == 0 )
    ········· b = (byte)(buffer[noparse][[/noparse]index] >>> 8);
    ······· else
    ········· b = (byte)(buffer[noparse][[/noparse]index] & 0x00ff);
    ······· tailPointer++;
    ······· CPU.writeRegister( vpBank|nmUartTail, tailPointer );
    ······· break;
    ····· }
    ··· }
    ··· // Inform the receiver so it can do the handshaking.
    ··· rxRead(vpBank);
    ··· return b;
    · }

    My adapted Uart class has the following receiveByte()

    · /**
    ·· * Receives a byte from a receive Uart. This method will block until
    ·· * a byte is available.
    ·· *
    ·· * @return the next byte in the receive buffer.
    ·· */
    · public int receiveByte() {
    ··· int b;
    ··· while ((b=readByte()) == -1) ;
    ··· return b;
    · }

    · /**
    ·· * This is the main receive method.
    ·· * Receives a byte from a receive Uart. This method returns -1
    ·· * if no byte is available.
    ·· *
    ·· * @return the next byte in the receive buffer.
    ·· *········ If parity is used, the byte returns with bit7 set if parity error
    ·· *········ -1 if buffer empty.
    ·· */
    · public int readByte() {
    ··· int b; boolean error;
    ··· int headPointer = CPU.readRegister(vpBank|nmUartHead);
    ··· int tailPointer = CPU.readRegister(vpBank|nmUartTail);
    ··· if (headPointer == tailPointer) return -1;
    ··· b = buffer[noparse][[/noparse]tailPointer++]&0xff;
    ··· CPU.writeRegister(vpBank|nmUartTail,tailPointer);
    ··· // Inform the receiver so it can do the handshaking.
    ··· rxRead(vpBank);
    ··· if (parity != 0) { //check for parity error
    ····· error = (parity == UartTools.ODD) ? !UartTools.isOddParity(b) : !UartTools.isEvenParity(b);
    ····· b &= 0x7F; //normally bit7 is clear when using parity
    ····· if (error) b |= 0x80; //set bit7 to indicate parity error
    ··· }
    ··· return b;
    · }

    I redefined the buffer as a character array, so access is faster. If you comment out the parity part
    of readByte() you can make it even faster.
    Using an external buffer with handshake towards the javelin, lets you control the pace
    at which the javelin reads data. The side of the external buffer that connects to the camera
    does not use the handshake signals.

    regards peter
  • barichards21barichards21 Posts: 7
    edited 2008-01-30 00:36
    Ok the modified Uart seems much better for what I'll be using.

    I've found some decently cheap serial buffers that would work, but the problem is I have a limited amount of space to work with and the average size of the external buffers seems to be around 4"x5"x1".

    When I bought the Javelin one of the main things that sold me on it was this line:
    - 32 k bytes of RAM/program space (leftover space can be used for variables, arrays, and serial buffers


    If I could avoid having to buy the external serial buffer it would make my life much easier. It really made it sound like if I wanted to I could use as much of the RAM as I wanted to as a serial buffer. Without trying to rewrite many of the core files for the javelin, is this just not going to be possible?

    I guess if it's just not possible I should just start looking into a different camera module that actually has flow control available.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-30 00:50
    You can use as much ram as you wish for a serial buffer (as memory serves)
    but, and this applies to all devices not just javelin, without flow control there
    is always a problem if a device has a sustained datastream. The javelin has
    256 byte driver buffers, most hardware uarts only have 16 byte buffers.
    I wouldn't be surprised if your camera does have flow control but it may
    just not be made external accessible.
    Another camera module might be a better idea, and cheaper, than an
    external serial buffer.
    When using handshake, the javelin will never miss data.

    regards peter
  • barichards21barichards21 Posts: 7
    edited 2008-01-31 10:51
    Well I was able to find a 2M (up to 600k/s speed) external serial buffer on ebay for $5 (list price of $200). It's pretty big and heavy but hopefully we will have room on it for the robot if we don't end up finding any other options.

    I will keep looking for other smaller and cheaper ways to solve this problem. Thanks for your advice and if you happen to think of any other way around this communication issue feel free to update me.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-01-31 12:01
    After taking another look at the datasheet, it looks as if you can set the packet size
    from 64 to 512 bytes (default is 64). If you set it to 128 bytes then you should have no loss of data,
    because each packet must be acknowledged, so be sure to read all bytes before sending ACK.
    This only works for compressed images (jpeg). But if you can set the compression factor to highest quality
    there should be not much difference from uncompressed.
    It only means you must convert to raw data in your javelin code (if you want uncompressed data).

    I found this demo code in C.
    http://www.electronics123.net/amazon/datasheet/C328_C_Demo.cpp


    regards peter

    Post Edited (Peter Verkaik) : 1/31/2008 12:08:56 PM GMT
  • barichards21barichards21 Posts: 7
    edited 2008-02-01 00:30
    Well the problem is I tried to look up information on JPEG encoding (to maybe find a way to easily convert the jpeg file and just pull RGB data out of it). I'm not too worried about quality of the picture I'd lose if I can just figure out how to do it. If converting back to raw image data from JPEG is anywhere near as complicated as the process to compress it, I don't think it's something I'm going to be able to figure out in a short amount of time. I also had a hard time just trying to decipher when the image data starts in a JPEG file (all the tags and header information of the file throw me off).
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2008-02-01 01:26
    Maybe this will help:
    http://www.impulseadventure.com/photo/jpeg-decoder.html

    regards peter
  • jmspaggijmspaggi Posts: 629
    edited 2008-05-23 04:45
    Hi Peter,

    Do you know if there is same kind of decoder code, but in Java? I'm not familiar enough with C/C++ to translate it. A camera like this one, or C628 model will help me for my color detection module.

    The C328 camera can't use package mode for uncompressed files, so I will have the same issue as barichards21 regarding the buffer size. If I found a way to decompress the JPEG file, then I can do like what you suggest regarding the packages ack.

    barichards21, can you share information regarding the serial buffer you found? I was not able to find any under $300 [noparse]:([/noparse]

    Thanks,

    Regards,

    JM
Sign In or Register to comment.