Summary: Exercise in using internal and external memory in the TI67x Image Developers Kit.
V:\ece320\projects\colorcool
#pragma DATA_SECTION command. There are two parameters :
// specifies name of mem space – ext_mem // and type as internal memory – ".image:ext_sect" // the data_align specification is the byte alignment – ours is // 8 bits #pragma DATA_SECTION(ext_mem,".image:ext_sect"); #pragma DATA_ALIGN(ext_mem,8); // specifies name of mem space – int_mem // and type as internal memory – ".image:int_sect" // the data_align specification is the byte alignment – ours is // 8 bits #pragma DATA_SECTION(int_mem,".chip_image:int_sect"); #pragma DATA_ALIGN(int_mem, 16);
// specify size as width 640 // height 480 // and 8 bytes per pixel // which could represent an RGB screen of 640 X 480 with // 2 bytes per pixel. Unsigned char = 8 bytes unsigned char ext_mem[640 * 480 * 2]; // here we create 6 lines of RGB data of 640 columns each, // 2 bytes per pixel unsigned char int_mem[6 * 2 * 640];
int_mem + (8 * cols); //cols = 640
VDIS_open(); VCAP_open();
color(VCAP_NTSC, VDIS_640X480X16, numFrames);This specifies:
VDIS_config(displayMode); VCAP_config(captureMode);
for (frameCnt=0; frameCnt<numFrames; frameCnt++)
This loop iterates for a set number of frames and processes them one at a time. And the lines following this :
input = VCAP_getFrame(SYS_FOREVER); output = (Uint16*)VDIS_toggleBuffs(0);are used to obtain the capture and output frames. After this statement, ‘input’ will hold a pointer to external memory where the captured frame is stored. The ‘input’ pointer holds pointers ‘y1’, ‘c1’ etc to the different color component of the image. These color components are in external memory as well. And ‘output’ will hold a pointer to a buffer in external memory, to which we will write whatever we need to output to the screen. Basically the buffer is the size of the output frame (640 X 480 X 2 bytes/pixel), and we can write what we wish to it. And, the next time togglebufs(0) is called, everything we placed in that buffer will be put on the screen. And a new buffer will be allocated, the pointer ‘output’ will be updated and we can now write to the next frame. The next line
out_image.img_data = (unsigned char *) output;updates the pointers we had setup. We then move on to the color_convert(..) routine. We pass the memory pointers we had created so that our color_conv program can process the input frame we obtained. In color_conv, we begin by setting up streams to bring in data and streams to send out data. After that we begin the color-space conversion.
dstr_t o_dstr;Then use the
dstr_open (…);The dstr_open () specification is given in the manual. Some clarifications are made here. As an example we will consider the output stream o_dstr in color_convert(). This stream is an output stream. This stream is used to transfer data from internal memory to the screen output data buffer. (we captured the buffer's memory location in the previous section using togglebufs(), it's memory address is stored in the pointer out_image->img_data)
dstr_t *dstrneeds a pointer to the data stream object we wish to use. In our case this would be o_dstr.
void *x_datatakes a pointer to the location in external memory which we are using. In our program this is specified in out_image->img_data. And since we are using an output stream, this argument specifies the Destination of the stream. (This argument is the Source for an input stream)
int x_sizetakes in the size of the external data buffer to which we are writing to. This specifies the actual number of bytes of external memory we will be traversing. So this is NOT necessarily the full size of the output buffer (i.e. NOT always 640 X 480 X 2) For our example we are writing to the full screen hence we use
(2 * out_rows * out_cols)which results in 640 X 480 X 2 bytes of data. An example of the exception is when we write to only, say, the first 10 rows of the screen. In this case we would only traverse: 10 X 640 X 2 bytes. One more thing to note is that if you need to only write to the first 40 columns of the first 10 rows, you would still need to traverse the same amount of space and you would use 10 X 640 X 2 bytes again for this argument. In this case however, you will be skipping some of the data, as shown later.
void *i_datatakes a pointer to the location in internal memory we are using. In our program this is specified as out_data. And since we are using an output stream, this argument specifies the Source of our stream. (This argument is the Destination for an input stream).
unsigned short i_sizeis used to specify the total size of the internal memory we will be using. In our case we will be writing one line of the output screen - (4 * out_cols) This is the amount we allocated earlier. This evaluates to 640 * 2 * 2 bytes. The extra ‘2’ is needed for double-buffering, which is a system used by the IDK for transferring data into internal memory. Basically, the IDM (image data manger) needs twice the amount of internal memory as data transferred. i.e. one line is worth only 640 * 2 bytes, but because of double buffering we allocate twice that for the IDM’s use. Remember this when allocating memory space for internal memory.
unsigned short quantumspecifies the amount of data transferred in a single dstr_get or dstr_put statement. In our case it would be (2 * out_cols). This evaluates to 640 * 2 bytes – one line of the output screen each time we use dstr_put Now, if we were transferring only part of a line, let’s take the first 40 columns of the first 10 rows example. With each dstr_put, we will output only the first forty columns of each row. Thus we are transferring 40 * 2 bytes in each call. But this can be extended further. By use of the ‘dstr_get_2D’ we can transfer multiple lines of data. So we can, say, transfer two full rows of the output screen (4 * cols) or in our mini-example this would mean 2 * 40 * 2 bytes. Transferring of multiple lines is very useful, especially when using filters which work on 2-D ‘regions’ of data.
unsigned short multiplespecifies the number of lines we are transferring with each call. Now this is not the conceptual number of lines. It is the physical multiple of argument 6 that we are transferring. It is best to leave this at one and modify argument 6 above.
unsigned short strideneeds the amount by which to move the external memory pointer. This gives us control over how the lines are extracted. In our case, it being the simplest, we move one line at a time : 2*out_cols The stride pointer is especially useful when creating input streams. For example you can pull in overlapping lines of input. So you can pull in lines 1 and 2 in the first dstr_get(). The next dstr_get() can pull in lines 2 and 3 or you can setup it up to pull lines 3 and 4 or 4 and 5 or ….. depending on the stride. In particular, this is useful in Sobel (edge-detect) filtering, where you need data above and below a pixel to evaluate the output.
unsigned short w_sizeis the window size. For transferring a single line at a time we would use '1' here, and the system will recognize this is as one line double-buffered. But if we needed to transfer two lines we would merely submit '2' as the argument.
dstr_t dirspecifies the type of stream. Use DSTR_OUTPUT for output stream and DSTR_INPUT for input stream.
#include "sobel_h.h"directive in the wrapper function at the top. Don't forget to create a header function for your wrapper as well and add it to your project.
V:\ece320\projects\colorcoolThe system will copy the red-component of a 100 by 100 area of the screen (let’s call this area M). It will place this in a different area of the screen. Also you will need to place a Sobel filtered version of this red-area to the screen as well. The locations where the copied and filtered images are placed must be quickly modifiable on request (use variable position as parameters to wrapper functions rather than fixed coordinates)