diff --git a/tracker/software/config.c b/tracker/software/config.c index ea0e9e3..e93e907 100644 --- a/tracker/software/config.c +++ b/tracker/software/config.c @@ -365,8 +365,8 @@ module_conf_t config[7]; uint8_t ssdv_buffer[128*1024] __attribute__((aligned(32))); // Image buffer systime_t track_cycle_time = S2ST(60); // Tracking cycle (all peripheral data [airpressure, GPS, temperature, ...] is collected each 60 seconds -systime_t log_cycle_time = S2ST(600); // Log cycle time in seconds (600 seconds) -bool keep_cam_switched_on = true; // Keep camera switched on and initialized after it has been switched on once, no configuration change is possible +systime_t log_cycle_time = S2ST(60); // Log cycle time in seconds (600 seconds) +bool keep_cam_switched_on = true; // Keep camera switched on and initialized, this makes image capturing faster but takes a lot of power over long time uint16_t gps_on_vbat = 3000; // Battery voltage threshold at which GPS is switched on uint16_t gps_off_vbat = 2500; // Battery voltage threshold at which GPS is switched off diff --git a/tracker/software/debug.c b/tracker/software/debug.c index 8bebba6..95edd1d 100644 --- a/tracker/software/debug.c +++ b/tracker/software/debug.c @@ -4,6 +4,7 @@ #include #include "config.h" #include "image.h" +#include "tracking.h" const SerialConfig uart_config = { @@ -15,7 +16,7 @@ const SerialConfig uart_config = mutex_t trace_mtx; // Used internal to synchronize multiple chprintf in debug.h -bool debug_on_usb = true; +bool debug_on_usb = false; void debugOnUSB_Off(BaseSequentialStream *chp, int argc, char *argv[]) { @@ -36,7 +37,6 @@ void debugOnUSB_On(BaseSequentialStream *chp, int argc, char *argv[]) static uint8_t usb_buffer[96*1024] __attribute__((aligned(32))); // USB image buffer void printPicture(BaseSequentialStream *chp, int argc, char *argv[]) { - (void)chp; (void)argc; (void)argv; @@ -52,7 +52,6 @@ void printPicture(BaseSequentialStream *chp, int argc, char *argv[]) // Transmit image via USB if(camera_found) { - bool start_detected = false; for(uint32_t i=0; i image/jpeg,%d", conf.size_sampled-i+1); // Flag the data on serial output - streamPut(&SDU1, 0xFF); - streamPut(&SDU1, 0xD8); + streamPut(chp, 0xFF); + streamPut(chp, 0xD8); } if(start_detected) - streamPut(&SDU1, conf.ram_buffer[i]); + streamPut(chp, conf.ram_buffer[i]); + } + if(!start_detected) + { + TRACE_USB("DATA > image,jpeg,0"); + TRACE_USB("DATA > error,no SOI flag found"); } } else { // No camera found - for(uint32_t i=0; i image,jpeg,0"); + TRACE_USB("DATA > error,no camera found"); } } +trackPoint_t* getLogBuffer(uint16_t id) +{ + if(sizeof(trackPoint_t)*id < LOG_SECTOR_SIZE-sizeof(trackPoint_t)) + { + return (trackPoint_t*)(LOG_FLASH_ADDR1 + id * sizeof(trackPoint_t)); + } else if((id-(LOG_SECTOR_SIZE/sizeof(trackPoint_t)))*sizeof(trackPoint_t) < LOG_SECTOR_SIZE-sizeof(trackPoint_t)) { + return (trackPoint_t*)(LOG_FLASH_ADDR2 + (id-(LOG_SECTOR_SIZE/sizeof(trackPoint_t))) * sizeof(trackPoint_t)); + } else { // Outside of memory address allocation + return NULL; + } +} + +void readLog(BaseSequentialStream *chp, int argc, char *argv[]) +{ + (void)argc; + (void)argv; + + trackPoint_t *tp; + for(uint16_t i=0; (tp = getLogBuffer(i)) != NULL; i++) + if(tp->id != 0xFFFFFFFF) + { + chprintf( chp, + "%d,%04d-%02d-%02d,%02d:%02d:%02d,%d.%05d,%d.%05d,%d,%d,%d,%d.%03d,%d.%03d,%d.%03d,%d,%d,%d.%01d,%2d.%02d,%2d.%01d\r\n", + tp->id,tp->time.year, tp->time.month, tp->time.day, tp->time.hour, tp->time.minute, tp->time.day, + tp->gps_lat/10000000, (tp->gps_lat > 0 ? 1:-1)*(tp->gps_lat/100)%100000, tp->gps_lon/10000000, (tp->gps_lon > 0 ? 1:-1)*(tp->gps_lon/100)%100000, tp->gps_alt, + tp->gps_sats, tp->gps_ttff, + tp->adc_vbat/1000, (tp->adc_vbat%1000), tp->adc_vsol/1000, (tp->adc_vsol%1000), tp->adc_vusb/1000, (tp->adc_vusb%1000), tp->adc_pbat, tp->adc_rbat, + tp->air_press/10, tp->air_press%10, tp->air_temp/100, tp->air_temp%100, tp->air_hum/10, tp->air_hum%10 + ); + } +} + void printConfig(BaseSequentialStream *chp, int argc, char *argv[]) { if(argc < 1) diff --git a/tracker/software/debug.h b/tracker/software/debug.h index 8415a27..5f5a747 100644 --- a/tracker/software/debug.h +++ b/tracker/software/debug.h @@ -42,12 +42,13 @@ extern bool debug_on_usb; chprintf((BaseSequentialStream*)&SD3, (format), ##args); \ chprintf((BaseSequentialStream*)&SD3, "\r\n"); \ \ - TRACE_BASE_USB(format, type, ##args); \ + if(debug_on_usb) \ + TRACE_BASE_USB(format, type, ##args); \ chMtxUnlock(&trace_mtx); \ } #define TRACE_BASE_USB(format, type, args...) { \ - if(usb_initialized && debug_on_usb) { \ + if(usb_initialized) { \ if(TRACE_TIME) { \ chprintf((BaseSequentialStream*)&SDU1, "[%8d.%03d]", chVTGetSystemTimeX()/CH_CFG_ST_FREQUENCY, (chVTGetSystemTimeX()*1000/CH_CFG_ST_FREQUENCY)%1000); \ } \ @@ -107,6 +108,7 @@ void debugOnUSB_Off(BaseSequentialStream *chp, int argc, char *argv[]); void debugOnUSB_On(BaseSequentialStream *chp, int argc, char *argv[]); void printConfig(BaseSequentialStream *chp, int argc, char *argv[]); void printPicture(BaseSequentialStream *chp, int argc, char *argv[]); +void readLog(BaseSequentialStream *chp, int argc, char *argv[]); #endif diff --git a/tracker/software/drivers/ov5640.c b/tracker/software/drivers/ov5640.c index 7defb3f..4642140 100644 --- a/tracker/software/drivers/ov5640.c +++ b/tracker/software/drivers/ov5640.c @@ -136,6 +136,7 @@ static const struct regval_list OV5640YUV_Sensor_Dvp_Init[] = { 0x4300, 0x30 }, { 0x501f, 0x00 }, { 0x4713, 0x03 }, + { 0x4404, 0x34 }, { 0x4407, 0x04 }, { 0x460b, 0x35 }, { 0x460c, 0x22 },//add by bright @@ -753,20 +754,21 @@ static const struct regval_list OV5640_QSXGA2XGA[] = {0xffff, 0xff}, }; - -static ssdv_conf_t *ov5640_conf; - -/* TODO: Implement a state machine instead of multiple flags. */ +// TODO: Implement a state machine instead of multiple flags static bool LptimRdy = false; static bool capture_finished; static bool vsync; static bool dma_error; static uint32_t dma_flags; +static uint8_t* dma_buffer; + static uint32_t oldSpeed; static uint32_t oldWS; -/* Increase AHB clock to 48 MHz */ +/** + * Increase AHB clock to 48 MHz and saves the old speed + */ void set48MHz(void) { oldSpeed = RCC->CFGR & RCC_CFGR_HPRE_Msk; @@ -781,9 +783,11 @@ void set48MHz(void) while(RCC->CFGR != new); } +/** + * Reduce AHB clock back to the old speed which has been saved by set48MHz() + */ void set6MHz(void) { - // Reduce AHB clock to 6 MHz uint32_t new = (RCC->CFGR & ~RCC_CFGR_HPRE_Msk) | oldSpeed; RCC->CFGR = new; while(RCC->CFGR != new); @@ -835,36 +839,61 @@ static bool analyze_image(uint8_t *image, uint32_t image_len) } } -bool OV5640_BufferOverflow(void) -{ - return ov5640_conf->size_sampled == ov5640_conf->ram_size - 1; // If SRAM was used completly its most likley that and overflow has occured (TODO: This is not 100% accurate) -} - /** * Captures an image from the camera. + * @buffer Buffer in which the image can be sampled + * @size Size of buffer + * @res Resolution of the image + * If resolution MAX_RES has been chosen, a highest resolution will be chosen + * which it suitable for the amount of buffer. Due to the JPEG compression + * that could lead to different resolutions on different method calls. + * The method returns the size of the image. */ -bool OV5640_Snapshot2RAM(bool enableJpegValidation) +uint32_t OV5640_Snapshot2RAM(uint8_t* buffer, uint32_t size, resolution_t res, bool enableJpegValidation) { - // Capture image until we get a good image (max 10 tries) - uint8_t cntr = 10; + uint8_t cntr = 5; bool status; bool jpegValid; + uint32_t size_sampled; + + // Set resoultion + if(res == RES_MAX) + { + OV5640_SetResolution(RES_UXGA); // FIXME: We actually have to choose the resolution which fits in the memory + } else { + OV5640_SetResolution(res); + } + + // Capture image until we get a good image (max 10 tries) do { + // Clearing buffer + uint32_t i; + for(i=0; i Capture image"); - status = OV5640_Capture(); + status = OV5640_Capture(buffer, size); TRACE_INFO("CAM > Capture finished"); - ov5640_conf->size_sampled = ov5640_conf->ram_size - 1; - while(!ov5640_conf->ram_buffer[ov5640_conf->size_sampled] && ov5640_conf->size_sampled > 0) - ov5640_conf->size_sampled--; + size_sampled = size - 1; + while(!buffer[size_sampled] && size_sampled > 0) + size_sampled--; - TRACE_INFO("CAM > Image size: %d bytes", ov5640_conf->size_sampled); + TRACE_INFO("CAM > Image size: %d bytes", size_sampled); + + // Validate JPEG image + if(enableJpegValidation) + { + TRACE_INFO("CAM > Validate integrity of JPEG"); + jpegValid = analyze_image(buffer, size); + TRACE_INFO("CAM > JPEG image %s", jpegValid ? "valid" : "invalid"); + } else { + jpegValid = true; + } - jpegValid = enableJpegValidation ? true : analyze_image(ov5640_conf->ram_buffer, ov5640_conf->ram_size); } while((!jpegValid || !status) && cntr--); - return true; + return size_sampled; } const stm32_dma_stream_t *dmastp; @@ -971,9 +1000,9 @@ static void dma_interrupt(void *p, uint32_t flags) { if (dmaStreamGetCurrentTarget(dmastp) == 1) { - dmaStreamSetMemory0(dmastp, &ov5640_conf->ram_buffer[++dma_index * DMA_SEGMENT_SIZE]); + dmaStreamSetMemory0(dmastp, &dma_buffer[++dma_index * DMA_SEGMENT_SIZE]); } else { - dmaStreamSetMemory1(dmastp, &ov5640_conf->ram_buffer[++dma_index * DMA_SEGMENT_SIZE]); + dmaStreamSetMemory1(dmastp, &dma_buffer[++dma_index * DMA_SEGMENT_SIZE]); } dmaStreamClearInterrupt(dmastp); return; @@ -1104,9 +1133,8 @@ CH_IRQ_HANDLER(Vector5C) { CH_IRQ_EPILOGUE(); } -bool OV5640_Capture(void) +bool OV5640_Capture(uint8_t* buffer, uint32_t size) { - /* * Note: * If there are no Chibios devices enabled that use DMA then... @@ -1128,14 +1156,16 @@ bool OV5640_Capture(void) #if OV5640_USE_DMA_DBM == TRUE STM32_DMA_CR_DBM | STM32_DMA_CR_HTIE | - #endif STM32_DMA_CR_TCIE; dmaStreamAllocate(dmastp, 2, (stm32_dmaisr_t)dma_interrupt, NULL); dmaStreamSetPeripheral(dmastp, &GPIOA->IDR); // We want to read the data from here + #if OV5640_USE_DMA_DBM == TRUE + dma_buffer = buffer; + /* * Buffer address must be word aligned. * Also note requirement for burst transfers from FIFO. @@ -1146,7 +1176,7 @@ bool OV5640_Capture(void) * Currently this is set to 32 manually in config.c. */ - if (((uint32_t)ov5640_conf->ram_buffer % DMA_FIFO_BURST_ALIGN) != 0) { + if (((uint32_t)buffer % DMA_FIFO_BURST_ALIGN) != 0) { TRACE_ERROR("CAM > Buffer not allocated on DMA burst boundary"); return false; } @@ -1154,15 +1184,15 @@ bool OV5640_Capture(void) * Set the initial buffer addresses. * The updating of DMA:MxAR is done in the the DMA interrupt function. */ - dmaStreamSetMemory0(dmastp, &ov5640_conf->ram_buffer[0]); - dmaStreamSetMemory1(dmastp, &ov5640_conf->ram_buffer[DMA_SEGMENT_SIZE]); + dmaStreamSetMemory0(dmastp, &buffer[0]); + dmaStreamSetMemory1(dmastp, &buffer[DMA_SEGMENT_SIZE]); dmaStreamSetTransactionSize(dmastp, DMA_SEGMENT_SIZE); /* * Calculate the number of whole buffers. * TODO: Make this include remainder memory as partial buffer? */ - dma_buffers = (ov5640_conf->ram_size / DMA_SEGMENT_SIZE); + dma_buffers = (size / DMA_SEGMENT_SIZE); if (dma_buffers == 0) { TRACE_ERROR("CAM > Capture buffer less than minimum DMA segment size"); return false; @@ -1170,8 +1200,8 @@ bool OV5640_Capture(void) /* Start with buffer index 0. */ dma_index = 0; #else - dmaStreamSetMemory0(dmastp, ov5640_conf->ram_buffer); - dmaStreamSetTransactionSize(dmastp, ov5640_conf->ram_size); + dmaStreamSetMemory0(dmastp, buffer); + dmaStreamSetTransactionSize(dmastp, size); #endif dmaStreamSetMode(dmastp, dmamode); // Setup DMA @@ -1183,48 +1213,45 @@ bool OV5640_Capture(void) dma_flags = 0; // Setup timer for PCLK - if(!LptimRdy) - { - rccResetLPTIM1(); - rccEnableLPTIM1(FALSE); + rccResetLPTIM1(); + rccEnableLPTIM1(FALSE); - /* - * LPTIM1 is run in external count mode (CKSEL = 0, COUNTMODE = 1). - * CKPOL is set so leading and trailing edge of PCLK increment the counter. - * The internal clocking (checking edges of LPTIM1_IN) is set to use APB. - * The internal clock must be >4 times the frequency of the input (PCLK). - * NOTE: This does not guarantee that LPTIM1_OUT is coincident with PCLK. - * Depending on PCLK state when LPTIM1 is enabled OUT may get inverted. - * - * LPTIM1 is enabled on the VSYNC edge interrupt. - * After enabling LPTIM1 wait for the first interrupt (ARRIF). - * The interrupt must be disabled on the first interrupt (else flood). - * - * LPTIM1_OUT is gated to TIM1 internal trigger input 2. - */ - LPTIM1->CFGR = (LPTIM_CFGR_COUNTMODE | LPTIM_CFGR_CKPOL_1 | LPTIM_CFGR_WAVPOL); - LPTIM1->OR |= LPTIM_OR_TIM1_ITR2_RMP; - LPTIM1->CR |= LPTIM_CR_ENABLE; - LPTIM1->IER |= LPTIM_IER_ARRMIE; + /* + * LPTIM1 is run in external count mode (CKSEL = 0, COUNTMODE = 1). + * CKPOL is set so leading and trailing edge of PCLK increment the counter. + * The internal clocking (checking edges of LPTIM1_IN) is set to use APB. + * The internal clock must be >4 times the frequency of the input (PCLK). + * NOTE: This does not guarantee that LPTIM1_OUT is coincident with PCLK. + * Depending on PCLK state when LPTIM1 is enabled OUT may get inverted. + * + * LPTIM1 is enabled on the VSYNC edge interrupt. + * After enabling LPTIM1 wait for the first interrupt (ARRIF). + * The interrupt must be disabled on the first interrupt (else flood). + * + * LPTIM1_OUT is gated to TIM1 internal trigger input 2. + */ + LPTIM1->CFGR = (LPTIM_CFGR_COUNTMODE | LPTIM_CFGR_CKPOL_1 | LPTIM_CFGR_WAVPOL); + LPTIM1->OR |= LPTIM_OR_TIM1_ITR2_RMP; + LPTIM1->CR |= LPTIM_CR_ENABLE; + LPTIM1->IER |= LPTIM_IER_ARRMIE; - /* - * When LPTIM1 is enabled and ready LPTIM1_OUT will be not set. - * WAVPOL inverts LPTIM1_OUT so it is not set. - * On the next PCLK edge LPTIM1 will count and match ARR. - * LPTIM1_OUT will set briefly and then clear again due ARR match. - * This triggers TIM1 with the short pulse from LPTIM1_OUT. - * TODO: - * This use of LPTIM1 works probably by good luck for now. - * Switch to direct triggering of TIM using Capture input is better. - * Requires a PCB change. - */ - LPTIM1->CMP = 0; - LPTIM1->ARR = 1; - } + /* + * When LPTIM1 is enabled and ready LPTIM1_OUT will be not set. + * WAVPOL inverts LPTIM1_OUT so it is not set. + * On the next PCLK edge LPTIM1 will count and match ARR. + * LPTIM1_OUT will set briefly and then clear again due ARR match. + * This triggers TIM1 with the short pulse from LPTIM1_OUT. + * TODO: + * This use of LPTIM1 works probably by good luck for now. + * Switch to direct triggering of TIM using Capture input is better. + * Requires a PCB change. + */ + LPTIM1->CMP = 0; + LPTIM1->ARR = 1; /* Set vector and clear flag. */ nvicEnableVector(LPTIM1_IRQn, 7); // Enable interrupt - //LptimRdy = false; + LptimRdy = false; /* * Setup slave timer to trigger DMA. @@ -1256,20 +1283,20 @@ bool OV5640_Capture(void) do { // Have a look for some bytes in memory for testing if capturing works TRACE_INFO("CAM > ... capturing"); - chThdSleepMilliseconds(50); + chThdSleepMilliseconds(100); } while(!capture_finished && !dma_error); - if (dma_error) { - if (dma_flags & STM32_DMA_ISR_HTIF) - TRACE_ERROR("CAM > DMA abort - last buffer segment") - if (dma_flags & STM32_DMA_ISR_FEIF) - TRACE_ERROR("CAM > DMA FIFO error") - if (dma_flags & STM32_DMA_ISR_TEIF) - TRACE_ERROR("CAM > DMA stream transfer error") - if (dma_flags & STM32_DMA_ISR_DMEIF) - TRACE_ERROR("CAM > DMA direct mode error") - TRACE_ERROR("CAM > Error capturing image"); - return false; + if(dma_error) { + if(dma_flags & STM32_DMA_ISR_HTIF) + TRACE_ERROR("CAM > DMA abort - last buffer segment"); + if(dma_flags & STM32_DMA_ISR_FEIF) + TRACE_ERROR("CAM > DMA FIFO error"); + if(dma_flags & STM32_DMA_ISR_TEIF) + TRACE_ERROR("CAM > DMA stream transfer error"); + if(dma_flags & STM32_DMA_ISR_DMEIF) + TRACE_ERROR("CAM > DMA direct mode error"); + TRACE_ERROR("CAM > Error capturing image"); + return false; } TRACE_INFO("CAM > Capture success"); @@ -1320,38 +1347,6 @@ void OV5640_TransmitConfig(void) for(uint32_t i=0; (OV5640_JPEG_QSXGA[i].reg != 0xffff) || (OV5640_JPEG_QSXGA[i].val != 0xff); i++) I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_JPEG_QSXGA[i].reg, OV5640_JPEG_QSXGA[i].val); - TRACE_INFO("CAM > ... Configure Resolution"); - switch(ov5640_conf->res) { - case RES_QQVGA: - for(uint32_t i=0; (OV5640_QSXGA2QQVGA[i].reg != 0xffff) || (OV5640_QSXGA2QQVGA[i].val != 0xff); i++) - I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QQVGA[i].reg, OV5640_QSXGA2QQVGA[i].val); - break; - - case RES_QVGA: - for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++) - I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val); - break; - - case RES_VGA: - for(uint32_t i=0; (OV5640_QSXGA2VGA[i].reg != 0xffff) || (OV5640_QSXGA2VGA[i].val != 0xff); i++) - I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2VGA[i].reg, OV5640_QSXGA2VGA[i].val); - break; - - case RES_XGA: - for(uint32_t i=0; (OV5640_QSXGA2XGA[i].reg != 0xffff) || (OV5640_QSXGA2XGA[i].val != 0xff); i++) - I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2XGA[i].reg, OV5640_QSXGA2XGA[i].val); - break; - - case RES_UXGA: - for(uint32_t i=0; (OV5640_QSXGA2UXGA[i].reg != 0xffff) || (OV5640_QSXGA2UXGA[i].val != 0xff); i++) - I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2UXGA[i].reg, OV5640_QSXGA2UXGA[i].val); - break; - - default: // Default QVGA - for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++) - I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val); - } - TRACE_INFO("CAM > ... Light Mode: Auto"); I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0x03); // start group 3 I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3406, 0x00); @@ -1397,14 +1392,43 @@ void OV5640_TransmitConfig(void) I2C_write8_16bitreg(OV5640_I2C_ADR, 0x3212, 0xa3); // launch group 3 } -void OV5640_init(ssdv_conf_t *config) { - ov5640_conf = config; +void OV5640_SetResolution(resolution_t res) +{ + TRACE_INFO("CAM > ... Configure Resolution"); + switch(res) { + case RES_QQVGA: + for(uint32_t i=0; (OV5640_QSXGA2QQVGA[i].reg != 0xffff) || (OV5640_QSXGA2QQVGA[i].val != 0xff); i++) + I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QQVGA[i].reg, OV5640_QSXGA2QQVGA[i].val); + break; - // Clearing buffer - uint32_t i; - for(i=0; iram_size; i++) - ov5640_conf->ram_buffer[i] = 0; + case RES_QVGA: + for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++) + I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val); + break; + case RES_VGA: + for(uint32_t i=0; (OV5640_QSXGA2VGA[i].reg != 0xffff) || (OV5640_QSXGA2VGA[i].val != 0xff); i++) + I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2VGA[i].reg, OV5640_QSXGA2VGA[i].val); + break; + + case RES_XGA: + for(uint32_t i=0; (OV5640_QSXGA2XGA[i].reg != 0xffff) || (OV5640_QSXGA2XGA[i].val != 0xff); i++) + I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2XGA[i].reg, OV5640_QSXGA2XGA[i].val); + break; + + case RES_UXGA: + for(uint32_t i=0; (OV5640_QSXGA2UXGA[i].reg != 0xffff) || (OV5640_QSXGA2UXGA[i].val != 0xff); i++) + I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2UXGA[i].reg, OV5640_QSXGA2UXGA[i].val); + break; + + default: // Default QVGA + for(uint32_t i=0; (OV5640_QSXGA2QVGA[i].reg != 0xffff) || (OV5640_QSXGA2QVGA[i].val != 0xff); i++) + I2C_write8_16bitreg(OV5640_I2C_ADR, OV5640_QSXGA2QVGA[i].reg, OV5640_QSXGA2QVGA[i].val); + } +} + +void OV5640_init(void) +{ TRACE_INFO("CAM > Init pins"); OV5640_InitGPIO(); @@ -1422,7 +1446,8 @@ void OV5640_init(ssdv_conf_t *config) { chThdSleepMilliseconds(1000); } -void OV5640_deinit(void) { +void OV5640_deinit(void) +{ // Power off OV5640 TRACE_INFO("CAM > Switch off"); diff --git a/tracker/software/drivers/ov5640.h b/tracker/software/drivers/ov5640.h index 07f4d9e..f729942 100644 --- a/tracker/software/drivers/ov5640.h +++ b/tracker/software/drivers/ov5640.h @@ -11,14 +11,15 @@ #define OV5640_USE_DMA_DBM TRUE -bool OV5640_Snapshot2RAM(bool enableJpegValidation); -bool OV5640_Capture(void); +uint32_t OV5640_Snapshot2RAM(uint8_t* buffer, uint32_t size, resolution_t resolution, bool enableJpegValidation); +bool OV5640_Capture(uint8_t* buffer, uint32_t size); void OV5640_InitGPIO(void); -bool OV5640_BufferOverflow(void); void OV5640_TransmitConfig(void); -void OV5640_init(ssdv_conf_t *config); +void OV5640_SetResolution(resolution_t res); +void OV5640_init(void); void OV5640_deinit(void); bool OV5640_isAvailable(void); uint32_t OV5640_getLightIntensity(void); #endif + diff --git a/tracker/software/main.c b/tracker/software/main.c index 7fc0dd9..f7b2ac0 100644 --- a/tracker/software/main.c +++ b/tracker/software/main.c @@ -11,6 +11,7 @@ static const ShellCommand commands[] = { {"dbgon", debugOnUSB_On}, {"dbgoff", debugOnUSB_Off}, {"picture", printPicture}, + {"log", readLog}, // {"printconfig", printConfig}, FIXME: This feature is faulty at the moment {NULL, NULL} }; diff --git a/tracker/software/threads/image.c b/tracker/software/threads/image.c index 041936f..d8d59aa 100644 --- a/tracker/software/threads/image.c +++ b/tracker/software/threads/image.c @@ -435,57 +435,24 @@ bool takePicture(ssdv_conf_t *conf, bool enableJpegValidation) TRACE_INFO("IMG > OV5640 found"); camera_found = true; - if(conf->res == RES_MAX) // Attempt maximum resolution (limited by memory) - { - conf->res = RES_UXGA; // Try maximum resolution - - do { - - // Init camera - if(!camInitialized) { - OV5640_init(conf); - camInitialized = true; - } - - // Sample data from DCMI through DMA into RAM - uint8_t tries = 5; // Try 5 times at maximum - bool status; - do { // Try capturing image until capture successful - lockRadio(); // Lock radio - status = OV5640_Snapshot2RAM(enableJpegValidation); - unlockRadio(); // Unlock radio - } while(!status && --tries); - - conf->res--; // Decrement resolution in next attempt (if status==false) - - } while(OV5640_BufferOverflow() && conf->res >= RES_QVGA); - - conf->res = RES_MAX; // Revert register - - } else { // Static resolution - - // Init camera - if(!camInitialized) { - OV5640_init(conf); - camInitialized = true; - } - - // Sample data from DCMI through DMA into RAM - uint8_t tries = 5; // Try 5 times at maximum - bool status; - do { // Try capturing image until capture successful - status = OV5640_Snapshot2RAM(enableJpegValidation); - } while(!status && --tries); - + // Init camera + if(!camInitialized) { + OV5640_init(); + camInitialized = true; } + // Sample data from pseudo DCMI through DMA into RAM + lockRadio(); // Lock radio + conf->size_sampled = OV5640_Snapshot2RAM(conf->ram_buffer, conf->ram_size, conf->res, enableJpegValidation); + unlockRadio(); // Unlock radio + // Switch off camera if(!keep_cam_switched_on) { OV5640_deinit(); camInitialized = false; } - } else { // Camera error + } else { // Camera not found camInitialized = false; TRACE_ERROR("IMG > No camera found"); diff --git a/tracker/software/threads/image.h b/tracker/software/threads/image.h index d80e2aa..a8a2560 100644 --- a/tracker/software/threads/image.h +++ b/tracker/software/threads/image.h @@ -4,11 +4,6 @@ #include "ch.h" #include "hal.h" -#define IMG_ID_FLASH_ADDR 0x80A0000 /* Image ID flash memory address */ -#define IMG_ID_FLASH_SIZE (128*1024) /* Image ID flash memory size */ - -extern const uint8_t noCameraFound[4071]; - void start_image_thread(module_conf_t *conf); bool takePicture(ssdv_conf_t *conf, bool enableJpegValidation); extern mutex_t camera_mtx;