Véletlenül rátaláltam, hogyan lehet blokkdiagramot generálni a projektrajzból, így be is linkelném a legutóbbi blokkrajzomat.
Egyelőre elég csupasz... Még lesz pár dolog, ami nincs berakva. Még egy képet meg szeretnék osztani itt. Az új fejlesztőlapomról lenne szó. Pont ugyanolyan, mint a régi, csak sokkal többet tud. Egy C220-as Merci, buherált 545 lóerős motorral.
A processzorokon futó programok a következők:
#include <xparameters.h>
#include <xuartlite_l.h>
#include <xuartlite.h>
#include <xstatus.h>
#include <stdio.h>
#include <stdlib.h>
#include <mb_interface.h>
#include <xintc_l.h>
#include <xutil.h>
#include <xio.h>
//====================================================
// Definitions
//====================================================
#define BAUDRATE 115200
#define USE_PARITY 0
#define PARITY_ODD 1
#define DATABITS 8
#define MICRON_MEM XPAR_MICRON_RAM_MEM0_BASEADDR
#define WIDTH 178
#define HEIGHT 143
//====================================================
// GLOBAL VARIABLES
//====================================================
unsigned int counter = 0;
unsigned int c2 = 0;
Xuint8 buchstabe;
Xuint8 flag=0;
Xuint8 x=0,y=0;
Xuint32 data,temp;
Xuint32* mem = (Xuint32*) MICRON_MEM;
XUartLite serial,second_serial;
void cam_ack()
{
char x[2];
x[0]=10;
x[1]=13;
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)(x), 2);
}
//====================================================
// INTERRUPT HANDLER FUNCTION
//====================================================
void serial_interrupt_handler(void* addr_p)
{
}
void second_serial_interrupt_handler(void* addr_p)
{
int empty;
empty = XUartLite_IsReceiveEmpty(XPAR_RS232_SECOND_BASEADDR);
if (empty == FALSE )
{
buchstabe = XUartLite_RecvByte(XPAR_RS232_SECOND_BASEADDR);
if(flag == 1)
{
data = buchstabe;
mem[c2]=data;
if(buchstabe == 3)
{
xil_printf("Harmas.%d\n",c2);
}
c2++;
xil_printf("%c",buchstabe);
}
else xil_printf("%c",buchstabe);
}
}
//====================================================
// DELAY FUNCTION
//====================================================
void udelay(unsigned int delay)
{
unsigned int j, i;
for(i=0; i<delay; i++)
for(j=0; j<26; j++);
}
void init_serial()
{
XUartLite_Config UART_Configuration;
UART_Configuration.DeviceId = XPAR_RS232_PORT_DEVICE_ID;
UART_Configuration.RegBaseAddr = XPAR_RS232_PORT_BASEADDR;
UART_Configuration.BaudRate = BAUDRATE;
UART_Configuration.UseParity = USE_PARITY;
UART_Configuration.ParityOdd = PARITY_ODD;
UART_Configuration.DataBits = DATABITS;
XUartLite_Config UART_Second_Configuration;
UART_Second_Configuration.DeviceId = XPAR_RS232_SECOND_DEVICE_ID;
UART_Second_Configuration.RegBaseAddr = XPAR_RS232_SECOND_BASEADDR;
UART_Second_Configuration.BaudRate = BAUDRATE;
UART_Second_Configuration.UseParity = USE_PARITY;
UART_Second_Configuration.ParityOdd = PARITY_ODD;
UART_Second_Configuration.DataBits = DATABITS;
XUartLite_CfgInitialize (&serial, &UART_Configuration, XPAR_RS232_PORT_BASEADDR) ;
XUartLite_CfgInitialize (&second_serial, &UART_Second_Configuration, XPAR_RS232_SECOND_BASEADDR) ;
}
int main ()
{
int i,j;
unsigned int oldstate;
int count = 0;
init_serial();
xil_printf("CPU 0 joined.\r\n");
XIntc_RegisterHandler(XPAR_XPS_INTC_0_BASEADDR,
XPAR_XPS_INTC_0_RS232_PORT_INTERRUPT_INTR,
(XInterruptHandler)serial_interrupt_handler,
(void *)XPAR_RS232_PORT_BASEADDR);
XIntc_RegisterHandler(XPAR_XPS_INTC_0_BASEADDR,
XPAR_XPS_INTC_0_RS232_SECOND_INTERRUPT_INTR,
(XInterruptHandler)second_serial_interrupt_handler,
(void *)XPAR_RS232_SECOND_BASEADDR);
XIntc_MasterEnable(XPAR_XPS_INTC_0_BASEADDR);
//ez V =(XPAR_RS232_PORT_INTERRUPT_MASK&&XPAR_RS232_SECOND_INTERRUPT_MASK)
XIntc_EnableIntr(XPAR_XPS_INTC_0_BASEADDR, 0X000003);
//XUartLite serial,second_serial;
XUartLite_Initialize(&serial,XPAR_RS232_PORT_DEVICE_ID);
XUartLite_Initialize(&second_serial,XPAR_RS232_SECOND_DEVICE_ID);
XUartLite_SetRecvHandler(&serial,
(XUartLite_Handler) serial_interrupt_handler,
(void *)XPAR_RS232_PORT_BASEADDR);
XUartLite_SetRecvHandler(&second_serial,
(XUartLite_Handler) second_serial_interrupt_handler,
(void *)XPAR_RS232_SECOND_BASEADDR);
XUartLite_EnableInterrupt(&serial);
XUartLite_EnableInterrupt(&second_serial);
microblaze_enable_interrupts();
//------------------------------------
// CMUcam3 interraction
//------------------------------------
cam_ack();
udelay(1000);
xil_printf("\nReset the Camera\n");
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)("RS"), 8);
cam_ack();
udelay(500000);
cam_ack();
udelay(1000);
xil_printf("\nCR 18 36 -> YCrCb, auto white balance on\n");
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)("CR 18 36"), 8);
cam_ack();
udelay(100000);
xil_printf("HR 0 -> Resolution 88*143\n");
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)("HR 0"), 8);
cam_ack();
udelay(100000);
xil_printf("NF 30 -> Noise Filtering(wtf)\n");
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)("NF 30"), 8);
cam_ack();
udelay(100000);
xil_printf("Get the Luminance layer, from YCrCb\n");
flag=1;
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)("SF 1"), 8);
cam_ack();
while(c2<12736);
flag=0;
for(i=0;i<c2;i++)
{
xil_printf("%d\n",mem[i]);
}
while(1);
return 0;
}
Ebben a kódrészletben kommunikálok az új babámmal, egy CMUCam3-assal. Van rajta egy CMUCam2 emulátor program, ami értelmezi az utasításokat, majd visszaküldi a megfelelő információt. Ebben a programban a következő lépéseken megyünk hosszan :
1. "\r" szólunk a kamerának, hogy figyeljen ide, illetve töröljük az eddigi hibás parancsokat (mert lehet, hogy van már ott valami, ami nem kellene ott legyen...)
2. "RS\n\r" Reset the Camera. Újraindítjuk a kamerát, aminek hatására a regisztereibe visszakerülnek az alapértelmezett beállítások.
3. "CR 18 36\n\r" YCrCb színkódolás beállítása, illetve automatikus fekéregyensúly beállítása (erre majd később lehet visszatérek)
4. "HR 0\n\r" Képfelbontás beállítása : 174*144 kb... Ez nagyjából akkora, mint egy bélyeg.
Annak ellenére, hogy ilyen kicsi a kép, sok sok információt hordozhat magában. Ebből már lehet színkövetést, vonalkövetést, meg sok más érdekes dolgot készíteni. Ebből én csak egy színtartományt használok fel. Nagyjából ugyanaz van rajta, mint a képen, csak fekete-fehérben.
5. "NF 30\n\r" Noise Filtering vagyis zajszűrés. A paraméterként megadott szám franc tudja mit jelent, sajnos nekem is csak feltételezéseim vannak ezzel kapcsolatban. Az angol leírás számomra nem egyértelmű. "This command controls the Noise Filter setting. It accepts a value that determines how many consecutive active pixels before the current pixel are required before the pixel should be detected (default 2). The range is between 0 and 255."
6. "SF 1\n\r" Send Frame. Ezzel a paranccsal indítjuk el a pixelek egymásutáni küldését. A paraméterként küldött számmal ki tudjuk választani, hogy melyik színcsatornát szeretnénk látni. Ebben az esetben ez az Y színcsatorna, vagyis a Luminance, magyarul asszem színerősség.
Most látom fontosnak megemlíteni, mit is csinál a megszakítás kezelő függvény. Tesztelési fázisban két megszakítás kezelő függvény volt, az egyik az egyik soros port RX vonalára, a másik a másik soros port RX vonalára. Azért interrupt, hogy a program futását ne kelljen felfüggeszteni, amíg az adatokra várakozunk.
Az első öt lépés esetében sokmindent nem csinál a megszakítás kezelő. Egyedüli feladata kiírni a standard soros kimenetre a másik soros porton érkezett adatokat. Az első öt lépés eszetében minden egyes parancsra egy ACK érkezik a kamerától, ezeket láthatjuk a következő képen :
Az a sok karakter a végén maga a kép, csak ASCII karakterekben kódolva. Ezeket a pixel értékeket kell elmenteni a micronRam-ba, későbbi feldolgozás végett. Azért nem a StrataFlash memóriát használjuk, mert annak írása és olvasása meghaladja az én agyi képességeimet. A MicronRam írása és olvasása egyszerű tömbműveletként képzelhető el. Fogunk egy mutatót (pointert), amivel rámutatunk a memória kezdőcímére, majd azzal végigmászunk a memórián.
#define MICRON_MEM XPAR_MICRON_RAM_MEM0_BASEADDR
(...)
Xuint32* mem = (Xuint32*) MICRON_MEM;
(...)
void second_serial_interrupt_handler(void* addr_p)
{
int empty;
empty = XUartLite_IsReceiveEmpty(XPAR_RS232_SECOND_BASEADDR);
if (empty == FALSE )
{
buchstabe = XUartLite_RecvByte(XPAR_RS232_SECOND_BASEADDR);
if(flag == 1)
{
data = buchstabe;
mem[c2]=data;
if(buchstabe == 3)
{
xil_printf("Harmas.%d\n",c2);
}
c2++;
}
else xil_printf("%c",buchstabe);
}
}
(...)
void main()
{
(...)
xil_printf("Get the Luminance layer, from YCrCb\n");
flag=1;
while(XUartLite_IsSending(&second_serial));
XUartLite_Send(&second_serial, (Xuint8*)("SF 1"), 8);
cam_ack();
(...)
return 0;
}
Gondolom ehhez már sok kommentet nem kell fűzni. Mielőtt lekérem a pixelértékeket, beállítom a flaget, ami azt mutatja, hogy képinformáció fog jönni a soros porton, s hogy azt másképp kell kezelni. Ennél elegánsabb megoldás az lehetett volna, ha a megszakítás kezelő függvényt cserélem ki egy másikra. Lehet meg is csinálom...
Két próbakép, amit a CmuCam3-assal készítettem, legkisebb felbontásban.
Röviden ennyi lenne mára. Most fogok neki, átírom a megszakítás kezelő függvényt, hogy ott helyben számoljon integrálképet is. Ha van valami új, akkor még jelentkezem...