DualCore -> már a multé...

     Pár napja sikerült összerakni egy hárommagos projektet. Abba vagyok most belebolondulva. Úgy érzem, ez lesz a végleges modell, ami meg is marad a projektben. Az első proci feladata a kommunikáció, a második proci lesz a matekes, a harmadik meg majd vezérli a szervókat...

     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...

0 megjegyzés:

Megjegyzés küldése

Return top