Arduino Binary Array is too Large - arrays

I have a three-dimensional array of binary numbers, which I use as a dictionary and pass through an LED array. The dictionary covers 27 letters, and each letter covers 30x30 pixels (where each pixel is a 0 or a 1).
I was using the Intel Edison - and the code worked well - but I ditched the Edison after having trouble connecting it to my PC (despite replacing it once). I switched to the Arduino Uno, but am now receiving an error that the array is too large.
Right now I have the array set as boolean. Is there anyway to reduce the memory demands of the array by setting it instead as bits? The array consists of just zeros and ones.
Here's a snip of the code:
boolean PHDict[27][30][30] = {
/* A */ {{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* this is one column of thirty, that show "A" as a letter */

You could write it as
#include <stdint.h>
//...
uint32_t PHdict[27][30] = {
{ 0x00004000, ... },
....
};
.. Where each entry contains 30 bits packed into a 32-bit number.
The size is under 4k bytes.
You would need a bit of code to unpack the bits when reading the array, and a way to generate the packed values (I.e a program which runs on your "host" computer, and generates the initialized array for the source code)
For the AVR processor, there's also a way to tell the compiler you want the array stored in PM (Flash memory) instead of DM - I think if you have it in DM, the compiler will need to put the initialization data in PM anyway, and copy it over before the program starts, so it's a good idea to explicitly store it in PM. See https://gcc.gnu.org/onlinedocs/gcc/AVR-Variable-Attributes.html#AVR-Variable-Attributes
In fact, depending on the amount of flash memory in the processor, changing it to PM may be sufficient to solve the problem, without needing to pack the bits.

Related

Formatting Dynamic Array of Bits as String in SystemVerilog

How can I format a dynamic array of bits (or more correctly, logics) as a string, e.g., for UVM's convert2string? For example, I would like to convert
logic vdyn[];
...
vdyn = new [16] ('{0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1});
to the string 0097.
I thought the following would work (the # are just to delimit the string for readability):
fmt = $sformatf("#%%%0dh#", (vdyn.size-1)/4 + 1); // "#%4h#"
vstr = $sformatf(fmt, { >> {vdyn}});
but it returns # x#, at least in Questa 10.3d (I suspect this is a bug - I'd be interested if it works on other simulators).
I tried converting it to a packed array first, but that runs into other problems. Without a size constraint on the result, the source value always gets left-justified in the destination variable, e.g.:
logic [63:0] v64;
...
v64 = {>> {vdyn}}; // 64'h0097000000000000
There's no way to print out just the part I want without using variable-size slices. The following works, but it requires that I know the size of the array at compile time:
v64 = 16'({>> {vdyn}}); // 64'h0000000000000097
The best thing I've found is the following "double-reverse" (note that I'm using << here, not >>):
v64 = {<< {vdyn}}; // 64'he900000000000000
v64 = {<< {v64}}; // 64'h0000000000000097
vstr = $sformatf(fmt, v64); // #0097#
It seems kind of hokey to have to do this, though. By the way, combining the first two statements into one doesn't work:
v64 = {<< {{<< {vdyn}}}}; // 64'hZ900000000000000
(v64[63] is z for some reason). Again, I suspect this is a bug in Questa 10.3d.
Try casting a slice of the array and loop through. For example an 4 entry slice that is cast to a 4-bits value. A slize can be done with the -: or +: operator (See IEEE Std 1800-2012 § 7.4.3 Operations on arrays and § 7.4.6 Indexing and slicing of arrays)
vstr = "";
for(int i=vdyn.size()-1; i>=0; i-=4) begin
vstr = $sformatf("%h%s", 4'({>>{vdyn[i -: 4]}}), vstr);
end
vstr = $sformatf("#%s#", vstr); // user formatting
The 4s in the code can be changed to something else depending how much leading 0 or a non-power-of-two formatting is desired, but it must be a numeric constant
I tried your code on some other simulators. vstr = $sformatf(fmt, { >> {vdyn}}); sometimes gave me compiling errors. Casting the array to something bigger than its expected max size seems to work
fmt = $sformatf("#%%%0dh#", (vdyn.size-1)/4 + 1); // "#%4h#"
vstr = $sformatf(fmt, 128'({ >> {vdyn}})); // works iff 128>=vdyn.size
I think the problem may be that the width of the streaming operator using dynamic types is not defined in a self-determined context (e.g. an argument to a system task). I think the LRM should have treated this an error.
A work-around is to shift the left-justified result to the right by
v64 = {>> {vdyn}};
v64 >>= 64-vdyn.size;

(OpenCL+ OpenCV) How to use the offset of clEnqueueWriteBuffer?

The input image is imageA. I want to copy the middle 1/3 data(imageB) into the opencl buffer.
I use the clEnqueueWriteBuffer function.(I use buffer but NOT the Image)
clEnqueueWriteBuffer(queue,
cl_buffer_input, // opencl buffer
1,
0, // NOW offset is 0
WIDTH_IMAGE*(HEIGHT_IMAGE/3))*COLOR_IMAGE_CHANNEL*sizeof(cl_uchar),//1/3 image height
(void*)(image_input.data), // input data
0, 0, NULL);
After that ,the buffer I copied is image C's data.
So I want to use the offset to copy image B.
The code I used is
clEnqueueWriteBuffer(queue,
cl_buffer_input, // opencl buffer
1,
(HEIGHT_IMAGE/3))*COLOR_IMAGE_CHANNEL*sizeof(cl_uchar), // NOW offset is the offset of data
WIDTH_IMAGE*(HEIGHT_IMAGE/3))*COLOR_IMAGE_CHANNEL*sizeof(cl_uchar),//1/3 image height
(void*)(image_input.data), // input data
0, 0, NULL);
But the result can't be updated! Even I change the offset into 1. The result is also still.(New frame data in the video can't be upload, the result is only the first frame and the position is like image C).
So I changed the start pointer of image data, and let the offset be 0
The new code is like this:
clEnqueueWriteBuffer(queue,
cl_buffer_input, // opencl buffer
1,
0, // NOW offset is the offset of data
WIDTH_IMAGE*(HEIGHT_IMAGE/3))*COLOR_IMAGE_CHANNEL*sizeof(cl_uchar),//1/3 image height
(void*)(image_input.data+(HEIGHT_IMAGE/3))*COLOR_IMAGE_CHANNEL), // input data's pointer changed
0, 0, NULL);
And... THe new result is like imageD!
It only has the offset of X line.
So...what can I do to copy just the middle 1/3 data of the image into a opencl buffer?
Thank you~
You are not getting anything weird, the results for the code you run are ok.
However, if you want to copy the part B, you need this piece of code:
clEnqueueWriteBuffer(queue,
cl_buffer_input, // opencl buffer
CL_TRUE, //Blocking?
0, // No offset inside the buffer (the image will start at 0 inside the cl_buffer)
WIDTH_IMAGE*(HEIGHT_IMAGE/3))*COLOR_IMAGE_CHANNEL*sizeof(cl_uchar),//Copy only 1/3 of image size
(void*)(image_input.data+WIDTH_IMAGE*(HEIGHT_IMAGE/3))*COLOR_IMAGE_CHANNEL), // Offset the input data by 1/3 as well (the first data to copy is at 1/3 inside the array)
0, 0, NULL);
In details: What you need is to copy 1/3 of the image, so the size is 1/3. The buffer offset is 0, because you don't want to write the image at the end of the buffer, but at the beggining. And the ptr where to take the data to copy has to have an offset of 1/3 of the image. So that you copy the portion of the pointer 1/3 to 2/3, into the buffer. (The buffer will have 1/3 of the original image size)

MQL4 Indicator passing signal to EA

the problem is, I want to open order when my indicator gives signal. How can I do that?
I have been trying to do with iCustom() but it is not satisfying.
I tried to use GlobalVariableSet() in indicator and GlobalVariableGet() method in EA but it is not properly worked.
Please help.
The syntax is:
double iCustom(
string symbol, // symbol
int timeframe, // timeframe
string name, // path/name of the custom indicator compiled program
... // custom indicator input parameters (if necessary)
int mode, // line index
int shift // shift
);
Here is the example using custom Alligator indicator (which should be available by default as Alligator.mq4 in MT platform).
double Alligator[3];
Alligator[0] = iCustom(NULL, 0, "Alligator", 13, 8, 8, 5, 5, 3, 0, 0);
Alligator[1] = iCustom(NULL, 0, "Alligator", 13, 8, 8, 5, 5, 3, 1, 0);
Alligator[2] = iCustom(NULL, 0, "Alligator", 13, 8, 8, 5, 5, 3, 2, 0);
where 13, 8, 8, 5, 5, 3 are corresponding input parameters of custom Alligator as defined in indicator it-self:
//---- input parameters
input int InpJawsPeriod=13; // Jaws Period
input int InpJawsShift=8; // Jaws Shift
input int InpTeethPeriod=8; // Teeth Period
input int InpTeethShift=5; // Teeth Shift
input int InpLipsPeriod=5; // Lips Period
input int InpLipsShift=3; // Lips Shift
and mode is the corresponding line index as defined in the indicator by:
SetIndexBuffer(0, ExtBlueBuffer);
SetIndexBuffer(1, ExtRedBuffer);
SetIndexBuffer(2, ExtLimeBuffer);
The syntax is:
int signal = iCustom(NULL, 0, "MyCustomIndicatorName",
...parameters it takes in...,
...the buffer index you want from the custom indicator...,
...shift in bars);
Let's say you wrote a custom moving average indicator called "myMA" and it takes in a period only as one of its extern variables. This indicator calculates a simple moving average based on the period that the user supplies and on the close of each bar. This indicator stores its calculated values in an array MAValues[] that gets assigned to an index like this: SetIndexBuffer(0, MAValues);
To get the moving average of the current bar with period 200 then, you would write:
double ma_current_bar = iCustom(NULL, 0, "myMA", 200, 0, 0);
Then once you have this value you can check it against some trading criteria you determine, and open an order when it is met. For example if you wanted to open a long position if the moving average of the current bar equals the current Ask price, you would write:
if (ma_current_bar == Ask){
OrderSend(Symbol(), OP_BUY, 1, Ask, *max slippage*, *sl*, *tp*, NULL, 0, 0, GREEN);
}
This is just example code, do NOT use this in a live EA.

Opencv 2.4.0: Load image through unsigned char array

I think I've thoroughly searched the forums, unless I left out certain keywords in my search string, so forgive me if I've missed a post. I am currently using OpenCV 2.4.0 and I have what I think is just a simple problem:
I am trying to take in an unsigned character array (8 bit, 3 channel) that I get from another API and put that into an OpenCV matrix to then view it. However, all that displays is an image of the correct size but a completely uniform gray. This is the same color you see when you specify the incorrect Mat name to be displayed.
Have consulted:
Convert a string of bytes to cv::mat (uses a string inside of array) and
opencv create mat from camera data (what I thought was a BINGO!, but can't seem to get to display the image properly).
I took a step back and just tried making a sample array (to eliminate the other part that supplies this array):
int main() {
bool isCamera = true;
unsigned char image_data[] = {255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255,0,0,255};
cv::Mat image_as_mat(Size(6,3),CV_8UC3,image_data);
namedWindow("DisplayVector2",CV_WINDOW_AUTOSIZE);
imshow("DisplayVector2",image_as_mat);
cout << image_as_mat << endl;
getchar();
}
So I am just creating a 6x3 matrix, with the first row being red pixels, the second row being green pixels, and third row being blue. However this still results in the same blank gray image but of correct size.
The output of the matrix is (note the semicolons i.e. it formatted it correctly):
[255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0; 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0; 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255, 0, 0, 255]
I might be crazy or missing something obvious here. Do I need to initialize something in the Mat to allow it to display properly? Much appreciated as always for all your help everyone!
all the voodoo here boils down to calling getchar() instead of (the required) waitKey()
let me explain, waitKey might be a misnomer here, but you actually need it, as the code inside wraps the window's messageloop, which triggers the actual blitting (besides waiting for keypresses).
if you don't call it, your window will never get updated, and will just stay grey ( that's what you observe here )
indeed, you should have trusted the result from cout , your Mat got properly constructed, it just did not show up in the namedWindow
(btw, getchar() waits for a keypress from the console window, not your img-window)
hope it helps, happy hacking further on ;)

Color Depth PIXELFORMATDESCRIPTOR

I'm wondering what values to change in a PIXELFORMATDESCRIPTOR object to change the color depth.
According to the OpenGL wiki, this is how you'd create a PIXELFORMATDESCRIPTOR object for an OpenGL context:
PIXELFORMATDESCRIPTOR pfd =
{
sizeof(PIXELFORMATDESCRIPTOR),
1,
PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, //Flags
PFD_TYPE_RGBA, //The kind of framebuffer. RGBA or palette.
32, //Colordepth of the framebuffer.
0, 0, 0, 0, 0, 0,
0,
0,
0,
0, 0, 0, 0,
24, //Number of bits for the depthbuffer
8, //Number of bits for the stencilbuffer
0, //Number of Aux buffers in the framebuffer.
PFD_MAIN_PLANE,
0,
0, 0, 0
};
But it has different variables effecting the color depth.
Which ones do I need to change to adjust the color depth accordingly?
The first number, 32 in your particular example specifies the amount of color bitplanes available to the framebuffer. The other numbers define the numbers of bitplanes to use for each component. It's perfectly possible to fit a 5-6-5 pixelformat into a 32 bitplanes framebuffer, which is a valid choice.
When you pass a PIXELFORMATDESCRIPTOR to ChoosePixelFormat the values are takes as minimum values. However the algorithm used by ChoosePixelFormat may not deliver an optimal result for your desired application. It can then be better to enumerate all available pixelformats and choose from them using a custom set of rules.

Resources