RGB video ADC Conversion Color Palletes - video-processing

I'm trying to better understand analog to digital video conversion and was hoping for some direction. Way I understand it, a dedicated 10-bit ADC chip will read the voltage of R, G, and B input pins, translate this to 10-bit RGB and output in parallel these value across 30-pins. (Ignoring sync/clock pins etc). My question however is this: If you know the source only has 5-bits per color, (2^5)^3 = 32,768 colors, dumps this to analog RGB, and you are using a 10-bit ADC, will the ADC interpolate colors due to voltage variances and the increase from 5 to 10 bits, thus introducing unoriginal/unintended colors, or is the sampling of analog to digital truly so precise the original source color pallet will be preserved correctly?

Most ADCs have a 1-LSB precision, so the lowest bit will toggle randomly anyway. If you need it to be stable, either use oversampling with increased frequency, or use a 12 bit ADC, this one will have an LSB toggling as well, but bit 2 will be probably stable.
Why probably you ask? Well, if you transmission line is noisy or badly coupled, it can introduce additional toggling in LSB range, or even higher. In some bad cases noise can even corrupt your higher 5 bits of data.
There might be some analog filters / ferrite beads / something else to smoothen your signal as well, so you won't even see actual "steps" on analog.
So, you never know until you test it. Try looking at your signal with a scope, that might solve some of your doubts.

Related

Can I use a Adafruit Neopixel RGB STRIP with a Particle Photon?

I am not sure if the RGB strip below will work with the Particle Photon. At the RGB strip product description they mention the MCU (microcontroller) should have at least a processor faster than 8 MHz as well as a highly repeatable 100nS timing precision. I searched and found that we would be okay on the processing (STM32F205 120Mhz ARM Cortex M3) but I am completely unsure about the timing precision.
What is time precision?
Is the time precision of the Particle Photon enough?
Here is the link to the specific RGB strip for more details (ADAFRUIT NEOPIXEL DIGITAL RGB LED STRIP - WHITE 60 LED)
Thank you so much
Yes you should be fine. I have used my Particle Photon with an 8 LED strip and not had any issues. There is a NeoPixel Library available for the photon as well.

Is it possible to read and/or write ports via a C variable instead of using GPIO_Pin_N values?

All the sample code I can find accesses ports like so:
GPIO_SetBits(GPIOE, GPIO_Pin_9 | GPIO_Pin_13);
Which looked OK at first, until I tried to reference LEDs (my port E) by index (0-7). A switch or a LUT is a solution, but I don't like either. Is it possible to declare e. g. uint8_t and map it to the specific range of pins of a certain port?
The standard Cortex-M3/M4 memory map allows for the CPU to have so-called "bit-band" aliases of regions, in which writing to each word in the bit-band alias performs an automatic read-modify-write to alter the target bit in the corresponding region.
Taking the STM32F411 (Cortex-M4F) manual I have to hand as an example, that shows the peripheral region 0x40000000-0x400FFFFF is covered by a bit-band alias in the region 0x42000000-0x43FFFFFF. Thus for instance on that device (if I've got my maths right) each word from 0x42420280-0x42420300 corresponds to a bit in the GPIO port E data register GPIOE_ODR at 0x40021014, so this:
volatile int *leds = (void *)0x42420280;
leds[x] = 1; /* only bit 0 of the bit-band word actually holds data */
makes the hardware perform the tidily-abstracted equivalent of this:
volatile int *leds = (void *)0x40021014;
int val = *leds;
val |= (1 << x);
*leds = val;
If you have a suitable device, don't want to update multiple bits at once, and don't mind the extra overhead vs. a single access to the regular register in some cases (e.g. writing the set/clear registers instead of the data), it's a pretty neat trick.
The values of the GPIO_Pin_X constants are defined as bit positions within a 16-bit value, with pin 0 as the least significant bit and pin 15 as the most significant:
#define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */
#define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */
#define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */
[...]
#define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */
(This is why you can OR them together to write to multiple pins!)
If you need to index pins dynamically, you can do so using a macro like:
#define GPIO_Pin(x) ((uint16_t) 1 << (x))
busses are fixed width you cannot change that hardware with software, and no you cannot break up a fixed sized register in a peripheral into smaller parts with software. You can possibly make it appear in software to do such a thing but in the end the real code generated by the high level code will still do read-modify-writes or whatever is needed or supported based on bus or peripheral register sized transactions.
Trying to make things smaller even making variables byte sized vs the native size of registers ultimately creates more or inefficient code. So trying to understand why you would want to do such a thing anyway.
An stm32 I recently played with has a bit clear/set register where writing a one clears or sets the output state of a pin. In the logic it simply clears or sets the flip flop controlling that port output, which in logic they can/do implement the backend of a control into smaller parts, but from software you cannot directly access those in non-aligned, not properly sized transfers. Some companies require you, in software, to do a read-modify-write. So using an stm32 with these kinds of features (other brands may also have similar features, sometimes using the address, sometimes like this but in separate registers one for setting one for clearing) actually makes your code about as simple as it can be.
You are more than welcome to create as many defines as you want for combinations of gpio pins so that in your main code you only need one mnemonic instead of multiples orred together if that is your desire.
You do not have to have a function for setting the bits if you can get the compiler to reliably generate a str of the right size, and the right combination if bits in a single define you can simply the code into an a = b; situation.
My guess from your vague question, is a LUT is the optimal solution.

Using SSE on floating point pixels with only 3 color components

I am creating a struct to store a single RGB pixel in an image.
struct Pixel
{
// color values range from 0.0 to 1.0
float r, g, b;
}__attribute__((aligned(16));
I want to use 128 bit SSE instructions to do things like adding, multiplying, etc. This way I can perform operations on all 3 color channels at once. So the first packed float in my SSE register would be red, then green, then blue, but I am not so sure what would go into my fourth register. I really don't care what bits are in the extra 32 bits of padding. When I load a pixel into the SSE register I would imagine it contains either zeros or junk values. Is this problematic? Should I add a fourth alpha channel even though I don't really need one? The only way I see this being an issue is if I were dividing by a pixel and there was a zero value in the fourth spot, or of I was taking a root of a negative, etc.
Integer ops will have no problem at all with uninitialized values, since the latency is never data-dependent. Floating point is different. Some FPUs slow down on denormals, NaNs, and infinities (in any one of the vector elements).
Intel Nehalem and earlier slow down a lot when doing math ops with denormal inputs/outputs, and on FP underflow/overflow. Sandybridge has a nice FPU with fast add/sub for any inputs (according to Agner Fog's instruction tables), but multiply can still slow down.
Add/sub/multiply are fine with zeros, but potentially a problem with uninitialized junk that might represent NaN or something.
Be careful with division that you aren't dividing by zero. That could even raise an FPU exception, depending on HW settings.
So yes, keeping the unused element zeroed is probably a good idea. Depending how you generate things in the first place, this may be pretty cheap to accomplish. (e.g. movd/pinsrd/pinsrd (or insertps) to put three 32bit elements into a vector, with the initial movd zeroing the high 96b.)
One workaround could be to store a 2nd copy of the blue channel in the 4th element. (or whatever is most convenient to shuffle there.) You could load vectors with movsldup(SSE3) / movlps. After movsldup, your register would hold { b b r r }. movlps would re-load the lower 64bits, so you'd have { b b g r }. (This is equivalent to movsd, BTW.) Or if the shuffle port is less busy than the load ports, do one 16B load and then shufps. (movsldup on Intel CPUs is a single uop that runs on a load port, even though it has the duplication built in.)
Another option would be to pack your pixels into 12 bytes, so a 16B load would get one component of the next pixel. Depending on what you're doing, overlapping stores that clobber one element of the next pixel might or might not be ok. Loading the next pixel before storing the current could work around that for some ops. It's quite easy to be cache or bandwidth-limited, so saving 1/4 space at the small cost of the occasional cache-line split load/store could be worth it.

Combine two bytes from gyroscope into signed angular rate

I've got two 8-bit chars. They're the product of some 16-bit signed float being broken up into MSB and LSB inside a gyroscope.
The standard method I know of combining two bytes is this:
(signed float) = (((MSB value) << 8) | (LSB value));
Just returns garbage.
How can I do this?
Okay, so, dear me from ~4 years ago:
First of all, the gyroscope you're working with is a MAX21000. The datasheet, as far as future you can see, doesn't actually describe the endianness of the I2C connection, which probably also tripped you up. However, the SPI connection does state that the data is transmitted MSB-first, with the top 8-bits of the axis data in the first byte, and the additional 8 in the next.
To your credit, the datasheet doesn't really go into what type those 16 bits represent - however, that's because it's standardized across manufacturers.
The real reason why you got such meaningless values when converting to float is that the gyro isn't sending a float. Why'd you even think it would?
The gyro sends a plain 'ol int16 (short). A simple search for "i2c gyro interface" would have made that clear. How do you get that into a decimal angular rate? You divide by 32,768 (int16's max positive value), then multiply by the full-scale range set on the gyro.
Simple! Here, want a code example?
float X_angular_rate = ((((int16_t)((byte_1 << 8) | byte_2))/SHRT_MAX)*GYRO_SCALE
However, I think that it's important to note that the data from these gyroscopes alone is not, in itself, as useful as you thought; to my current knowledge, due to their poor zero-rate drift characteristics, MEMS gyros are almost always used in a sensor fusion setup with an accelerometer and a Kalman filter to make a proper IMU.
Any position and attitude derived from dead-reckoning without this added complexity is going to be hopelessly inaccurate after mere minutes, which is why you added an accelerometer to the next revision of the board.
You have shown two bytes, and float is 4 bytes on most systems. What did you do with the other two bytes of the original float you deconstructed? You should preserve and re-construct all four original bytes if possible. If you can't, and you have to omit any bytes, set them to zero, and make them the least significant bits in the fractional part of the float and hopefully you'll get an answer with satisfactory precision.
The diagram below shows the bit positions, so acting in accordance with the endianness of your system, you should be able to construct a valid float based on how you deconstructed the original. It can really help to write a function to display values as binary numbers and line them up and display initial, intermediate and end results to ensure that you're really accomplishing what you think (hope) you are.
To get a valid result you have to put something sensible into those bits.

array storage and multiplication in verilog

I have a peripheral connected to my altera fpga and am able read data from it using SPI. I would like to store this incoming data into an array, preferably as a floating point value. Further, I have a csv file on my computer and want to store that data in another array, and then after triggering a 'start' signal multiply both arrays and send the output via rs-232 to my pc. Any suggestions on how to go about this? Code for reading data from peripheral is as follows:
// we sample on negative edge of clock
always #(negedge SCL)
begin
// data comes as MSB first.
MOSI_reg[31:0] <= {MOSI_reg[30:0], MOSI}; // left shift for MOSI data
MISO_reg[31:0] <= {MISO_reg[30:0], MISO}; // left shift for MISO data
end
thank you.
A 1024x28 matrix of 32 bits each element requires 917504 bits of RAM in your FPGA, plus another 28*32 = 896 bits for the SPI data. Multiplying these two matrices will result in a vector of 1024x1 elements, thus add 32768 bits for the result. This sums 951168 bits you will need in your device. Does your FPGA chip have this memory?
Asumming you have, yes: you can instantiate a ROM inside your design and initialize with $readmemh or $readmemb (for values in binary or hexadecimal form respectively).
If precission is not an issue, go for fixed point, as implementing multiplication and addition in floating point is kind of hard job.
You need then a FSM to fill your source vector with SPI data, do the multiplication and store the result in your destination vector. You may consider instantiating a small processor to do the job more easily
Multiplication is non-trivial in hardware, and 'assign c = a*b' is not necessarily going to produce what you want.
If your FPGA has DSP blocks, you can use one of Altera's customizable IP cores to do your multiplication in a DSP block. If not, you can still use an IP core to tune the multiplier the way you want (with regards to signed/unsigned, latency, etc.) and likely produce a better result.

Resources