Video data compression for serial link

On Sun, 28 Apr 2019 15:11:50 -0400, bitrex <user@example.net> wrote:

I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just using a
KISS implementation, constant-overhead-byte-stuffing protocol, two bytes
per value, with a simple CRC-type checksum appended to each scanline the
link needs to be around 384kbps to support the amount of
data required to transmit.

Since some variants o ARM Cortex also support Ethernet, did you
considered using such part and thus, simplify the connectivity to the
external world ?

Implementing UDP on a device supporting Ethernet is trivial. Put three
10 bit samples into four bytes and at least 1024 horizontal pixels
fits nicely into a single Ethernet or UDP telegram. Add frame and line
numbers and the receiver can take appropriate actions, if it fails to
catch some of the telegrams sent.
 
On 4/30/19 5:22 AM, Martin Brown wrote:
On 29/04/2019 18:04, bitrex wrote:
On 4/29/19 7:10 AM, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, April 28, 2019 at 3:11:55 PM UTC-4, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just
using a
KISS implementation, constant-overhead-byte-stuffing protocol, two
bytes
per value, with a simple CRC-type checksum appended to each scanline
the
link needs to be around 384kbps to support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash up is
unstable, there's a bottleneck somewhere, most likely on the PC side as
it's not a "real" hardware serial port but virtualized via USB and it
has to go thru all the multiple layers of abstraction from the
application until it finally gets spit out; the application code isn't
even complied it's from a scripting language.

Windoze is nothing like an RTOS and has always been dodgy at fast serial
data since forever. My money is on a FIFO buffer overflow whilst the PC
is off doing something "more important" - screen updating or disk IO.

Using compiled C/C++ that can do system calls directly will probably
help but I'm also looking for ways to compress the serial stream
bandwidth. For 10 bit greyscale data I was thinking that just something
like u-law or A-law encoding could significantly reduce the bandwidth
without resorting to more compute-intensive bespoke video compression
algorithms. Primary requirement is that the link needs to be very
fault-tolerant and reliable for long term operation

What does "unstable" mean?  Do you loose data or are there simply
variable delays?  Do you buffer up data in the CPU for display?  I
would think you'd want to understand the problem before you try to
find a cure.

The KISS communication implementation works perfectly fine for a while
and then both the uP and PC app lock and it fails utterly.
transmission stops. annoying problem to diagnose. Logging the data on
the link doesn't show anything unusual just prior to it happening.

OK the first thing to try is drop the most significant bytes entirely
and live with bullseye effects on the highlights to see if as a proof of
concept halving the volume of data will bring it back under control.

If that works then you have two basic KISS choices:

Transform the 10 bit data into 8 bit data using a lookup table

y' = INT(8*sqrt(y)+0.5)  would do for a start

Or since you know you must have an average step of 4 and have 1024
levels to transform into 256 output levels choose something like

if (y<65)  y' = y
else y' = A + (y-64)/5

As a piecewise linear approximation to a nonlinear tranform that
preserves all the dynamic range at the low end at the expense of
highlight detail. Better approximations are available and you might want
to think carefully about rounding rules to preserve details.

The other option if you have a bit more time to spare on the encoding
side is for each line OR the high bytes together and based on that
result send a scaled version and a tag in the line CRC to say whether
the line scaling is 1x, 2x or 4x.

About all I can say at this point is that it doesn't happen (at least
not over the course of a day's runtime) at lower data rates. And that
since the transmission is only one-way I don't see any good reason for
the PC application to lock up other than the issue originating on that
side of things.

How locked up it is? Is it just the user application that is
unresponsive or has the thing really gone AWOL inside a driver?

How fast are you running the serial link?

I don't think the eye has the same sensitivity to light as the ear
does to sound.  uLaw works by approximating a log relationship which
matches human sensitivity to sound.  More resolution is given to soft
sounds extending the effective number of bits than what is transmitted.

all human senses are more-or-less logarithmic in response. the
difference in actual brightness between walking outside into a bright
spring morning like today, from say an office lit in a usual
office-way with ceiling fluorescents is like, a million times brighter
outside (sorry not really an optics-guy I don't know the appropriate
unit to use, here.) but we don't go blind

If you are convinced the problem is too high bandwidth, I agree with
Hul, you are adding 6 bits of overhead by having empty bits on each
word.  With Hul's packing you can shove the CRC and a sync bit into a
32 bit word and get a 60% bandwidth increase.  If you need to, do the
data reshuffling and CRC check in a small FPGA and present the CPU a
FIFO interface via SPI like signals where the overhead isn't important.


In any case it was just an idea on how two bytes of data could be
stuffed into one, in fact since the data is only 10 bits I'd first
just try right shifting 2 on the way out then left shifting on reception.

It may be that the re-write of the transmission code in C solves the
immediate problem so some of my request is just for my reference if
further optimization should be necessary. Byte-packing, at the very
least, doesn't seem like premature optimization regardless.

I think  making the transmission code go even faster will almost
certainly make things worse if the problem is due to buffer overflow in
the PC end serial receiver.

I've been doing a CRC for each line rather than each frame as the
client doesn't need pixel-by-pixel correctness, if a line is wrong
then just dump it and wait for the next frame.

Quick and dirty test is send only the least significant byte and see if
that ever locks up. At least then you have a working baseline again.

The other trick might be to run the PC side in a debugger and hope to
catch the trap inside the errant driver. There may be options on the
fake serial implementation driver to make its IO buffers deeper.

Good serial drivers are possible on a PC but not in Windoze. The OS/2
serial driver was capable of implementing full 16550 hardware FIFO
behaviour on the crudest bare metal original stone age serial ports.

Thank you Martin, you have good suggestions here that will take me some
time to explore but I'll update when I have more answers.

The good news is this design will be talking to Macs or Linux machines
only - no Windows here.
 
On Tue, 30 Apr 2019 10:22:03 +0100, Martin Brown
<'''newspam'''@nezumi.demon.co.uk> wrote:

On 29/04/2019 18:04, bitrex wrote:
On 4/29/19 7:10 AM, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, April 28, 2019 at 3:11:55 PM UTC-4, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just using a
KISS implementation, constant-overhead-byte-stuffing protocol, two bytes
per value, with a simple CRC-type checksum appended to each scanline the
link needs to be around 384kbps to support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash up is
unstable, there's a bottleneck somewhere, most likely on the PC side as
it's not a "real" hardware serial port but virtualized via USB and it
has to go thru all the multiple layers of abstraction from the
application until it finally gets spit out; the application code isn't
even complied it's from a scripting language.

Windoze is nothing like an RTOS and has always been dodgy at fast serial
data since forever. My money is on a FIFO buffer overflow whilst the PC

While Windows is not a hard RTOS, this affects mainly half duplex
causing large latencies, if some protocol is done in user mode.
Assuming a half duplex slave protocol, the kernel mode driver receives
the request and tries to wake up the user mode protocol processing.
The user mode activates after some undefined amount of time, generates
a response, which is sent by the kernel mode driver back to the serial
line. The foreign master sees this as a greatly varying response time
and if the master timeout is set too tightly, may eve timeout, before
the response from Windows arrives.

Last century, some bad PC hardware caused a lot of lost interrupts on
serial lines by disabling interrupts. Some floppy and CD controllers,
some Ethernet adapters and some display adapters were particularity
bad. By avoiding these bad apples, the Windows serial handler can
capture all received bytes, before any UART hardware with reasonable
sized hardware FIFO overflows.

I haven't seen such problems with modern hardware.

The next problematic point is the kernel mode to user mode transition.
By using SetupComm() quite large kernel mode buffers can be allocated,
into which the kernel driver inserts more bytes, until the user mode
code wakes up and handles the received bytes. If the user mode
protocol code doesn't call SetupComm(), at least previously, the
default kernel mode Rx buffer was quite small, increasing the risk of
overflowing the kernel mode buffer.
 
upsidedown@downunder.com wrote in
news:chvgceptjabvns9b4h6049ogl10ui76mjt@4ax.com:

On Tue, 30 Apr 2019 10:22:03 +0100, Martin Brown
'''newspam'''@nezumi.demon.co.uk> wrote:

On 29/04/2019 18:04, bitrex wrote:
On 4/29/19 7:10 AM, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, April 28, 2019 at 3:11:55 PM UTC-4, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now
just using a KISS implementation,
constant-overhead-byte-stuffing protocol, two bytes per value,
with a simple CRC-type checksum appended to each scanline the
link needs to be around 384kbps to support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the
lash up is unstable, there's a bottleneck somewhere, most
likely on the PC side as it's not a "real" hardware serial
port but virtualized via USB and it has to go thru all the
multiple layers of abstraction from the application until it
finally gets spit out; the application code isn't even
complied it's from a scripting language.

Windoze is nothing like an RTOS and has always been dodgy at fast
serial data since forever. My money is on a FIFO buffer overflow
whilst the PC

While Windows is not a hard RTOS, this affects mainly half duplex
causing large latencies, if some protocol is done in user mode.
Assuming a half duplex slave protocol, the kernel mode driver
receives the request and tries to wake up the user mode protocol
processing. The user mode activates after some undefined amount of
time, generates a response, which is sent by the kernel mode
driver back to the serial line. The foreign master sees this as a
greatly varying response time and if the master timeout is set too
tightly, may eve timeout, before the response from Windows
arrives.

Last century, some bad PC hardware caused a lot of lost interrupts
on serial lines by disabling interrupts. Some floppy and CD
controllers, some Ethernet adapters and some display adapters were
particularity bad. By avoiding these bad apples, the Windows
serial handler can capture all received bytes, before any UART
hardware with reasonable sized hardware FIFO overflows.

I haven't seen such problems with modern hardware.

The next problematic point is the kernel mode to user mode
transition. By using SetupComm() quite large kernel mode buffers
can be allocated, into which the kernel driver inserts more bytes,
until the user mode code wakes up and handles the received bytes.
If the user mode protocol code doesn't call SetupComm(), at least
previously, the default kernel mode Rx buffer was quite small,
increasing the risk of overflowing the kernel mode buffer.

RTMP Real Time Messaging Protocol. It buffers things and reduces
dropped frames. Made for streaming.
 
On Tuesday, April 30, 2019 at 3:04:43 PM UTC-7, DecadentLinux...@decadence.org wrote:

On Sunday, April 28, 2019 at 3:11:55 PM UTC-4, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data

RTMP Real Time Messaging Protocol. It buffers things and reduces
dropped frames. Made for streaming.

So, a different networking protocol?

As long as USB is universally available, though, a hardware solution
(first-in-first-out memory buffer) is as easy to add as replacing the
USB/serial dongle with a USB connection through a FT245 interface chip.

Involving a full network of switches and wires, just doesn't seem useful
when a short-distance one-computer-one-peripheral link is wanted.
There's too many points-of-failure.
 
On 4/30/19 9:02 PM, Dave Platt wrote:
In article <KcJxE.768986$Z%2.2694@fx48.iad>, bitrex <user@example.net> wrote:


Yes, the device we're using is ACM. on linux the uP's port is accessed
thru /dev/ttyACM0. On a Mac its identifier is some bizarre gibberish but
works the same.

On the API side of things however there does seem to be a concept of
'baud rate' as one still has to define a link speed in software prior to
transmitting or receiving data.

I sent back and re-checked this, and you're right - that sort of
negotiation is supported, although not mandatory.

The endpoint is what's known as a CDC (Communications Device Class).
This class has commands defined which allow the host to query, and
set, the line coding (bits per character, stop bits, baud rate) and
the hardware handshaking. In effect, you _can_ do to a full-featured
CDC, what you can do to a normal host-attached serial port.

I recall now that I have a small USB-attached faxmodem at home which
works this way.

You could, if you wish, actually implement an RS-232 serial port via
such a CDC endpoint, with full hardware handshaking. In effect, this
class is capable of being a standards-conforming equivalent to the
sorts of proprietary USB implementations that FTDI and Prologix and
etc. do in their serial-to-USB converters.

It's also possible to implement a CDC which does not implement these
line-related commands at all - they're optional. You'd do this if you
want a CDC which behaves very much like a speed-independent,
hardware-independent serial port... that is, you can send a string of
bytes to it, read bytes back, operate in full or half duplex, etc.,
but without having to worry about the concept of baud rate.

You might, for example, implement a speed-less CDC inside a
microcontroller, creating a "console" or "terminal" interface. This
would be more efficient and reliable, in some ways, than using the
micro's own RX and TX serial port pins, because the traffic between
host and micro would be carried directly in USB "URBs" as sequences of
bytes with full flow control. There would never be a need to do
RS-232-serial-like conversion between bytes, and individual bits
flowing over a single serial line. You could read or write hundreds
of bytes per operation, rather than having to take individual
interrupts every character or every few characters.

This looks like an example of what you're talking about:

<https://mcuoneclipse.com/2015/04/15/usb-cdc-with-the-teensy-3-1-board/>

Seems promising; strict serial is more appropriate for intermittent
async communication what I really need is higher bandwidth continuous
transmission
 
In article <KcJxE.768986$Z%2.2694@fx48.iad>, bitrex <user@example.net> wrote:


Yes, the device we're using is ACM. on linux the uP's port is accessed
thru /dev/ttyACM0. On a Mac its identifier is some bizarre gibberish but
works the same.

On the API side of things however there does seem to be a concept of
'baud rate' as one still has to define a link speed in software prior to
transmitting or receiving data.

I sent back and re-checked this, and you're right - that sort of
negotiation is supported, although not mandatory.

The endpoint is what's known as a CDC (Communications Device Class).
This class has commands defined which allow the host to query, and
set, the line coding (bits per character, stop bits, baud rate) and
the hardware handshaking. In effect, you _can_ do to a full-featured
CDC, what you can do to a normal host-attached serial port.

I recall now that I have a small USB-attached faxmodem at home which
works this way.

You could, if you wish, actually implement an RS-232 serial port via
such a CDC endpoint, with full hardware handshaking. In effect, this
class is capable of being a standards-conforming equivalent to the
sorts of proprietary USB implementations that FTDI and Prologix and
etc. do in their serial-to-USB converters.

It's also possible to implement a CDC which does not implement these
line-related commands at all - they're optional. You'd do this if you
want a CDC which behaves very much like a speed-independent,
hardware-independent serial port... that is, you can send a string of
bytes to it, read bytes back, operate in full or half duplex, etc.,
but without having to worry about the concept of baud rate.

You might, for example, implement a speed-less CDC inside a
microcontroller, creating a "console" or "terminal" interface. This
would be more efficient and reliable, in some ways, than using the
micro's own RX and TX serial port pins, because the traffic between
host and micro would be carried directly in USB "URBs" as sequences of
bytes with full flow control. There would never be a need to do
RS-232-serial-like conversion between bytes, and individual bits
flowing over a single serial line. You could read or write hundreds
of bytes per operation, rather than having to take individual
interrupts every character or every few characters.
 
onsdag den 1. maj 2019 kl. 03.02.36 UTC+2 skrev Dave Platt:
In article <KcJxE.768986$Z%2.2694@fx48.iad>, bitrex <user@example.net> wrote:


Yes, the device we're using is ACM. on linux the uP's port is accessed
thru /dev/ttyACM0. On a Mac its identifier is some bizarre gibberish but
works the same.

On the API side of things however there does seem to be a concept of
'baud rate' as one still has to define a link speed in software prior to
transmitting or receiving data.

I sent back and re-checked this, and you're right - that sort of
negotiation is supported, although not mandatory.

The endpoint is what's known as a CDC (Communications Device Class).
This class has commands defined which allow the host to query, and
set, the line coding (bits per character, stop bits, baud rate) and
the hardware handshaking. In effect, you _can_ do to a full-featured
CDC, what you can do to a normal host-attached serial port.

I recall now that I have a small USB-attached faxmodem at home which
works this way.

You could, if you wish, actually implement an RS-232 serial port via
such a CDC endpoint, with full hardware handshaking. In effect, this
class is capable of being a standards-conforming equivalent to the
sorts of proprietary USB implementations that FTDI and Prologix and
etc. do in their serial-to-USB converters.

It's also possible to implement a CDC which does not implement these
line-related commands at all - they're optional. You'd do this if you
want a CDC which behaves very much like a speed-independent,
hardware-independent serial port... that is, you can send a string of
bytes to it, read bytes back, operate in full or half duplex, etc.,
but without having to worry about the concept of baud rate.

You might, for example, implement a speed-less CDC inside a
microcontroller, creating a "console" or "terminal" interface. This
would be more efficient and reliable, in some ways, than using the
micro's own RX and TX serial port pins, because the traffic between
host and micro would be carried directly in USB "URBs" as sequences of
bytes with full flow control. There would never be a need to do
RS-232-serial-like conversion between bytes, and individual bits
flowing over a single serial line. You could read or write hundreds
of bytes per operation, rather than having to take individual
interrupts every character or every few characters.

but then the MCU has to handle USB instead of just DMAing bytes to a UART

so it isn't necessarily any better
 
On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just using a
KISS implementation, constant-overhead-byte-stuffing protocol, two bytes
per value, with a simple CRC-type checksum appended to each scanline the
link needs to be around 384kbps to support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash up is
unstable, there's a bottleneck somewhere, most likely on the PC side as
it's not a "real" hardware serial port but virtualized via USB and it
has to go thru all the multiple layers of abstraction from the
application until it finally gets spit out; the application code isn't
even complied it's from a scripting language.

Using compiled C/C++ that can do system calls directly will probably
help but I'm also looking for ways to compress the serial stream
bandwidth. For 10 bit greyscale data I was thinking that just something
like u-law or A-law encoding could significantly reduce the bandwidth
without resorting to more compute-intensive bespoke video compression
algorithms. Primary requirement is that the link needs to be very
fault-tolerant and reliable for long term operation

you want a look up table like this. It might not solve all your problems
but at least it will halve the required bit rate which should improve
things. Note the darkness details (up to 63) are not compressed at all.

{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43,
44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,
58, 59, 60, 61, 62, 63, 65, 67, 69, 71, 73, 75, 78, 80,
82, 84, 87, 89, 91, 94, 96, 99, 101, 104, 106, 109, 112,
114, 117, 120, 122, 125, 128, 131, 134, 137, 140, 143, 146,
149, 152, 155, 158, 161, 164, 167, 171, 174, 177, 181, 184,
187, 191, 194, 198, 201, 205, 208, 212, 216, 219, 223, 227,
231, 234, 238, 242, 246, 250, 254, 258, 262, 266, 270, 274,
278, 283, 287, 291, 295, 300, 304, 308, 313, 317, 322, 326,
331, 335, 340, 345, 349, 354, 359, 363, 368, 373, 378, 383,
388, 393, 398, 403, 408, 413, 418, 423, 428, 433, 438, 444,
449, 454, 460, 465, 470, 476, 481, 487, 492, 498, 503, 509,
515, 520, 526, 532, 538, 543, 549, 555, 561, 567, 573, 579,
585, 591, 597, 603, 609, 616, 622, 628, 634, 641, 647, 653,
660, 666, 673, 679, 686, 692, 699, 706, 712, 719, 726, 732,
739, 746, 753, 760, 767, 774, 781, 788, 795, 802, 809, 816,
823, 830, 837, 845, 852, 859, 867, 874, 881, 889, 896, 904,
911, 919, 926, 934, 942, 949, 957, 965, 973, 980, 988, 996,
1004, 1012, 1020}
 
On 01/05/2019 00:30, whit3rd wrote:
On Tuesday, April 30, 2019 at 3:04:43 PM UTC-7, DecadentLinux...@decadence.org wrote:

On Sunday, April 28, 2019 at 3:11:55 PM UTC-4, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data

RTMP Real Time Messaging Protocol. It buffers things and reduces
dropped frames. Made for streaming.

So, a different networking protocol?

As long as USB is universally available, though, a hardware solution
(first-in-first-out memory buffer) is as easy to add as replacing the
USB/serial dongle with a USB connection through a FT245 interface chip.

Involving a full network of switches and wires, just doesn't seem useful
when a short-distance one-computer-one-peripheral link is wanted.
There's too many points-of-failure.

Cross over network cables are available for point to point connections.
I still have one somewhere - it is purple to avoid confusion.


--
Regards,
Martin Brown
 
On 5/1/19 3:49 AM, Martin Brown wrote:
On 01/05/2019 00:30, whit3rd wrote:
On Tuesday, April 30, 2019 at 3:04:43 PM UTC-7,
DecadentLinux...@decadence.org wrote:

On Sunday, April 28, 2019 at 3:11:55 PM UTC-4, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data

RTMP  Real Time Messaging Protocol.  It buffers things and reduces
dropped frames.  Made for streaming.

So, a different networking protocol?

As long as USB is universally available, though, a hardware solution
(first-in-first-out memory buffer) is as easy to add as replacing the
USB/serial dongle with a USB connection through a FT245 interface chip.

Involving a full network of switches and wires, just doesn't seem useful
when a short-distance one-computer-one-peripheral link is wanted.
There's too many points-of-failure.

Cross over network cables are available for point to point connections.
I still have one somewhere - it is purple to avoid confusion.

Ah, the "good ol' days" I remember owning some of those. Not since
either 100 mbit or Gigabit Ethernet became common on just about
everything, whatever the standard was where the port hardware itself was
able to auto-negotiate that stuff.

In college I worked for the IT department helping setting up other
student's networking, in 1997 it was still common for students to be
bringing machines from home from the mid-late 80s like the Macintosh SE
and wanting them on the campus network. It was possible using
aftermarket equipment like Ethernet to Appletalk bridges, but it was pain.
 
On 08/05/2019 21:57, bitrex wrote:
On 4/30/19 11:45 PM, david eather wrote:


On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just
using a KISS implementation, constant-overhead-byte-stuffing
protocol, two bytes per value, with a simple CRC-type checksum
appended to each scanline the link needs to be around 384kbps to
support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash up
is unstable, there's a bottleneck somewhere, most likely on the PC
side as it's not a "real" hardware serial port but virtualized via
USB and it has to go thru all the multiple layers of abstraction from
the application until it finally gets spit out; the application code
isn't even complied it's from a scripting language.

Using compiled C/C++ that can do system calls directly will probably
help but I'm also looking for ways to compress the serial stream
bandwidth. For 10 bit greyscale data I was thinking that just
something like u-law or A-law encoding could significantly reduce the
bandwidth without resorting to more compute-intensive bespoke video
compression algorithms. Primary requirement is that the link needs to
be very fault-tolerant and reliable for long term operation

you want a look up table like this. It might not solve all your
problems but at least it will halve the required bit rate which should
improve things. Note the darkness details (up to 63) are not
compressed at all.


Hi David, sorry for the delay in my reply - if you're around can you
tell me how you came up with that table? And/or how to adapt to a
different bit depth?

A formula that will work to give the same transform approximately is:

x = int( 0.5 + 0.998*y*(4096+y)/(4096+16*y))

maps 0<y<1024 onto 0<x<255 linearly at first and then sort of log.

Did it behave OK when you halved the datarate?


--
Regards,
Martin Brown
 
On 4/30/19 11:45 PM, david eather wrote:
On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just using
a KISS implementation, constant-overhead-byte-stuffing protocol, two
bytes per value, with a simple CRC-type checksum appended to each
scanline the link needs to be around 384kbps to support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash up
is unstable, there's a bottleneck somewhere, most likely on the PC
side as it's not a "real" hardware serial port but virtualized via USB
and it has to go thru all the multiple layers of abstraction from the
application until it finally gets spit out; the application code isn't
even complied it's from a scripting language.

Using compiled C/C++ that can do system calls directly will probably
help but I'm also looking for ways to compress the serial stream
bandwidth. For 10 bit greyscale data I was thinking that just
something like u-law or A-law encoding could significantly reduce the
bandwidth without resorting to more compute-intensive bespoke video
compression algorithms. Primary requirement is that the link needs to
be very fault-tolerant and reliable for long term operation

you want a look up table like this. It might not solve all your problems
but at least it will halve the required bit rate which should improve
things. Note the darkness details (up to 63) are not compressed at all.

Hi David, sorry for the delay in my reply - if you're around can you
tell me how you came up with that table? And/or how to adapt to a
different bit depth?
 
On Tuesday, April 30, 2019 at 3:25:02 AM UTC-4, Tauno Voipio wrote:
On 30.4.19 03:53, DecadentLinuxUserNumeroUno@decadence.org wrote:
Tauno Voipio <tauno.voipio@notused.fi.invalid> wrote in news:qa7k1p
$k4s$1@dont-email.me:

On 29.4.19 21:56, DecadentLinuxUserNumeroUno@decadence.org wrote:
dplatt@coop.radagast.org (Dave Platt) wrote in
news:jurjpf-fm5.ln1@coop.radagast.org:

In article <B8GxE.398358$oy5.350898@fx06.iad>,
bitrex <user@example.net> wrote:

The KISS communication implementation works perfectly fine for
a
while and then both the uP and PC app lock and it fails
utterly.
transmission stops. annoying problem to diagnose. Logging the
data
on the link doesn't show anything unusual just prior to it
happening.

What USB-to-serial adapter/dongle are you using?

I had somewhat-similar problems when trying to run a Bitscope
from
a PC... it would work for a while and then the communication
would
freeze up.

The problem appeared to be the USB adapter I was using. It was
one of the inexpensive "translucent blue" adapters, that claim
to
have a Prologix PL-2303 serial-to-USB bridge inside... but very
probably had a clone/counterfeit chip instead. I've heard other
reports of these counterfeit chips locking up under heavy
load...
timing or chip-firmware problem, I suspect.

I swapped the adapter for a known-good FTDI serial adapter
(Mouser
and Digi-Key are both authorized FTDI distributors, so you can
be
pretty confident that they aren't selling counterfeits) and the
problem went away.

As to compression: A simple logarithmic-encoding scheme (akin
to
A-law or u-law), followed by a run-length-encoding, might do
what
you want, without introducing too many artifacts (although there
will be some). Another approach would be a 16-to-8-bit
quantization with Floyd-Steinberg error diffusion... this will
give you a fixed 2:1 compression with (I think) fairly decent
visual quality, and it would be quite fast to implement.



USB is a serial interface. Doesn't putty interface directly to a
usb port without a serial adapter?

Seems that one could write an easy app to do the whole thing.
Putty source code migt be a good read.


USB is used to get into the PC. The link from the USB dongle
to the Cortex is asynchronous serial (often miscalled RS-232).


No, it is just that RS-232D is the most commonly used asynchronous
serial communications schema at the physical layer.

EIA RS-232 is the most commonly used and the most common start-
stop signalling is ASCII.


You're a bit mislead: EIA RS-232 is an electrical specification for
connection of a data terminal equipment (computer/terminal) and a
data communication equipment (modem etc), originally for asynchronous
transfers up to 20000 bits/s, using voltage level signals.

The character transmission in start-stop mode is a different story,
as is further the character coding (usually a variant of the ISO 646
standard, like ISO 10646).

It is a common mistake to include the asynchronous octet transfer
and character coding into 'RS-232'.

Only to the pedantic. While what you say is correct, it's not important. Virtually everyone refers to an async serial port as RS-232 even when the voltage levels are something different. Like calling photocopiers "Xerox" machines or using saying they'd like a "coke" when they mean soft drink.

Even more common is to just shorten it to a "two-thirty-two" port.

--

Rick C.

+ Get a 1,000 miles of free Supercharging
+ Tesla referral code - https://ts.la/richard11209
 
On 5/8/19 10:09 PM, bitrex wrote:
On 5/8/19 5:22 PM, Martin Brown wrote:
On 08/05/2019 21:57, bitrex wrote:
On 4/30/19 11:45 PM, david eather wrote:


On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just
using a KISS implementation, constant-overhead-byte-stuffing
protocol, two bytes per value, with a simple CRC-type checksum
appended to each scanline the link needs to be around 384kbps to
support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash
up is unstable, there's a bottleneck somewhere, most likely on the
PC side as it's not a "real" hardware serial port but virtualized
via USB and it has to go thru all the multiple layers of
abstraction from the application until it finally gets spit out;
the application code isn't even complied it's from a scripting
language.

Using compiled C/C++ that can do system calls directly will
probably help but I'm also looking for ways to compress the serial
stream bandwidth. For 10 bit greyscale data I was thinking that
just something like u-law or A-law encoding could significantly
reduce the bandwidth without resorting to more compute-intensive
bespoke video compression algorithms. Primary requirement is that
the link needs to be very fault-tolerant and reliable for long term
operation

you want a look up table like this. It might not solve all your
problems but at least it will halve the required bit rate which
should improve things. Note the darkness details (up to 63) are not
compressed at all.


Hi David, sorry for the delay in my reply - if you're around can you
tell me how you came up with that table? And/or how to adapt to a
different bit depth?

A formula that will work to give the same transform approximately is:

x = int( 0.5 + 0.998*y*(4096+y)/(4096+16*y))

maps 0<y<1024 onto 0<x<255 linearly at first and then sort of log.

Did it behave OK when you halved the datarate?



I'm testing it out this week. The requirement was the final deliverable
be written in C++ anyway so that was the priority and almost finished, now.

The client's own scripting-language template for what they want was
kinda kludge-y it's been re-written in a modular way such that it's easy
to "plug-in" various encodings and compression schemes to test

That is to say the scripting language implementation behaved erratically
in general, not stable enough to tell anything for sure. It's not really
appropriate tool for the task and the data rates involved
 
On 5/8/19 5:22 PM, Martin Brown wrote:
On 08/05/2019 21:57, bitrex wrote:
On 4/30/19 11:45 PM, david eather wrote:


On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just
using a KISS implementation, constant-overhead-byte-stuffing
protocol, two bytes per value, with a simple CRC-type checksum
appended to each scanline the link needs to be around 384kbps to
support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash up
is unstable, there's a bottleneck somewhere, most likely on the PC
side as it's not a "real" hardware serial port but virtualized via
USB and it has to go thru all the multiple layers of abstraction
from the application until it finally gets spit out; the application
code isn't even complied it's from a scripting language.

Using compiled C/C++ that can do system calls directly will probably
help but I'm also looking for ways to compress the serial stream
bandwidth. For 10 bit greyscale data I was thinking that just
something like u-law or A-law encoding could significantly reduce
the bandwidth without resorting to more compute-intensive bespoke
video compression algorithms. Primary requirement is that the link
needs to be very fault-tolerant and reliable for long term operation

you want a look up table like this. It might not solve all your
problems but at least it will halve the required bit rate which
should improve things. Note the darkness details (up to 63) are not
compressed at all.


Hi David, sorry for the delay in my reply - if you're around can you
tell me how you came up with that table? And/or how to adapt to a
different bit depth?

A formula that will work to give the same transform approximately is:

x = int( 0.5 + 0.998*y*(4096+y)/(4096+16*y))

maps 0<y<1024 onto 0<x<255 linearly at first and then sort of log.

Did it behave OK when you halved the datarate?

I'm testing it out this week. The requirement was the final deliverable
be written in C++ anyway so that was the priority and almost finished, now.

The client's own scripting-language template for what they want was
kinda kludge-y it's been re-written in a modular way such that it's easy
to "plug-in" various encodings and compression schemes to test
 
On Tue, 30 Apr 2019 10:24:57 +0300, Tauno Voipio
<tauno.voipio@notused.fi.invalid> wrote:

USB is used to get into the PC. The link from the USB dongle
to the Cortex is asynchronous serial (often miscalled RS-232).


No, it is just that RS-232D is the most commonly used asynchronous
serial communications schema at the physical layer.

EIA RS-232 is the most commonly used and the most common start-
stop signalling is ASCII.


You're a bit mislead: EIA RS-232 is an electrical specification for
connection of a data terminal equipment (computer/terminal) and a
data communication equipment (modem etc), originally for asynchronous
transfers up to 20000 bits/s, using voltage level signals.

The RS-232 was also used for _synchronous_ to connect DTE to DCE.
Look at the RS-232 signal list, there is also the Tx-clock from DTE
and Rx-clock from DCE. Later on, when the D-connector was standardized
for RS-232 this too included the Tx and Rx clocks and secondary
channel etc. These are not required for asynchronous connection.

The character transmission in start-stop mode is a different story,
as is further the character coding (usually a variant of the ISO 646
standard, like ISO 10646).

It is a common mistake to include the asynchronous octet transfer
and character coding into 'RS-232'.
 
On 09/05/2019 03:09, bitrex wrote:
On 5/8/19 5:22 PM, Martin Brown wrote:
On 08/05/2019 21:57, bitrex wrote:
On 4/30/19 11:45 PM, david eather wrote:


On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just
using a KISS implementation, constant-overhead-byte-stuffing
protocol, two bytes per value, with a simple CRC-type checksum
appended to each scanline the link needs to be around 384kbps to
support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash
up is unstable, there's a bottleneck somewhere, most likely on the
PC side as it's not a "real" hardware serial port but virtualized
via USB and it has to go thru all the multiple layers of
abstraction from the application until it finally gets spit out;
the application code isn't even complied it's from a scripting
language.

Using compiled C/C++ that can do system calls directly will
probably help but I'm also looking for ways to compress the serial
stream bandwidth. For 10 bit greyscale data I was thinking that
just something like u-law or A-law encoding could significantly
reduce the bandwidth without resorting to more compute-intensive
bespoke video compression algorithms. Primary requirement is that
the link needs to be very fault-tolerant and reliable for long term
operation

you want a look up table like this. It might not solve all your
problems but at least it will halve the required bit rate which
should improve things. Note the darkness details (up to 63) are not
compressed at all.


Hi David, sorry for the delay in my reply - if you're around can you
tell me how you came up with that table? And/or how to adapt to a
different bit depth?

A formula that will work to give the same transform approximately is:

x = int( 0.5 + 0.998*y*(4096+y)/(4096+16*y))

maps 0<y<1024 onto 0<x<255 linearly at first and then sort of log.

Did it behave OK when you halved the datarate?



I'm testing it out this week. The requirement was the final deliverable
be written in C++ anyway so that was the priority and almost finished, now.

There are a whole family of such curves of the form

x = int( 0.5+k*y*(A+By)/(A+Cy))

for 0<y<Y and linear for small y and to scale by 1/N at the top end

requires

Y/N = Y*(A+BY)/(A+CY)

A+CY = AN+NBY

hence C = (N-1)A/Y + NB

Making A bigger extends linearity at the low end, increasing C extends
linearity at the high end.

Beware of C<-1 where it isn't monotonic any more.

The client's own scripting-language template for what they want was
kinda kludge-y it's been re-written in a modular way such that it's easy
to "plug-in" various encodings and compression schemes to test

The simplest one would be to drop the most significant byte. TBH I'm
surprised a scripting language can keep up with a video stream at all.

--
Regards,
Martin Brown
 
On 5/9/19 3:44 AM, Martin Brown wrote:
On 09/05/2019 03:09, bitrex wrote:
On 5/8/19 5:22 PM, Martin Brown wrote:
On 08/05/2019 21:57, bitrex wrote:
On 4/30/19 11:45 PM, david eather wrote:


On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just
using a KISS implementation, constant-overhead-byte-stuffing
protocol, two bytes per value, with a simple CRC-type checksum
appended to each scanline the link needs to be around 384kbps to
support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash
up is unstable, there's a bottleneck somewhere, most likely on the
PC side as it's not a "real" hardware serial port but virtualized
via USB and it has to go thru all the multiple layers of
abstraction from the application until it finally gets spit out;
the application code isn't even complied it's from a scripting
language.

Using compiled C/C++ that can do system calls directly will
probably help but I'm also looking for ways to compress the serial
stream bandwidth. For 10 bit greyscale data I was thinking that
just something like u-law or A-law encoding could significantly
reduce the bandwidth without resorting to more compute-intensive
bespoke video compression algorithms. Primary requirement is that
the link needs to be very fault-tolerant and reliable for long
term operation

you want a look up table like this. It might not solve all your
problems but at least it will halve the required bit rate which
should improve things. Note the darkness details (up to 63) are not
compressed at all.


Hi David, sorry for the delay in my reply - if you're around can you
tell me how you came up with that table? And/or how to adapt to a
different bit depth?

A formula that will work to give the same transform approximately is:

x = int( 0.5 + 0.998*y*(4096+y)/(4096+16*y))

maps 0<y<1024 onto 0<x<255 linearly at first and then sort of log.

Did it behave OK when you halved the datarate?



I'm testing it out this week. The requirement was the final
deliverable be written in C++ anyway so that was the priority and
almost finished, now.

There are a whole family of such curves of the form

x = int( 0.5+k*y*(A+By)/(A+Cy))

for 0<y<Y and linear for small y and to scale by 1/N at the top end

requires

Y/N = Y*(A+BY)/(A+CY)

A+CY = AN+NBY

hence C = (N-1)A/Y + NB

Making A bigger extends linearity at the low end, increasing C extends
linearity at the high end.

Beware of C<-1 where it isn't monotonic any more.

The client's own scripting-language template for what they want was
kinda kludge-y it's been re-written in a modular way such that it's
easy to "plug-in" various encodings and compression schemes to test

The simplest one would be to drop the most significant byte. TBH I'm
surprised a scripting language can keep up with a video stream at all.

It was some Java code, so not exactly the proper terminology it was not
interpreted but compiled for the Java virtual machine. I was a little
surprised that Java could access a USB serial interface as well and it
does okay but the transmission must have to propagate down thru many
layers of abstraction to the actual hardware.

It's probably fine for logging stuff at a few dozen kbps intermittently
but trying to send a continual stream of dummy data at a hundred kbps
will intermittently hang the app, even on a very recent high performance
laptop. It's not the interface's problem it can push that amount of
async data no problem when C code on Linux is driving it directly from a
/dev handle to it.
 
On 5/9/19 3:44 AM, Martin Brown wrote:
On 09/05/2019 03:09, bitrex wrote:
On 5/8/19 5:22 PM, Martin Brown wrote:
On 08/05/2019 21:57, bitrex wrote:
On 4/30/19 11:45 PM, david eather wrote:


On 29/04/2019 5:11 am, bitrex wrote:
I have a client who needs to send 10 bit greyscale video data
over a serial link from a PC to an ARM Cortex uP. Right now just
using a KISS implementation, constant-overhead-byte-stuffing
protocol, two bytes per value, with a simple CRC-type checksum
appended to each scanline the link needs to be around 384kbps to
support the amount of
data required to transmit.

the hardware is on-paper capable of that but in practice the lash
up is unstable, there's a bottleneck somewhere, most likely on the
PC side as it's not a "real" hardware serial port but virtualized
via USB and it has to go thru all the multiple layers of
abstraction from the application until it finally gets spit out;
the application code isn't even complied it's from a scripting
language.

Using compiled C/C++ that can do system calls directly will
probably help but I'm also looking for ways to compress the serial
stream bandwidth. For 10 bit greyscale data I was thinking that
just something like u-law or A-law encoding could significantly
reduce the bandwidth without resorting to more compute-intensive
bespoke video compression algorithms. Primary requirement is that
the link needs to be very fault-tolerant and reliable for long
term operation

you want a look up table like this. It might not solve all your
problems but at least it will halve the required bit rate which
should improve things. Note the darkness details (up to 63) are not
compressed at all.


Hi David, sorry for the delay in my reply - if you're around can you
tell me how you came up with that table? And/or how to adapt to a
different bit depth?

A formula that will work to give the same transform approximately is:

x = int( 0.5 + 0.998*y*(4096+y)/(4096+16*y))

maps 0<y<1024 onto 0<x<255 linearly at first and then sort of log.

Did it behave OK when you halved the datarate?



I'm testing it out this week. The requirement was the final
deliverable be written in C++ anyway so that was the priority and
almost finished, now.

There are a whole family of such curves of the form

x = int( 0.5+k*y*(A+By)/(A+Cy))

for 0<y<Y and linear for small y and to scale by 1/N at the top end

requires

Y/N = Y*(A+BY)/(A+CY)

A+CY = AN+NBY

hence C = (N-1)A/Y + NB

Making A bigger extends linearity at the low end, increasing C extends
linearity at the high end.

Beware of C<-1 where it isn't monotonic any more.

The client's own scripting-language template for what they want was
kinda kludge-y it's been re-written in a modular way such that it's
easy to "plug-in" various encodings and compression schemes to test

The simplest one would be to drop the most significant byte. TBH I'm
surprised a scripting language can keep up with a video stream at all.

in 2019 the way we roll (as opposed to what they did in their mockup) is
that the application logic is abstracted away from the hardware
interface logic, which is abstracted away from the datastream logic. The
interface is something. it doesn't matter what it is. it accepts a
stream of bytes.

The application logic generates its data. and the datastream logic has a
compression policy, an ecc policy, an encoding policy that massages the
application output into a stream of bytes the interface logic accepts.
And the reverse on the other side.

Dropping the MSB is called e.g. DumbCompression and that's a template
that plugs-in at compile time, there's no run-time cost associated with
that fashion of polymorphism.
 

Welcome to EDABoard.com

Sponsor

Back
Top