SmartWheels self-driving race car. Designed for NXP Cup. Uses FRDM-KL25Z, area-scan camera, and simple image processing to detect and navigate any NXP spec track.

Dependencies:   TSI USBDevice mbed-dev

Fork of SmartWheels by haofan Zheng

RemovedSources/Camera.cpp.txt

Committer:
hazheng
Date:
2017-03-14
Revision:
36:7e747e19f660
Parent:
Hardwares/Camera.cpp@ 29:f87d8790f57d

File content as of revision 36:7e747e19f660:

#include "Camera.h"

#include "Core.h"
#include "OV7725RegAddr.h"
#include "PinAssignment.h"
#include "SWUSBServer.h"

namespace
{
    DigitalOut testLED(LED_GREEN, 1);
    DigitalOut testLED2(LED_RED, 1);
    
    BusIn dataBus(PIN_CC_D_0, PIN_CC_D_1, PIN_CC_D_2, PIN_CC_D_3, PIN_CC_D_4, PIN_CC_D_5, PIN_CC_D_6, PIN_CC_D_7);
    
    bool isInLine = false;
    uint8_t currentCol = 0;
    uint8_t outCurrentCol = 0;
    
    uint16_t currentRow = 0;
    uint16_t outCurrentRow = 0;
    
    uint16_t outENum = 0;
    
    uint8_t pictureData[PICTURE_ARRAY_SIZE];
    
    bool hasPic = false;
}


static void OnPixelClock()
{
    if(hasPic)
        return;
    
    unsigned int pos = (currentRow * (CAMERA_PIXEL_WIDTH/8)) + currentCol;
    if(isInLine && (pos < PICTURE_ARRAY_SIZE))
    {
        pictureData[pos] = dataBus.read();
        ++currentCol;
    }
    /*
    else if(pos > PICTURE_ARRAY_SIZE)
    {
        outENum = pos;
        testLED2 = 0;
    }
    */
}

static void OnHorizontalRise()
{
    if(hasPic)
        return;
    
    isInLine = true;
    
    //++currentRow;
}

static void OnHorizontalFall()
{
    if(hasPic)
        return;
    
    isInLine = false;
    
    if(currentCol > 0)
    {
        ++currentRow;
    }
    outCurrentCol = currentCol;
    currentCol = 0;
}

static void OnFrameRise()
{
    if(currentRow >= CAMERA_PIXEL_HEIGHT)
        hasPic = true;
}

static void OnFrameFall()
{
    if(hasPic)
        return;
    
    outCurrentRow = currentRow;
    currentRow = 0;
    testLED = testLED.read() == 1 ? 0 : 1;
}

Camera::Camera(SW::Core & core) : 
    m_core(core),
    m_pClock(InterruptIn(PIN_CC_PCLOCK)),
    m_href(InterruptIn(PIN_CC_HREF)),
    m_vsnyc(InterruptIn(PIN_CC_VSYNC)),
    m_regBuf(NULL),
    m_debugOutputTimer(0.0f)
{
    m_regBuf = new OV7725RegBuf(m_core);

/*
    m_regBuf->WriteDefaultRegisters();
    
#if (CAMERA_PIXEL_WIDTH == 80)
    m_regBuf->SCCBWrite(OV7725_HOutSize, 0x14);
#elif (CAMERA_PIXEL_WIDTH == 160)
    m_regBuf->SCCBWrite(OV7725_HOutSize, 0x28);
#elif (CAMERA_PIXEL_WIDTH == 240)
    m_regBuf->SCCBWrite(OV7725_HOutSize, 0x3c);
#elif (CAMERA_PIXEL_WIDTH == 320)
    m_regBuf->SCCBWrite(OV7725_HOutSize, 0x50);
#endif

#if (CAMERA_PIXEL_HEIGHT == 60 )
    m_regBuf->SCCBWrite(OV7725_VOutSize, 0x1E);
#elif (CAMERA_PIXEL_HEIGHT == 120 )
    m_regBuf->SCCBWrite(OV7725_VOutSize, 0x3c);
#elif (CAMERA_PIXEL_HEIGHT == 180 )
    m_regBuf->SCCBWrite(OV7725_VOutSize, 0x5a);
#elif (CAMERA_PIXEL_HEIGHT == 240 )
    m_regBuf->SCCBWrite(OV7725_VOutSize, 0x78);
#endif
    
    m_regBuf->SCCBWrite(OV7725_COM4,  0x01);
    m_regBuf->SCCBWrite(OV7725_CLKRC, 0x89);
*/    
    char buf[20];
    unsigned char tempV = m_regBuf->SCCBRead(OV7725_HOutSize);
    sprintf(buf, "CamReg %#x=%#x", OV7725_HOutSize, tempV);
    m_core.GetUSBServer().PushReliableMsg('D', buf);
    
    tempV = m_regBuf->SCCBRead(OV7725_VOutSize);
    sprintf(buf, "CamReg %#x=%#x", OV7725_VOutSize, tempV);
    m_core.GetUSBServer().PushReliableMsg('D', buf);
    
    tempV = m_regBuf->SCCBRead(OV7725_COM4);
    sprintf(buf, "CamReg %#x=%#x", OV7725_COM4, tempV);
    m_core.GetUSBServer().PushReliableMsg('D', buf);
    
    tempV = m_regBuf->SCCBRead(OV7725_CLKRC);
    sprintf(buf, "CamReg %#x=%#x", OV7725_CLKRC, tempV);
    m_core.GetUSBServer().PushReliableMsg('D', buf);
    
    delete m_regBuf;
    m_regBuf = NULL;
    
    memset(pictureData, 0, PICTURE_ARRAY_SIZE);
    
    StartReceivingPic();
}

Camera::~Camera()
{
    
}

void Camera::Update(float deltaTime)
{
    m_debugOutputTimer += deltaTime;
    
    //if(hasPic)
    //{
    //    StopReceivingPic();
    //}
    
    if(m_debugOutputTimer >= 10.0)
    {
        char buf[20];
        sprintf(buf, "ColSize: %u", outCurrentCol);
        m_core.GetUSBServer().PushUnreliableMsg('D', buf);
        sprintf(buf, "RowSize: %u", outCurrentRow);
        m_core.GetUSBServer().PushUnreliableMsg('D', buf);
        //sprintf(buf, "ENum: %u", outENum);
        //m_core.GetUSBServer().PushUnreliableMsg('D', buf);
        
        m_debugOutputTimer = 0.0f;
        
        //if(hasPic)
        //{
            StopReceivingPic();
            testLED2 = testLED2.read() == 1 ? 0 : 1;
            
            for(uint8_t i = 0; i < CAMERA_PIXEL_HEIGHT; ++i)
            {
                std::string outBuf;
                outBuf.push_back(i);
                outBuf.insert(outBuf.end(), &pictureData[i * (CAMERA_PIXEL_WIDTH / 8)], &pictureData[(i + 1) * (CAMERA_PIXEL_WIDTH / 8)]);
                m_core.GetUSBServer().PushReliableMsg('P', outBuf);
                wait(0.02);
            }
            
            StartReceivingPic();
        //}
    }
    
}

void Camera::StartReceivingPic()
{
    hasPic = false;
    
    m_pClock.rise(&OnPixelClock);
    m_href.rise(&OnHorizontalRise);
    m_href.fall(&OnHorizontalFall);
    m_vsnyc.fall(&OnFrameFall);
    //m_vsnyc.rise(&OnFrameRise);
}

void Camera::StopReceivingPic()
{
    //m_vsnyc.rise(NULL);
    m_vsnyc.fall(NULL);
    m_href.fall(NULL);
    m_href.rise(NULL);
    m_pClock.rise(NULL);
}

bool Camera::HasPicture() const
{
    return hasPic;
}

const unsigned char * Camera::GetPicture() const
{
    return NULL; //m_pics[m_currentIndex == 0 ? 1 : 0];
}