kopia lustrzana https://github.com/DL7AD/pecanpico9
Implemented shell, worked on camera driver (not working)
rodzic
c2e9f44465
commit
44aa301d5f
|
@ -100,6 +100,7 @@ include $(CHIBIOS)/os/common/ports/ARMCMx/compilers/GCC/mk/port_v7m.mk
|
|||
# Other files (optional).
|
||||
include $(CHIBIOS)/test/rt/test.mk
|
||||
include $(CHIBIOS)/os/hal/lib/streams/streams.mk
|
||||
include $(CHIBIOS)/os/various/shell/shell.mk
|
||||
|
||||
# Define linker script file here
|
||||
LDSCRIPT= board/STM32F413xH.ld
|
||||
|
@ -113,6 +114,8 @@ CSRC = $(STARTUPSRC) \
|
|||
$(HALSRC) \
|
||||
$(PLATFORMSRC) \
|
||||
$(BOARDSRC) \
|
||||
$(TESTSRC) \
|
||||
$(SHELLSRC) \
|
||||
$(CHIBIOS)/os/hal/lib/streams/memstreams.c \
|
||||
$(CHIBIOS)/os/hal/lib/streams/chprintf.c \
|
||||
modules/tracking.c \
|
||||
|
@ -177,8 +180,9 @@ ASMXSRC = $(STARTUPASM) $(PORTASM) $(OSALASM)
|
|||
|
||||
INCDIR = $(CHIBIOS)/os/license \
|
||||
$(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \
|
||||
$(HALINC) $(PLATFORMINC) $(BOARDINC) \
|
||||
$(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \
|
||||
$(CHIBIOS)/os/hal/lib/streams $(CHIBIOS)/os/various \
|
||||
$(SHELLINC)
|
||||
|
||||
#
|
||||
# Project, sources and paths
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "radio.h"
|
||||
#include "sleep.h"
|
||||
|
||||
|
||||
#define TRACK_CYCLE_TIME 30 /* Tracking cycle (all peripheral data [airpressure, GPS, temperature, ...] is collected each x seconds */
|
||||
|
||||
#define LOG_CYCLE_TIME 30 /* Log cycle time in seconds */
|
||||
|
@ -27,6 +26,7 @@
|
|||
* order to work. However 3V takes a lot of power in idle. You can save energy using 1.8V. */
|
||||
|
||||
void start_user_modules(void);
|
||||
extern module_conf_t config[9];
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "ch.h"
|
||||
#include "hal.h"
|
||||
#include "debug.h"
|
||||
#include <stdlib.h>
|
||||
#include "config.h"
|
||||
|
||||
const SerialConfig uart_config =
|
||||
{
|
||||
|
@ -12,3 +14,59 @@ const SerialConfig uart_config =
|
|||
|
||||
mutex_t trace_mtx; // Used internal to synchronize multiple chprintf in debug.h
|
||||
|
||||
bool debug_on_usb = true;
|
||||
|
||||
void debugOnUSB_Off(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
{
|
||||
(void)chp;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
debug_on_usb = false;
|
||||
}
|
||||
|
||||
void debugOnUSB_On(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
{
|
||||
(void)chp;
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
debug_on_usb = true;
|
||||
}
|
||||
|
||||
void printConfig(BaseSequentialStream *chp, int argc, char *argv[])
|
||||
{
|
||||
if(argc < 1)
|
||||
{
|
||||
chprintf(chp, "Argument missing!\r\n");
|
||||
chprintf(chp, "Argument 1: Id of config!\r\n");
|
||||
}
|
||||
|
||||
uint8_t id = atoi(argv[0]);
|
||||
chprintf(chp, "Config ID=%d\r\n", id);
|
||||
|
||||
chprintf(chp, "Power: %d\r\n", config[id].power);
|
||||
|
||||
if(config[id].frequency.type == FREQ_STATIC) {
|
||||
chprintf(chp, "Frequency: %d Hz\r\n", config[id].frequency.hz);
|
||||
} else {
|
||||
chprintf(chp, "Frequency: APRS region dependent (currently %d Hz\r\n", getFrequency(&config[id].frequency));
|
||||
}
|
||||
|
||||
chprintf(chp, "Protocol: %d\r\n", config[id].protocol);
|
||||
chprintf(chp, "Initial Delay: %d\r\n", config[id].init_delay);
|
||||
chprintf(chp, "Packet Spacing: %d\r\n", config[id].packet_spacing);
|
||||
chprintf(chp, "Sleep config: xx\r\n");
|
||||
chprintf(chp, "Trigger config: xx\r\n");
|
||||
|
||||
chprintf(chp, "Modulation config: xx\r\n");
|
||||
|
||||
chprintf(chp, "Protocol config: xx\r\n");
|
||||
|
||||
chprintf(chp, "SSDV config: xx\r\n");
|
||||
|
||||
chprintf(chp, "Watchdog timeout: %d\r\n", config[id].wdg_timeout);
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
extern mutex_t trace_mtx;
|
||||
extern const SerialConfig uart_config;
|
||||
extern bool debug_on_usb;
|
||||
|
||||
// Initializer for serial debug and LEDs
|
||||
#define DEBUG_INIT() { \
|
||||
|
@ -41,7 +42,7 @@ extern const SerialConfig uart_config;
|
|||
chprintf((BaseSequentialStream*)&SD3, (format), ##args); \
|
||||
chprintf((BaseSequentialStream*)&SD3, "\r\n"); \
|
||||
\
|
||||
if(usb_initialized) { \
|
||||
if(usb_initialized && debug_on_usb) { \
|
||||
if(TRACE_TIME) { \
|
||||
chprintf((BaseSequentialStream*)&SDU1, "[%8d.%03d]", chVTGetSystemTimeX()/CH_CFG_ST_FREQUENCY, (chVTGetSystemTimeX()*1000/CH_CFG_ST_FREQUENCY)%1000); \
|
||||
} \
|
||||
|
@ -113,5 +114,9 @@ extern const SerialConfig uart_config;
|
|||
TRACE_INFO("%-4s > Current time: %02d-%02d-%02d %02d:%02d:%02d:%03d", thd, dbgtime.year, dbgtime.month, dbgtime.day, dbgtime.hour, dbgtime.minute, dbgtime.second, dbgtime.millisecond); \
|
||||
}
|
||||
|
||||
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[]);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -312,7 +312,7 @@ static const struct regval_list ov2640_init_regs[] = {
|
|||
{ 0x2e, 0xdf },
|
||||
{ BANK_SEL, BANK_SEL_SENS },
|
||||
{ 0x3c, 0x32 },
|
||||
{ CLKRC, CLKRC_DIV_SET(3) },
|
||||
{ CLKRC, CLKRC_DIV_SET(4) },
|
||||
{ COM2, COM2_OCAP_Nx_SET(3) },
|
||||
{ REG04, REG04_DEF | REG04_HREF_EN },
|
||||
{ COM8, COM8_DEF | COM8_AGC_EN | COM8_AEC_EN },
|
||||
|
@ -648,18 +648,20 @@ bool OV2640_Snapshot2RAM(void)
|
|||
|
||||
bool OV2640_BufferOverflow(void)
|
||||
{
|
||||
return ov2640_conf->ram_buffer[0] != 0xFF || ov2640_conf->ram_buffer[1] != 0xD8; // Check for JPEG SOI header
|
||||
return ov2640_conf->image_buffer[0] != 0xFF || ov2640_conf->image_buffer[1] != 0xD8; // Check for JPEG SOI header
|
||||
}
|
||||
|
||||
uint32_t OV2640_getBuffer(uint8_t** buffer) {
|
||||
*buffer = ov2640_conf->ram_buffer;
|
||||
*buffer = ov2640_conf->ram_buffer[0];
|
||||
return ov2640_conf->size_sampled;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
|
||||
const stm32_dma_stream_t *dmastp;
|
||||
static bool image_finished;
|
||||
uint8_t dma_index;
|
||||
|
||||
inline int32_t dma_start(void) {
|
||||
/* Clear any pending inerrupts. */
|
||||
|
@ -674,59 +676,95 @@ inline int32_t dma_stop(void) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get DMA stream current target.
|
||||
* @note This function can be invoked in both ISR or thread context.
|
||||
* @pre The stream must have been allocated using @p dmaStreamAllocate().
|
||||
* @post After use the stream can be released using @p dmaStreamRelease().
|
||||
*
|
||||
* @param[in] dmastp pointer to a stm32_dma_stream_t structure
|
||||
* @return Current target index
|
||||
*
|
||||
* @special
|
||||
*/
|
||||
#define dmaStreamGetCurrentTarget(dmastp) \
|
||||
((uint8_t)(((dmastp)->stream->CR >> DMA_SxCR_CT_Pos) & 1U))
|
||||
|
||||
static void dma_interrupt(void *p, uint32_t flags) {
|
||||
(void)p;
|
||||
/* No parameter passed. */
|
||||
(void)p;
|
||||
|
||||
if ((flags & STM32_DMA_ISR_HTIF) != 0) {
|
||||
/* Deprecate - Nothing really to do at half way point. */
|
||||
return;
|
||||
}
|
||||
if ((flags & STM32_DMA_ISR_TCIF) != 0) {
|
||||
/* End of transfer. */
|
||||
palSetLine(LINE_IO_LED1);
|
||||
if (flags & STM32_DMA_ISR_HTIF) {
|
||||
/*
|
||||
* Half transfer complete.
|
||||
* Check if DMA is writing to the last buffer.
|
||||
*/
|
||||
if (dma_index == (DMA_BUFFERS - 1)) {
|
||||
/*
|
||||
* This is the last buffer so we have to terminate DMA.
|
||||
* Because the DBM switch is done in h/w.
|
||||
* Stopping DMA in interrupt would be too late.
|
||||
* DMA would write beyond buffer or overwrite prior buffer (if MxAR not updated).
|
||||
*
|
||||
* So stop DMA and TIM DMA trigger.
|
||||
*/
|
||||
dmaStreamClearInterrupt(dmastp);
|
||||
chSysLockFromISR();
|
||||
dma_stop();
|
||||
TIM1->DIER &= ~TIM_DIER_TDE;
|
||||
image_finished = true;
|
||||
/* Disable HSYNC and VYSNC edge interrupts. */
|
||||
nvicDisableVector(EXTI1_IRQn);
|
||||
nvicDisableVector(EXTI2_IRQn);
|
||||
chSysUnlockFromISR();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* Else Safe to allow buffer to fill.
|
||||
* DMA DBM will switch buffers in h/w this one is full.
|
||||
* Just clear the interrupt and wait for TCIF.
|
||||
*/
|
||||
dmaStreamClearInterrupt(dmastp);
|
||||
return;
|
||||
}
|
||||
if (flags & STM32_DMA_ISR_TCIF) {
|
||||
/*
|
||||
* Full transfer complete.
|
||||
* Update non-active memory address register.
|
||||
* DMA will use new address at h/w DBM switch.
|
||||
*/
|
||||
dmaStreamClearInterrupt(dmastp);
|
||||
|
||||
/*
|
||||
* Stop TIM8 DMA trigger.
|
||||
* Stop and release DMA channel.
|
||||
* Either DMA count full or VSNC traling edge can terminate frame capture
|
||||
*/
|
||||
TIM8->DIER &= ~TIM_DIER_CC1DE;
|
||||
dma_stop();
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* TODO: Anything else is an error.
|
||||
* Maybe set an error flag?
|
||||
*/
|
||||
if (dmaStreamGetCurrentTarget(dmastp) == 1) {
|
||||
dmaStreamSetMemory0(dmastp, ram_buffer[++dma_index]);
|
||||
} else {
|
||||
dmaStreamSetMemory1(dmastp, ram_buffer[++dma_index]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static bool image_finished;
|
||||
|
||||
|
||||
// This is the vector for HREF (EXTI2) (stolen from hal_ext_lld_isr.c)
|
||||
|
||||
CH_FAST_IRQ_HANDLER(Vector60) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
//CH_IRQ_PROLOGUE();
|
||||
|
||||
uint8_t gpioc = GPIOC->IDR;
|
||||
//uint8_t gpioc = GPIOC->IDR;
|
||||
// HREF handling
|
||||
if(gpioc & 0x4) {
|
||||
if(GPIOC->IDR & 0x4) {
|
||||
// HREF rising edge, start capturing data on pixel clock
|
||||
/*
|
||||
* Start or re-start dma. The transfer count already set will be used.
|
||||
* The M0AR (DMA memory address) register is set for autoincrement.
|
||||
* It will be pointing to the next buffer address when DMA is re-started.
|
||||
* Start or continuation of dma.
|
||||
* Set TIM8_CH1 capture input rising edge as DMA trigger.
|
||||
*/
|
||||
//dma_start();
|
||||
/* Set TIM8 trigger to initate DMA. */
|
||||
TIM8->DIER |= TIM_DIER_CC1DE;
|
||||
} else {
|
||||
/* Remove TIM8 trigger to initate DMA. */
|
||||
/* On falling edge remove TIM8 trigger for DMA. */
|
||||
TIM8->DIER &= ~TIM_DIER_CC1DE;
|
||||
}
|
||||
|
||||
EXTI->PR |= EXTI_PR_PR2;
|
||||
CH_IRQ_EPILOGUE();
|
||||
//CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
bool vsync = false;
|
||||
|
@ -737,31 +775,28 @@ bool vsync = false;
|
|||
* This is contrary to the OV2640 datasheet which shows VSYNC as pulses.
|
||||
*/
|
||||
CH_FAST_IRQ_HANDLER(Vector5C) {
|
||||
CH_IRQ_PROLOGUE();
|
||||
//CH_IRQ_PROLOGUE();
|
||||
|
||||
// VSYNC handling
|
||||
if(!vsync && palReadLine(LINE_CAM_VSYNC)) {
|
||||
/*
|
||||
* Rising edge of VSYNC after LPTIM1 has been initiualized.
|
||||
* Start DMA channel.
|
||||
* Enable TIM8 trigger of DMA.
|
||||
* Rising edge of VSYNC .
|
||||
*/
|
||||
dma_start();
|
||||
TIM8->DIER |= TIM_DIER_CC1DE;
|
||||
|
||||
palClearLine(LINE_IO_LED1); // Indicate that picture will be captured
|
||||
vsync = true;
|
||||
} else if(vsync) {
|
||||
} else if(vsync && !palReadLine(LINE_CAM_VSYNC)) {
|
||||
/* VSYNC falling edge - end of JPEG frame.
|
||||
* Stop & release the DMA channel.
|
||||
* Disable TIM8 trigger of DMA and stop PCLK via LPTIM1
|
||||
* Disable TIM8 trigger of DMA
|
||||
* These should have already been disabled in DMA interrupt if was filled.
|
||||
*/
|
||||
dma_stop();
|
||||
TIM8->DIER &= ~TIM_DIER_CC1DE;
|
||||
|
||||
/* Disable VYSNC edge interrupts. */
|
||||
/* Disable HSYNC & VYSNC edge interrupts. */
|
||||
nvicDisableVector(EXTI1_IRQn);
|
||||
//nvicDisableVector(EXTI2_IRQn);
|
||||
nvicDisableVector(EXTI2_IRQn);
|
||||
/* Turn on capture LED and signal the semaphore (data can be processed). */
|
||||
palSetLine(LINE_IO_LED1);
|
||||
image_finished = true;
|
||||
|
@ -771,9 +806,11 @@ CH_FAST_IRQ_HANDLER(Vector5C) {
|
|||
palToggleLine(LINE_IO_LED1);
|
||||
|
||||
EXTI->PR |= EXTI_PR_PR1;
|
||||
CH_IRQ_EPILOGUE();
|
||||
//CH_IRQ_EPILOGUE();
|
||||
}
|
||||
|
||||
uint8_t ram_buffer[DMA_BUFFERS][DMA_SIZE] __attribute__((aligned(DMA_ALIGNMENT)));
|
||||
|
||||
bool OV2640_Capture(void)
|
||||
{
|
||||
/*
|
||||
|
@ -783,32 +820,65 @@ bool OV2640_Capture(void)
|
|||
* UDEFS = -DSTM32_DMA_REQUIRED
|
||||
*/
|
||||
|
||||
/* Setup DMA for transfer on TIM8_CH1 - DMA2 stream 2, channel 7 */
|
||||
/*
|
||||
* Setup DMA for transfer on TIM8_CH1 - DMA2 stream 2, channel 7.
|
||||
* Direction is peripheral (GPIO) to memory.
|
||||
* Set highest priority (3).
|
||||
* Further down we set DMA FIFO to write to memory on FIFO full (4 words).
|
||||
* GPIO is 8 bit, memory is 32 bit, memory burst write using 4 beats.
|
||||
*/
|
||||
dmastp = STM32_DMA_STREAM(STM32_DMA_STREAM_ID(2, 2));
|
||||
uint32_t dmamode = STM32_DMA_CR_CHSEL(7) |
|
||||
STM32_DMA_CR_PL(2) |
|
||||
STM32_DMA_CR_PL(3) |
|
||||
STM32_DMA_CR_DIR_P2M |
|
||||
STM32_DMA_CR_MSIZE_BYTE |
|
||||
STM32_DMA_CR_MSIZE_WORD |
|
||||
STM32_DMA_CR_PSIZE_BYTE |
|
||||
STM32_DMA_CR_MINC |
|
||||
STM32_DMA_CR_DMEIE |
|
||||
STM32_DMA_CR_TEIE |
|
||||
STM32_DMA_CR_HTIE |
|
||||
STM32_DMA_CR_TCIE |
|
||||
STM32_DMA_CR_MBURST_INCR16;
|
||||
STM32_DMA_CR_DBM |
|
||||
STM32_DMA_CR_MBURST_INCR4;
|
||||
|
||||
chSysLock();
|
||||
|
||||
dmaStreamAllocate(dmastp, 2, (stm32_dmaisr_t)dma_interrupt, NULL);
|
||||
|
||||
dmaStreamSetPeripheral(dmastp, &GPIOA->IDR); // We want to read the data from here
|
||||
dmaStreamSetMemory0(dmastp, ov2640_conf->ram_buffer); // Thats the buffer address
|
||||
dmaStreamSetTransactionSize(dmastp, ov2640_conf->ram_size); // Thats the buffer size
|
||||
/*
|
||||
* Buffer address must be word aligned.
|
||||
* Also note requirement for burst transfers.
|
||||
* Bursts must not cross a 1K address boundary.
|
||||
* See RM0430 9.3.12
|
||||
* DMA buffers for ov2640_conf should be defined like this...
|
||||
* #define DMA_ALIGNMENT 1024
|
||||
* #define DMA_SIZE DMA_ALIGNMENT
|
||||
* #define DMA_BUFFERS 6
|
||||
* uint8_t ram_buffer[DMA_BUFFERS][DMA_SIZE] __attribute__((aligned(DMA_ALIGNMENT)));
|
||||
*
|
||||
*/
|
||||
dmaStreamSetMemory0(dmastp, ov2640_conf->ram_buffer[0]);
|
||||
dmaStreamSetMemory1(dmastp, ov2640_conf->ram_buffer[1]);
|
||||
/*
|
||||
* Transfer size (NDT) must be a multiple of 4 bytes.
|
||||
* See RM0430 9.3.11
|
||||
*/
|
||||
dmaStreamSetTransactionSize(dmastp, DMA_SIZE);
|
||||
//dmaStreamSetTransactionSize(dmastp, (ov2640_conf->ram_size));
|
||||
|
||||
dmaStreamSetMode(dmastp, dmamode); // Setup DMA
|
||||
/* Setup DMA...
|
||||
* Disable direct mode (enable FIFO).
|
||||
* Set FIFO to transfer at full.
|
||||
* Clear any outstanding interrupt.
|
||||
*/
|
||||
dmaStreamSetMode(dmastp, dmamode);
|
||||
dmaStreamSetFIFO(dmastp, STM32_DMA_FCR_DMDIS | STM32_DMA_FCR_FTH_FULL);
|
||||
|
||||
dmaStreamClearInterrupt(dmastp);
|
||||
/*
|
||||
* Setup timer to trigger DMA.
|
||||
* We have to use TIM8 because...
|
||||
* > TIM8_CH1 is in DMA2 and we need DMA2 for peripheral -> memory transfer
|
||||
* - TIM8_CH1 is in DMA2 and we need DMA2 for peripheral -> memory transfer
|
||||
*/
|
||||
rccResetTIM8();
|
||||
rccEnableTIM8(FALSE);
|
||||
|
@ -817,7 +887,7 @@ bool OV2640_Capture(void)
|
|||
TIM8->CCER |= TIM_CCER_CC1E; // Enable capture channel
|
||||
TIM8->CCER |= TIM_CCER_CC1P; // Select trailing edge
|
||||
|
||||
image_finished = false;
|
||||
|
||||
|
||||
// Setup EXTI: EXTI1 PC for PC1 (VSYNC) and EXIT2 PC for PC2 (HREF)
|
||||
SYSCFG->EXTICR[0] |= SYSCFG_EXTICR1_EXTI1_PC | SYSCFG_EXTICR1_EXTI2_PC;
|
||||
|
@ -825,28 +895,35 @@ bool OV2640_Capture(void)
|
|||
EXTI->IMR = EXTI_IMR_MR1 | EXTI_IMR_MR2; // Activate interrupt for chan1 (=>PC1) and chan2 (=>PC2)
|
||||
EXTI->RTSR = EXTI_RTSR_TR1 | EXTI_RTSR_TR2; // Listen on rising edge
|
||||
EXTI->FTSR = EXTI_FTSR_TR1 | EXTI_FTSR_TR2; // Listen on falling edge too
|
||||
|
||||
nvicEnableVector(EXTI1_IRQn, 2); // Enable interrupt
|
||||
nvicEnableVector(EXTI2_IRQn, 1); // Enable interrupt
|
||||
|
||||
do { // Have a look for some bytes in memory for testing if capturing works
|
||||
int32_t size=65535;
|
||||
while(ov2640_conf->ram_buffer[size] == 0 && size >= 0)
|
||||
size--;
|
||||
//TRACE_DEBUG("CAM > Image %d %02x %02x %02x %02x", size, ov2640_conf->ram_buffer[0], ov2640_conf->ram_buffer[1], ov2640_conf->ram_buffer[2], ov2640_conf->ram_buffer[3]);
|
||||
chThdSleepMilliseconds(100);
|
||||
} while(!image_finished);
|
||||
|
||||
/* Reset any pending interrupt. */
|
||||
EXTI->PR |= EXTI_PR_PR1;
|
||||
EXTI->PR |= EXTI_PR_PR2;
|
||||
/* Enable interrupt vectors. */
|
||||
nvicEnableVector(EXTI1_IRQn, 2);
|
||||
nvicEnableVector(EXTI2_IRQn, 1);
|
||||
/* Start DMA and timer DMA. */
|
||||
dma_start();
|
||||
TIM8->DIER |= TIM_DIER_CC1DE;
|
||||
|
||||
image_finished = false;
|
||||
dma_index = 0;
|
||||
chSysUnlock();
|
||||
|
||||
do {
|
||||
osalThdSleepMilliseconds(100);
|
||||
} while(!image_finished);
|
||||
|
||||
unit8_t *image_buffer = ov2640_conf->ram_buffer[0];
|
||||
int32_t size=65535;
|
||||
while(ov2640_conf->ram_buffer[size] == 0 && size >= 0)
|
||||
while(ov2640_conf->image_buffer[size] == 0 && size >= 0)
|
||||
size--;
|
||||
TRACE_DEBUG("CAM > Image %d %02x %02x %02x %02x", size, ov2640_conf->ram_buffer[0], ov2640_conf->ram_buffer[1], ov2640_conf->ram_buffer[2], ov2640_conf->ram_buffer[3]);
|
||||
TRACE_DEBUG("CAM > Image %d %02x %02x %02x %02x", size, ov2640_conf->image_buffer[0], ov2640_conf->image_buffer[1], ov2640_conf->image_buffer[2], ov2640_conf->image_buffer[3]);
|
||||
|
||||
TRACE_DEBUG("CAM > Have a look for SOI");
|
||||
uint32_t soi; // Start of Image
|
||||
for(soi=0; soi<65533; soi++)
|
||||
{
|
||||
if(ov2640_conf->ram_buffer[soi] == 0xFF && ov2640_conf->ram_buffer[soi+1] == 0xD8)
|
||||
if(ov2640_conf->image_buffer[soi] == 0xFF && ov2640_conf->image_buffer[soi+1] == 0xD8)
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -859,47 +936,48 @@ bool OV2640_Capture(void)
|
|||
|
||||
// Found SOI, move bytes
|
||||
for(uint32_t i=0; i<65535; i++)
|
||||
ov2640_conf->ram_buffer[i] = ov2640_conf->ram_buffer[i+soi];
|
||||
ov2640_conf->image_buffer[i] = ov2640_conf->image_buffer[i+soi];
|
||||
|
||||
TRACE_DEBUG("CAM > Image %02x %02x %02x %02x", ov2640_conf->ram_buffer[0], ov2640_conf->ram_buffer[1], ov2640_conf->ram_buffer[2], ov2640_conf->ram_buffer[3]);
|
||||
TRACE_DEBUG("CAM > Image %02x %02x %02x %02x", ov2640_conf->image_buffer[0], ov2640_conf->image_buffer[1], ov2640_conf->image_buffer[2], ov2640_conf->image_buffer[3]);
|
||||
TRACE_INFO("CAM > Capture finished");
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
|
||||
bool image_finished;
|
||||
bool sample_byte;
|
||||
|
||||
bool OV2640_Capture(void)
|
||||
{
|
||||
TRACE_INFO("CAM > Start capture");
|
||||
while(1)
|
||||
|
||||
while(palReadLine(LINE_CAM_VSYNC));
|
||||
while(!palReadLine(LINE_CAM_VSYNC));
|
||||
|
||||
uint8_t gpioc;
|
||||
uint8_t gpioa;
|
||||
ov2640_conf->size_sampled = 0;
|
||||
while(true)
|
||||
{
|
||||
while(palReadLine(LINE_CAM_VSYNC));
|
||||
while(!palReadLine(LINE_CAM_VSYNC));
|
||||
do {
|
||||
gpioc = GPIOC->IDR & 0x7;
|
||||
} while((gpioc & 0x1) != 0x1); // Wait for PCLK to rise
|
||||
|
||||
uint8_t gpioc;
|
||||
uint8_t gpioa;
|
||||
ov2640_conf->size_sampled = 0;
|
||||
while(true)
|
||||
{
|
||||
do {
|
||||
gpioc = GPIOC->IDR & 0x7;
|
||||
} while((gpioc & 0x1) != 0x1); // Wait for PCLK to rise
|
||||
gpioa = GPIOA->IDR;
|
||||
|
||||
gpioa = GPIOA->IDR;
|
||||
|
||||
switch(gpioc) {
|
||||
case 0x3:
|
||||
break;
|
||||
case 0x7:
|
||||
ov2640_conf->ram_buffer[ov2640_conf->size_sampled++] = gpioa;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wait for falling edge
|
||||
while(GPIOC->IDR & 0x1);
|
||||
switch(gpioc) {
|
||||
case 0x3:
|
||||
break;
|
||||
case 0x7:
|
||||
ov2640_conf->ram_buffer[ov2640_conf->size_sampled++] = gpioa;
|
||||
break;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
||||
// Wait for falling edge
|
||||
while(GPIOC->IDR & 0x1);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -998,7 +1076,7 @@ void OV2640_init(ssdv_conf_t *config) {
|
|||
// Clearing buffer
|
||||
uint32_t i;
|
||||
for(i=0; i<ov2640_conf->ram_size; i++)
|
||||
ov2640_conf->ram_buffer[i] = 0;
|
||||
ov2640_conf->ram_buffer[0][i] = 0;
|
||||
|
||||
TRACE_INFO("CAM > Init pins");
|
||||
OV2640_InitGPIO();
|
||||
|
|
Plik diff jest za duży
Load Diff
|
@ -5,6 +5,19 @@
|
|||
#include "modules.h"
|
||||
#include "padc.h"
|
||||
#include "usbcfg.h"
|
||||
#include "shell.h"
|
||||
|
||||
static const ShellCommand commands[] = {
|
||||
{"dbgon", debugOnUSB_On},
|
||||
{"dbgoff", debugOnUSB_Off},
|
||||
// {"printconfig", printConfig}, FIXME: This feature is faulty at the moment
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
static const ShellConfig shell_cfg = {
|
||||
(BaseSequentialStream *)&SDU1,
|
||||
commands
|
||||
};
|
||||
|
||||
/**
|
||||
* Main routine is starting up system, runs the software watchdog (module monitoring), controls LEDs
|
||||
|
@ -48,8 +61,11 @@ int main(void) {
|
|||
|
||||
// Print time every 10 sec
|
||||
while(true) {
|
||||
PRINT_TIME("MAIN");
|
||||
chThdSleepMilliseconds(10000);
|
||||
if (SDU1.config->usbp->state == USB_ACTIVE) {
|
||||
thread_t *shelltp = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2048), "shell", NORMALPRIO+1, shellThread, (void*)&shell_cfg);
|
||||
chThdWait(shelltp);
|
||||
}
|
||||
chThdSleepMilliseconds(1000);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,5 @@ void start_essential_threads(void) {
|
|||
|
||||
pi2cInit(); // Initialize I2C
|
||||
pac1720_init(); // Initialize current measurement
|
||||
|
||||
// Start tracking manager
|
||||
init_tracking_manager();
|
||||
chThdSleepMilliseconds(1000); // Give Tracking manager some time to fill first track point
|
||||
}
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ void start_position_thread(module_conf_t *conf)
|
|||
if(conf->init_delay) chThdSleepMilliseconds(conf->init_delay);
|
||||
|
||||
// Start tracking manager (if not running yet)
|
||||
setTrackingManagerRunning();
|
||||
init_tracking_manager();
|
||||
|
||||
// Start position thread
|
||||
TRACE_INFO("POS > Startup position thread");
|
||||
|
|
|
@ -16,7 +16,7 @@ static trackPoint_t trackPoints[2];
|
|||
static trackPoint_t* lastTrackPoint;
|
||||
static systime_t nextLogEntryTimer;
|
||||
static module_conf_t trac_conf = {.name = "TRAC"}; // Fake config needed for watchdog tracking
|
||||
static bool blockThread = true;
|
||||
static bool threadStarted = false;
|
||||
|
||||
/**
|
||||
* Returns most recent track point witch is complete.
|
||||
|
@ -159,13 +159,6 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
uint32_t id = 1;
|
||||
lastTrackPoint = &trackPoints[0]; // FIXME: That might not work
|
||||
|
||||
// Block thread while no position thread is started
|
||||
while(blockThread)
|
||||
{
|
||||
trac_conf.wdg_timeout = chVTGetSystemTimeX() + S2ST(5);
|
||||
chThdSleepMilliseconds(1000);
|
||||
}
|
||||
|
||||
// Fill initial values by PAC1720 and BME280 and RTC
|
||||
|
||||
// Time
|
||||
|
@ -368,25 +361,20 @@ THD_FUNCTION(trackingThread, arg) {
|
|||
|
||||
void init_tracking_manager(void)
|
||||
{
|
||||
TRACE_INFO("TRAC > Startup tracking thread");
|
||||
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2*1024), "TRA", NORMALPRIO, trackingThread, NULL);
|
||||
if(!th) {
|
||||
// Print startup error, do not start watchdog for this thread
|
||||
TRACE_ERROR("TRAC > Could not startup thread (not enough memory available)");
|
||||
} else {
|
||||
register_thread_at_wdg(&trac_conf);
|
||||
trac_conf.wdg_timeout = chVTGetSystemTimeX() + S2ST(1);
|
||||
if(!threadStarted)
|
||||
{
|
||||
threadStarted = true;
|
||||
|
||||
TRACE_INFO("TRAC > Startup tracking thread");
|
||||
thread_t *th = chThdCreateFromHeap(NULL, THD_WORKING_AREA_SIZE(2*1024), "TRA", NORMALPRIO, trackingThread, NULL);
|
||||
if(!th) {
|
||||
// Print startup error, do not start watchdog for this thread
|
||||
TRACE_ERROR("TRAC > Could not startup thread (not enough memory available)");
|
||||
} else {
|
||||
register_thread_at_wdg(&trac_conf);
|
||||
trac_conf.wdg_timeout = chVTGetSystemTimeX() + S2ST(1);
|
||||
chThdSleepMilliseconds(300); // Wait a little bit until tracking manager has initialized first dataset
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Without position module, GPS sampling would be a waste a energy, so it
|
||||
* should be kept switched off. Due to this reason the tracking manager thread
|
||||
* is blocked by the blockThread variable. This prevents the tracking manager
|
||||
* to run when no position module is enabled. This function should be called
|
||||
* as one position thread is active. This function may be called multiple times.
|
||||
*/
|
||||
void setTrackingManagerRunning(void)
|
||||
{
|
||||
blockThread = false;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ void waitForNewTrackPoint(void);
|
|||
trackPoint_t* getLastTrackPoint(void);
|
||||
void getNextLogTrackPoint(trackPoint_t* log);
|
||||
void init_tracking_manager(void);
|
||||
void setTrackingManagerRunning(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue