File ArducamCamera.c
File List > arducam > ArducamCamera.c
Go to the documentation of this file
/*
* This file is part of the Arducam SPI Camera project.
*
* Copyright 2021 Arducam Technology co., Ltd. All Rights Reserved.
*
* This work is licensed under the MIT license, see the file LICENSE for
* details.
*
*/
#include "ArducamCamera.h"
#include "Platform.h"
#include "ns_camera.h"
#include "ns_core.h"
#define NS_CAMERA_MAX_WAIT 1500
#define ARDUCHIP_FRAMES 0x01
#define ARDUCHIP_TEST1 0x00 // TEST register
#define ARDUCHIP_FIFO 0x04 // FIFO and I2C control
#define ARDUCHIP_FIFO_2 0x07 // FIFO and I2C control
#define FIFO_CLEAR_ID_MASK 0x01
#define FIFO_START_MASK 0x02
#define FIFO_RDPTR_RST_MASK 0x10
#define FIFO_WRPTR_RST_MASK 0x20
#define FIFO_CLEAR_MASK 0x80
#define ARDUCHIP_TRIG 0x44 // Trigger source
#define VSYNC_MASK 0x01
#define SHUTTER_MASK 0x02
#define CAP_DONE_MASK 0x04
#define FIFO_SIZE1 0x45 // Camera write FIFO size[7:0] for burst to read
#define FIFO_SIZE2 0x46 // Camera write FIFO size[15:8]
#define FIFO_SIZE3 0x47 // Camera write FIFO size[18:16]
#define SENSOR_DATA 0x48 // Camera write FIFO size[18:16]
#define BURST_FIFO_READ 0x3C // Burst FIFO read operation
#define SINGLE_FIFO_READ 0x3D // Single FIFO read operation
#if defined(__MSP430G2553__)
#define PREVIEW_BUF_LEN 50
#else
#define PREVIEW_BUF_LEN 255
#endif
#define CAPRURE_MAX_NUM 0xff
#define CAM_REG_POWER_CONTROL 0X02
#define CAM_REG_SENSOR_RESET 0X07
#define CAM_REG_FORMAT 0X20
#define CAM_REG_CAPTURE_RESOLUTION 0X21
#define CAM_REG_BRIGHTNESS_CONTROL 0X22
#define CAM_REG_CONTRAST_CONTROL 0X23
#define CAM_REG_SATURATION_CONTROL 0X24
#define CAM_REG_EV_CONTROL 0X25
#define CAM_REG_WHILEBALANCE_MODE_CONTROL 0X26
#define CAM_REG_COLOR_EFFECT_CONTROL 0X27
#define CAM_REG_SHARPNESS_CONTROL 0X28
#define CAM_REG_AUTO_FOCUS_CONTROL 0X29
#define CAM_REG_IMAGE_QUALITY 0x2A
#define CAM_REG_EXPOSURE_GAIN_WHILEBALANCE_CONTROL 0X30
#define CAM_REG_MANUAL_GAIN_BIT_9_8 0X31
#define CAM_REG_MANUAL_GAIN_BIT_7_0 0X32
#define CAM_REG_MANUAL_EXPOSURE_BIT_19_16 0X33
#define CAM_REG_MANUAL_EXPOSURE_BIT_15_8 0X34
#define CAM_REG_MANUAL_EXPOSURE_BIT_7_0 0X35
#define CAM_REG_BURST_FIFO_READ_OPERATION 0X3C
#define CAM_REG_SINGLE_FIFO_READ_OPERATION 0X3D
#define CAM_REG_SENSOR_ID 0x40
#define CAM_REG_YEAR_ID 0x41
#define CAM_REG_MONTH_ID 0x42
#define CAM_REG_DAY_ID 0x43
#define CAM_REG_SENSOR_STATE 0x44
#define CAM_REG_FPGA_VERSION_NUMBER 0x49
#define CAM_REG_DEBUG_DEVICE_ADDRESS 0X0A
#define CAM_REG_DEBUG_REGISTER_HIGH 0X0B
#define CAM_REG_DEBUG_REGISTER_LOW 0X0C
#define CAM_REG_DEBUG_REGISTER_VALUE 0X0D
#define CAM_REG_DEBUG_REGISTER_VALUE_H 0X0E
#define CAM_I2C_READ_MODE (1 << 0)
#define CAM_REG_SENSOR_STATE_IDLE (1 << 1)
#define CAM_SENSOR_RESET_ENABLE (1 << 6)
#define CAM_FORMAT_BASICS (0 << 0)
#define CAM_SET_CAPTURE_MODE (0 << 7)
#define CAM_SET_VIDEO_MODE (1 << 7)
#define SET_WHILEBALANCE 0X02
#define SET_EXPOSURE 0X01
#define SET_GAIN 0X00
#define CAMERA_TYPE_NUMBER 2
// #define FORMAT_NONE 0X00
// #define FORMAT_JPEG 0X01
// #define FORMAT_RGB 0X02
// #define FORMAT_YUV 0X03
#define RESOLUTION_160X120 (1 << 0)
#define RESOLUTION_320X240 (1 << 1)
#define RESOLUTION_640X480 (1 << 2)
#define RESOLUTION_800X600 (1 << 3)
#define RESOLUTION_1280X720 (1 << 4)
#define RESOLUTION_1280X960 (1 << 5)
#define RESOLUTION_1600X1200 (1 << 6)
#define RESOLUTION_1920X1080 (1 << 7)
#define RESOLUTION_2048X1536 (1 << 8)
#define RESOLUTION_2592X1944 (1 << 9)
#define RESOLUTION_320x320 (1 << 10)
#define RESOLUTION_128x128 (1 << 11)
#define RESOLUTION_96x96 (1 << 12)
#define SPECIAL_NORMAL (0 << 0)
#define SPECIAL_BLUEISH (1 << 0)
#define SPECIAL_REDISH (1 << 1)
#define SPECIAL_BW (1 << 2)
#define SPECIAL_SEPIA (1 << 3)
#define SPECIAL_NEGATIVE (1 << 4)
#define SPECIAL_GREENISH (1 << 5)
#define SPECIAL_OVEREXPOSURE (1 << 6)
#define SPECIAL_SOLARIZE (1 << 7)
#define SPECIAL_YELLOWISH (1 << 8)
union SdkInfo currentSDK = {
.sdkInfo.year = 24,
.sdkInfo.month = 6,
.sdkInfo.day = 18,
.sdkInfo.version = 0x020C, // V2.0.11 H bit[11:8] M bit[7:4] L bit[3:0]
};
struct cameraDefaultState {
uint8_t cameraDefaultFormat;
uint8_t cameraDefaultResolution;
};
void setCapture(ArducamCamera *camera);
void csHigh(ArducamCamera *camera);
void csLow(ArducamCamera *camera);
void writeReg(ArducamCamera *camera, uint8_t addr, uint8_t val);
uint8_t readReg(ArducamCamera *camera, uint8_t addr);
uint8_t busRead(ArducamCamera *camera, int address);
uint8_t busWrite(ArducamCamera *camera, int address, int value);
void clearFifoFlag(ArducamCamera *camera);
uint32_t readFifoLength(ArducamCamera *camera);
uint8_t getBit(ArducamCamera *camera, uint8_t addr, uint8_t bit);
void setFifoBurst(ArducamCamera *camera);
void setCapture(ArducamCamera *camera);
uint32_t waitI2cIdle(ArducamCamera *camera);
uint32_t imageAvailable(ArducamCamera *camera);
void flushFifo(ArducamCamera *camera);
void startCapture(ArducamCamera *camera);
struct CameraInfo CameraInfo_5MP = {
.cameraId = "5MP",
.supportResolution = RESOLUTION_320x320 | RESOLUTION_128x128 | RESOLUTION_96x96 |
RESOLUTION_320X240 | RESOLUTION_640X480 | RESOLUTION_1280X720 |
RESOLUTION_1600X1200 | RESOLUTION_1920X1080 | RESOLUTION_2592X1944,
.supportSpecialEffects = SPECIAL_BLUEISH | SPECIAL_REDISH | SPECIAL_BW | SPECIAL_SEPIA |
SPECIAL_NEGATIVE |
SPECIAL_GREENISH /*| SPECIAL_OVEREXPOSURE | SPECIAL_SOLARIZE*/,
.exposureValueMax = 30000,
.exposureValueMin = 1,
.gainValueMax = 1023,
.gainValueMin = 1,
.supportFocus = TRUE,
.supportSharpness = FALSE,
.deviceAddress = 0x78,
};
struct CameraInfo CameraInfo_3MP = {
.cameraId = "3MP",
.supportResolution = RESOLUTION_320x320 | RESOLUTION_128x128 | RESOLUTION_96x96 |
RESOLUTION_320X240 | RESOLUTION_640X480 | RESOLUTION_1280X720 |
RESOLUTION_1600X1200 | RESOLUTION_1920X1080 | RESOLUTION_2048X1536,
.supportSpecialEffects = SPECIAL_BLUEISH | SPECIAL_REDISH | SPECIAL_BW | SPECIAL_SEPIA |
SPECIAL_NEGATIVE | SPECIAL_GREENISH | SPECIAL_YELLOWISH,
.exposureValueMax = 30000,
.exposureValueMin = 1,
.gainValueMax = 1023,
.gainValueMin = 1,
.supportFocus = FALSE,
.supportSharpness = TRUE,
.deviceAddress = 0x78,
};
struct CameraInfo *CameraType[CAMERA_TYPE_NUMBER];
// struct cameraDefaultState DefaultState_5mp = {
// .cameraDefaultFormat = CAM_IMAGE_PIX_FMT_JPG,
// .cameraDefaultResolution = CAM_IMAGE_MODE_WQXGA2,
// };
// struct cameraDefaultState DefaultState_3mp = {
// .cameraDefaultFormat = CAM_IMAGE_PIX_FMT_JPG,
// .cameraDefaultResolution = CAM_IMAGE_MODE_QXGA,
// };
// struct cameraDefaultState* cameraDefaultInfo[CAMERA_TYPE_NUMBER];
uint8_t ov3640GainValue[] = {0x00, 0x10, 0x18, 0x30, 0x34, 0x38, 0x3b, 0x3f, 0x72, 0x74, 0x76,
0x78, 0x7a, 0x7c, 0x7e, 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6,
0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff};
void updateCameraInfo(ArducamCamera *camera) {
if (camera->cameraId == SENSOR_5MP_2 || camera->cameraId == SENSOR_3MP_2) {
camera->myCameraInfo.exposureValueMax = 0xFFFF;
camera->myCameraInfo.gainValueMax = 0xFFFF;
}
}
void cameraInit(ArducamCamera *camera) {
arducamSpiBegin();
arducamCsOutputMode(camera->csPin);
arducamSpiCsPinLow(camera->csPin);
}
void cameraGetSensorConfig(ArducamCamera *camera) {
uint8_t cameraIdx = 0;
camera->cameraId = readReg(camera, CAM_REG_SENSOR_ID);
waitI2cIdle(camera);
switch (camera->cameraId) {
case SENSOR_5MP_2:
CameraInfo_5MP.cameraId = "5MP_2";
case SENSOR_5MP_1:
cameraIdx = 0x00;
break;
case SENSOR_3MP_1:
case SENSOR_3MP_2:
cameraIdx = 0x01;
break;
}
camera->myCameraInfo = *CameraType[cameraIdx];
// camera->currentPixelFormat = cameraDefaultInfo[cameraIdx]->cameraDefaultFormat;
// camera->currentPictureMode = cameraDefaultInfo[cameraIdx]->cameraDefaultResolution;
}
CamStatus cameraBegin(ArducamCamera *camera) {
// reset cpld and camera
writeReg(camera, CAM_REG_SENSOR_RESET, CAM_SENSOR_RESET_ENABLE);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
cameraGetSensorConfig(camera);
updateCameraInfo(camera);
camera->verDateAndNumber[0] = readReg(camera, CAM_REG_YEAR_ID) & 0x3F; // year
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
// ns_lp_printf("year: %d\n", camera->verDateAndNumber[0]);
camera->verDateAndNumber[1] = readReg(camera, CAM_REG_MONTH_ID) & 0x0F; // month
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
// ns_lp_printf("month: %d\n", camera->verDateAndNumber[1]);
camera->verDateAndNumber[2] = readReg(camera, CAM_REG_DAY_ID) & 0x1F; // day
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
// ns_lp_printf("day: %d\n", camera->verDateAndNumber[2]);
camera->verDateAndNumber[3] = readReg(camera, CAM_REG_FPGA_VERSION_NUMBER) & 0xFF; // day
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
// ns_lp_printf("fpga version: %d\n", camera->verDateAndNumber[3]);
writeReg(camera, CAM_REG_DEBUG_DEVICE_ADDRESS, camera->myCameraInfo.deviceAddress);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
return CAM_ERR_SUCCESS;
}
void cameraSetCapture(ArducamCamera *camera) {
// flushFifo(camera);
clearFifoFlag(camera);
startCapture(camera);
while (getBit(camera, ARDUCHIP_TRIG, CAP_DONE_MASK) == 0)
;
camera->receivedLength = readFifoLength(camera);
camera->totalLength = camera->receivedLength;
camera->burstFirstFlag = 0;
}
uint32_t cameraImageAvailable(ArducamCamera *camera) { return camera->receivedLength; }
CamStatus cameraSetAutoFocus(ArducamCamera *camera, uint8_t val) {
writeReg(camera, CAM_REG_AUTO_FOCUS_CONTROL, val); // auto focus control
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
uint8_t cameraGetAutoFocusSta(ArducamCamera *camera) {
uint16_t sta_reg = 0x3029;
// step 1 write sta_reg
uint8_t register_high = (sta_reg >> 8) & 0xFF;
uint8_t register_low = (sta_reg)&0xFF;
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, register_high);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, register_low);
waitI2cIdle(camera);
// step 2 read real sensor register
writeReg(camera, CAM_REG_SENSOR_RESET, CAM_I2C_READ_MODE);
waitI2cIdle(camera); // Wait I2c Idle
arducamDelayMs(5); // wait read finish
// step 3 get value
return readReg(camera, SENSOR_DATA);
}
CamStatus cameraSetManualFocus(ArducamCamera *camera, uint16_t val) {
uint16_t vcm_reg_H = 0x3603;
uint16_t vcm_reg_L = 0x3602;
uint8_t register_high, register_low;
// step 1 convert val to vcm code
uint8_t code_9_4 = (val >> 4) & 0x3F;
uint8_t code_3_0 = (val << 4) & 0xF0;
// step 2 wirte high register
register_high = (vcm_reg_H >> 8) & 0xFF;
register_low = (vcm_reg_H)&0xFF;
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, register_high);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, register_low);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, code_9_4);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
// step 3 wirte low register
register_high = (vcm_reg_L >> 8) & 0xFF;
register_low = (vcm_reg_L)&0xFF;
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, register_high);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, register_low);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, code_3_0);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
return CAM_ERR_SUCCESS;
}
CamStatus
cameraTakePicture(ArducamCamera *camera, CAM_IMAGE_MODE mode, CAM_IMAGE_PIX_FMT pixel_format) {
if (camera->currentPixelFormat != pixel_format) {
camera->currentPixelFormat = pixel_format;
writeReg(camera, CAM_REG_FORMAT, pixel_format); // set the data format
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
}
if (camera->currentPictureMode != mode) {
camera->currentPictureMode = mode;
writeReg(camera, CAM_REG_CAPTURE_RESOLUTION, CAM_SET_CAPTURE_MODE | mode);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
}
setCapture(camera);
return CAM_ERR_SUCCESS;
}
CamStatus cameratakeMultiPictures(
ArducamCamera *camera, CAM_IMAGE_MODE mode, CAM_IMAGE_PIX_FMT pixel_format, uint8_t num) {
if (camera->currentPixelFormat != pixel_format) {
camera->currentPixelFormat = pixel_format;
writeReg(camera, CAM_REG_FORMAT, pixel_format); // set the data format
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
}
if (camera->currentPictureMode != mode) {
camera->currentPictureMode = mode;
writeReg(camera, CAM_REG_CAPTURE_RESOLUTION, CAM_SET_CAPTURE_MODE | mode);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
}
if (num > CAPRURE_MAX_NUM) {
num = CAPRURE_MAX_NUM;
}
writeReg(camera, ARDUCHIP_FRAMES, num);
setCapture(camera);
return CAM_ERR_SUCCESS;
}
void cameraRegisterCallback(
ArducamCamera *camera, BUFFER_CALLBACK function, uint8_t size, STOP_HANDLE handle) {
camera->callBackFunction = function;
camera->blockSize = size;
camera->handle = handle;
}
CamStatus cameraStartPreview(ArducamCamera *camera, CAM_VIDEO_MODE mode) {
// camera->cameraDataFormat = CAM_IMAGE_PIX_FMT_JPG;
camera->previewMode = TRUE;
if (!camera->callBackFunction) {
return CAM_ERR_NO_CALLBACK;
}
writeReg(camera, CAM_REG_FORMAT, CAM_IMAGE_PIX_FMT_JPG); // set jpeg format
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
writeReg(camera, CAM_REG_CAPTURE_RESOLUTION,
CAM_SET_VIDEO_MODE | mode); // set video mode
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
setCapture(camera);
return CAM_ERR_SUCCESS;
}
static uint8_t callBackBuff[PREVIEW_BUF_LEN];
void cameraCaptureThread(ArducamCamera *camera) {
if (camera->previewMode) {
uint8_t callBackLength = readBuff(camera, callBackBuff, camera->blockSize);
if (callBackLength != FALSE) {
camera->callBackFunction(callBackBuff, callBackLength);
} else {
setCapture(camera);
}
}
}
CamStatus cameraStopPreview(ArducamCamera *camera) {
if (camera->previewMode == TRUE && camera->handle != 0) {
camera->handle();
}
camera->currentPixelFormat = CAM_IMAGE_PIX_FMT_JPG;
camera->currentPictureMode = CAM_IMAGE_MODE_QVGA;
camera->previewMode = FALSE;
camera->receivedLength = 0;
camera->totalLength = 0;
writeReg(camera, CAM_REG_FORMAT, CAM_IMAGE_PIX_FMT_JPG); // set jpeg format
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetImageQuality(ArducamCamera *camera, IMAGE_QUALITY qualtiy) {
writeReg(camera, CAM_REG_IMAGE_QUALITY, qualtiy);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraReset(ArducamCamera *camera) {
writeReg(camera, CAM_REG_SENSOR_RESET, CAM_SENSOR_RESET_ENABLE);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
camera->currentPixelFormat = -1;
camera->currentPictureMode = -1;
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetAutoWhiteBalanceMode(ArducamCamera *camera, CAM_WHITE_BALANCE mode) {
writeReg(camera, CAM_REG_WHILEBALANCE_MODE_CONTROL, mode); // set Light Mode
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetAutoWhiteBalance(ArducamCamera *camera, uint8_t val) {
unsigned char symbol = 0;
if (val == TRUE) {
symbol |= 0x80;
}
symbol |= SET_WHILEBALANCE;
writeReg(camera, CAM_REG_EXPOSURE_GAIN_WHILEBALANCE_CONTROL,
symbol); // white balance control
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetAutoISOSensitive(ArducamCamera *camera, uint8_t val) {
unsigned char symbol = 0;
if (val == TRUE) {
symbol |= 0x80;
}
symbol |= SET_GAIN;
writeReg(camera, CAM_REG_EXPOSURE_GAIN_WHILEBALANCE_CONTROL,
symbol); // auto gain control
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetISOSensitivity(ArducamCamera *camera, int iso_sense) {
if (camera->cameraId == SENSOR_3MP_1) {
iso_sense = ov3640GainValue[iso_sense - 1];
}
writeReg(camera, CAM_REG_MANUAL_GAIN_BIT_9_8,
iso_sense >> 8); // set AGC VALUE
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
writeReg(camera, CAM_REG_MANUAL_GAIN_BIT_7_0, iso_sense & 0xff);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetAutoExposure(ArducamCamera *camera, uint8_t val) {
unsigned char symbol = 0;
if (val == TRUE) {
symbol |= 0x80;
}
symbol |= SET_EXPOSURE;
writeReg(camera, CAM_REG_EXPOSURE_GAIN_WHILEBALANCE_CONTROL,
symbol); // auto EXPOSURE control
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetAbsoluteExposure(ArducamCamera *camera, uint32_t exposure_time) {
// set exposure output [19:16]
writeReg(camera, CAM_REG_MANUAL_EXPOSURE_BIT_19_16, (uint8_t)((exposure_time >> 16) & 0xff));
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
// set exposure output [15:8]
writeReg(camera, CAM_REG_MANUAL_EXPOSURE_BIT_15_8, (uint8_t)((exposure_time >> 8) & 0xff));
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
// set exposure output [7:0]
writeReg(camera, CAM_REG_MANUAL_EXPOSURE_BIT_7_0, (uint8_t)(exposure_time & 0xff));
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed");
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetColorEffect(ArducamCamera *camera, CAM_COLOR_FX effect) {
writeReg(camera, CAM_REG_COLOR_EFFECT_CONTROL, effect); // set effect
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetSaturation(ArducamCamera *camera, CAM_STAURATION_LEVEL level) {
writeReg(camera, CAM_REG_SATURATION_CONTROL, level); // set Saturation Level
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetEV(ArducamCamera *camera, CAM_EV_LEVEL level) {
// set Exposure Compensation Level
writeReg(camera, CAM_REG_EV_CONTROL, level);
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetContrast(ArducamCamera *camera, CAM_CONTRAST_LEVEL level) {
writeReg(camera, CAM_REG_CONTRAST_CONTROL, level); // set Contrast Level
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetSharpness(ArducamCamera *camera, CAM_SHARPNESS_LEVEL level) {
writeReg(camera, CAM_REG_SHARPNESS_CONTROL, level); // set Brightness Level
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
CamStatus cameraSetBrightness(ArducamCamera *camera, CAM_BRIGHTNESS_LEVEL level) {
writeReg(camera, CAM_REG_BRIGHTNESS_CONTROL, level); // set Brightness Level
NS_TRY_ABORT(waitI2cIdle(camera), "Camera Wait for Idle Failed"); // Wait I2c Idle
return CAM_ERR_SUCCESS;
}
void cameraFlushFifo(ArducamCamera *camera) { writeReg(camera, ARDUCHIP_FIFO_2, FIFO_CLEAR_MASK); }
void cameraStartCapture(ArducamCamera *camera) { writeReg(camera, ARDUCHIP_FIFO, FIFO_START_MASK); }
void cameraClearFifoFlag(ArducamCamera *camera) {
writeReg(camera, ARDUCHIP_FIFO, FIFO_CLEAR_ID_MASK);
}
uint32_t cameraReadFifoLength(ArducamCamera *camera) {
uint32_t len1, len2, len3, length = 0;
len1 = readReg(camera, FIFO_SIZE1);
len2 = readReg(camera, FIFO_SIZE2);
len3 = readReg(camera, FIFO_SIZE3);
length = ((len3 << 16) | (len2 << 8) | len1) & 0xffffff;
return length;
}
uint8_t cameraGetBit(ArducamCamera *camera, uint8_t addr, uint8_t bit) {
uint8_t temp;
temp = readReg(camera, addr);
temp = temp & bit;
return temp;
}
void cameraSetFifoBurst(ArducamCamera *camera) {
// arducamSpiTransfer(BURST_FIFO_READ);
}
uint8_t cameraReadByte(ArducamCamera *camera) {
uint8_t data = cameraReadReg(camera, SINGLE_FIFO_READ);
// arducamSpiCsPinLow(camera->csPin);
// arducamSpiTransfer(SINGLE_FIFO_READ);
// arducamSpiTransfer(0x00);
// data = arducamSpiTransfer(0x00);
// arducamSpiCsPinHigh(camera->csPin);
camera->receivedLength -= 1;
return data;
}
uint32_t cameraReadBuff(ArducamCamera *camera, uint8_t *buff, uint32_t length)
{
if (imageAvailable(camera) == 0 || (length == 0)) {
return 0;
}
if (camera->receivedLength < length) {
length = camera->receivedLength;
}
// TODO Read block instead
arducam_spi_read(buff, length, BURST_FIFO_READ, 1, camera->csPin);
// arducamSpiCsPinLow(camera->csPin);
// setFifoBurst(camera);
if (camera->burstFirstFlag == 0) {
camera->burstFirstFlag = 1;
// arducamSpiTransfer(0x00);
}
// #ifndef arducamSpiReadBlock
// for (uint32_t count = 0; count < length; count++) {
// buff[count] = arducamSpiTransfer(0x00);
// }
// #else
// arducamSpiReadBlock(buff, length);
// #endif
// arducamSpiCsPinHigh(camera->csPin);
camera->receivedLength -= length;
return length;
}
void cameraWriteReg(ArducamCamera *camera, uint8_t addr, uint8_t val) {
busWrite(camera, addr | 0x80, val);
}
uint8_t cameraReadReg(ArducamCamera *camera, uint8_t addr) {
uint8_t data;
data = busRead(camera, addr & 0x7F);
// ns_lp_printf("addr %d data: %d\n", addr, data);
return data;
}
uint8_t cameraBusWrite(ArducamCamera *camera, int address, int value) {
// arducamSpiCsPinLow(camera->csPin);
// arducamSpiTransfer(address);
// arducamSpiTransfer(value);
// arducamSpiCsPinHigh(camera->csPin);
arducam_spi_write(&value, 1, address, 1, camera->csPin);
// arducamDelayMs(1);
return 1;
}
void cameraCsHigh(ArducamCamera *camera) { arducamSpiCsPinHigh(camera->csPin); }
void cameraCsLow(ArducamCamera *camera) { arducamSpiCsPinLow(camera->csPin); }
uint8_t cameraBusRead(ArducamCamera *camera, int address) {
uint8_t value[2] = {0, 0};
uint64_t long_address = address;
arducam_spi_read(value, 2, long_address, 1, camera->csPin);
// arducamSpiCsPinLow(camera->csPin);
// arducamSpiTransfer(address);
// value = arducamSpiTransfer(0x00);
// value = arducamSpiTransfer(0x00);
// arducamSpiCsPinHigh(camera->csPin);
return value[1];
}
uint32_t cameraWaitI2cIdle(ArducamCamera *camera) {
uint32_t count = NS_CAMERA_MAX_WAIT;
while ((readReg(camera, CAM_REG_SENSOR_STATE) & 0X03) != CAM_REG_SENSOR_STATE_IDLE) {
arducamDelayMs(2);
count--;
if (count == 0) {
return NS_STATUS_FAILURE;
}
}
return NS_STATUS_SUCCESS;
}
uint8_t cameraHeartBeat(ArducamCamera *camera) {
return (readReg(camera, CAM_REG_SENSOR_STATE) & 0X03) == CAM_REG_SENSOR_STATE_IDLE;
}
void cameraDebugWriteRegister(ArducamCamera *camera, uint8_t *buff) {
uint8_t register_high = buff[0];
uint8_t register_low = buff[1];
uint8_t value = buff[2];
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, register_high);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, register_low);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, value);
}
void cameraLowPowerOn(ArducamCamera *camera) {
if ((camera->cameraId == SENSOR_5MP_2) || (camera->cameraId == SENSOR_3MP_2)) {
uint16_t reg1 = 0x0028;
uint16_t data1 = 0xD000;
uint16_t reg2 = 0x002A;
uint16_t data2 = 0x107E;
uint16_t reg3 = 0x0F12;
uint16_t data3 = 0x0001;
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, (reg1 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, (reg1)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE_H, (data1 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, (data1)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, (reg2 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, (reg2)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE_H, (data2 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, (data2)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, (reg3 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, (reg3)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE_H, (data3 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, (data3)&0xFF);
waitI2cIdle(camera);
} else {
writeReg(camera, CAM_REG_POWER_CONTROL, 0X07);
}
}
void cameraLowPowerOff(ArducamCamera *camera) {
if ((camera->cameraId == SENSOR_5MP_2) || (camera->cameraId == SENSOR_3MP_2)) {
uint16_t reg1 = 0x0028;
uint16_t data1 = 0xD000;
uint16_t reg2 = 0x002A;
uint16_t data2 = 0x107E;
uint16_t reg3 = 0x0F12;
uint16_t data3 = 0x0000;
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, (reg1 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, (reg1)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE_H, (data1 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, (data1)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, (reg2 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, (reg2)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE_H, (data2 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, (data2)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_HIGH, (reg3 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_LOW, (reg3)&0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE_H, (data3 >> 8) & 0xFF);
waitI2cIdle(camera);
writeReg(camera, CAM_REG_DEBUG_REGISTER_VALUE, (data3)&0xFF);
waitI2cIdle(camera);
} else {
writeReg(camera, CAM_REG_POWER_CONTROL, 0X05);
}
}
CamStatus reset(ArducamCamera *camera) { return camera->arducamCameraOp->reset(camera); }
CamStatus begin(ArducamCamera *camera) { return camera->arducamCameraOp->begin(camera); }
CamStatus takePicture(ArducamCamera *camera, CAM_IMAGE_MODE mode, CAM_IMAGE_PIX_FMT pixel_format) {
return camera->arducamCameraOp->takePicture(camera, mode, pixel_format);
}
CamStatus takeMultiPictures(
ArducamCamera *camera, CAM_IMAGE_MODE mode, CAM_IMAGE_PIX_FMT pixel_format, uint8_t num) {
return camera->arducamCameraOp->takeMultiPictures(camera, mode, pixel_format, num);
}
CamStatus startPreview(ArducamCamera *camera, CAM_VIDEO_MODE mode) {
return camera->arducamCameraOp->startPreview(camera, mode);
}
void captureThread(ArducamCamera *camera) { camera->arducamCameraOp->captureThread(camera); }
CamStatus stopPreview(ArducamCamera *camera) {
return camera->arducamCameraOp->stopPreview(camera);
}
CamStatus setAutoExposure(ArducamCamera *camera, uint8_t val) {
return camera->arducamCameraOp->setAutoExposure(camera, val);
}
CamStatus setAbsoluteExposure(ArducamCamera *camera, uint32_t val) {
return camera->arducamCameraOp->setAbsoluteExposure(camera, val);
}
CamStatus setAutoISOSensitive(ArducamCamera *camera, uint8_t val) {
return camera->arducamCameraOp->setAutoISOSensitive(camera, val);
}
CamStatus setISOSensitivity(ArducamCamera *camera, int iso_sense) {
return camera->arducamCameraOp->setISOSensitivity(camera, iso_sense);
}
CamStatus setAutoWhiteBalance(ArducamCamera *camera, uint8_t val) {
return camera->arducamCameraOp->setAutoWhiteBalance(camera, val);
}
CamStatus setAutoWhiteBalanceMode(ArducamCamera *camera, CAM_WHITE_BALANCE mode) {
return camera->arducamCameraOp->setAutoWhiteBalanceMode(camera, mode);
}
CamStatus setColorEffect(ArducamCamera *camera, CAM_COLOR_FX effect) {
return camera->arducamCameraOp->setColorEffect(camera, effect);
}
CamStatus setAutoFocus(ArducamCamera *camera, uint8_t val) {
return camera->arducamCameraOp->setAutoFocus(camera, val);
}
uint8_t getAutoFocusSta(ArducamCamera *camera) {
return camera->arducamCameraOp->getAutoFocusSta(camera);
}
CamStatus setManualFocus(ArducamCamera *camera, uint16_t val) {
return camera->arducamCameraOp->setManualFocus(camera, val);
}
CamStatus setSaturation(ArducamCamera *camera, CAM_STAURATION_LEVEL level) {
return camera->arducamCameraOp->setSaturation(camera, level);
}
CamStatus setEV(ArducamCamera *camera, CAM_EV_LEVEL level) {
return camera->arducamCameraOp->setEV(camera, level);
}
CamStatus setContrast(ArducamCamera *camera, CAM_CONTRAST_LEVEL level) {
return camera->arducamCameraOp->setContrast(camera, level);
}
CamStatus setBrightness(ArducamCamera *camera, CAM_BRIGHTNESS_LEVEL level) {
return camera->arducamCameraOp->setBrightness(camera, level);
}
CamStatus setSharpness(ArducamCamera *camera, CAM_SHARPNESS_LEVEL level) {
return camera->arducamCameraOp->setSharpness(camera, level);
}
uint32_t readBuff(ArducamCamera *camera, uint8_t *buff, uint32_t length) {
return camera->arducamCameraOp->readBuff(camera, buff, length);
}
uint8_t readByte(ArducamCamera *camera) { return camera->arducamCameraOp->readByte(camera); }
void debugWriteRegister(ArducamCamera *camera, uint8_t *buff) {
camera->arducamCameraOp->debugWriteRegister(camera, buff);
}
void registerCallback(
ArducamCamera *camera, BUFFER_CALLBACK function, uint8_t blockSize, STOP_HANDLE handle) {
camera->arducamCameraOp->registerCallback(camera, function, blockSize, handle);
}
void lowPowerOn(ArducamCamera *camera) { camera->arducamCameraOp->lowPowerOn(camera); }
void lowPowerOff(ArducamCamera *camera) { camera->arducamCameraOp->lowPowerOff(camera); }
void csHigh(ArducamCamera *camera) { camera->arducamCameraOp->csHigh(camera); }
void csLow(ArducamCamera *camera) { camera->arducamCameraOp->csLow(camera); }
void writeReg(ArducamCamera *camera, uint8_t addr, uint8_t val) {
camera->arducamCameraOp->writeReg(camera, addr, val);
}
uint8_t readReg(ArducamCamera *camera, uint8_t addr) {
return camera->arducamCameraOp->readReg(camera, addr);
}
uint8_t busRead(ArducamCamera *camera, int address) {
return camera->arducamCameraOp->busRead(camera, address);
}
uint8_t busWrite(ArducamCamera *camera, int address, int value) {
return camera->arducamCameraOp->busWrite(camera, address, value);
}
void startCapture(ArducamCamera *camera) { camera->arducamCameraOp->startCapture(camera); }
void clearFifoFlag(ArducamCamera *camera) { camera->arducamCameraOp->clearFifoFlag(camera); }
uint32_t readFifoLength(ArducamCamera *camera) {
return camera->arducamCameraOp->readFifoLength(camera);
}
uint8_t getBit(ArducamCamera *camera, uint8_t addr, uint8_t bit) {
return camera->arducamCameraOp->getBit(camera, addr, bit);
}
void setFifoBurst(ArducamCamera *camera) { camera->arducamCameraOp->setFifoBurst(camera); }
void setCapture(ArducamCamera *camera) { camera->arducamCameraOp->setCapture(camera); }
uint32_t waitI2cIdle(ArducamCamera *camera) { return camera->arducamCameraOp->waitI2cIdle(camera); }
uint32_t imageAvailable(ArducamCamera *camera) {
return camera->arducamCameraOp->imageAvailable(camera);
}
void flushFifo(ArducamCamera *camera) { camera->arducamCameraOp->flushFifo(camera); }
CamStatus setImageQuality(ArducamCamera *camera, IMAGE_QUALITY qualtiy) {
return camera->arducamCameraOp->setImageQuality(camera, qualtiy);
}
const struct CameraOperations ArducamcameraOperations = {
.reset = cameraReset,
.begin = cameraBegin,
.takePicture = cameraTakePicture,
.takeMultiPictures = cameratakeMultiPictures,
.startPreview = cameraStartPreview,
.captureThread = cameraCaptureThread,
.stopPreview = cameraStopPreview,
.setAutoExposure = cameraSetAutoExposure,
.setAbsoluteExposure = cameraSetAbsoluteExposure,
.setAutoISOSensitive = cameraSetAutoISOSensitive,
.setISOSensitivity = cameraSetISOSensitivity,
.setAutoWhiteBalance = cameraSetAutoWhiteBalance,
.setAutoWhiteBalanceMode = cameraSetAutoWhiteBalanceMode,
.setColorEffect = cameraSetColorEffect,
.setAutoFocus = cameraSetAutoFocus,
.getAutoFocusSta = cameraGetAutoFocusSta,
.setManualFocus = cameraSetManualFocus,
.setSaturation = cameraSetSaturation,
.setEV = cameraSetEV,
.setContrast = cameraSetContrast,
.setBrightness = cameraSetBrightness,
.setSharpness = cameraSetSharpness,
.registerCallback = cameraRegisterCallback,
.imageAvailable = cameraImageAvailable,
.csHigh = cameraCsHigh,
.csLow = cameraCsLow,
.readBuff = cameraReadBuff,
.readByte = cameraReadByte,
.debugWriteRegister = cameraDebugWriteRegister,
.writeReg = cameraWriteReg,
.readReg = cameraReadReg,
.busRead = cameraBusRead,
.busWrite = cameraBusWrite,
.flushFifo = cameraFlushFifo,
.startCapture = cameraStartCapture,
.clearFifoFlag = cameraClearFifoFlag,
.readFifoLength = cameraReadFifoLength,
.getBit = cameraGetBit,
.setFifoBurst = cameraSetFifoBurst,
.setCapture = cameraSetCapture,
.waitI2cIdle = cameraWaitI2cIdle,
.lowPowerOn = cameraLowPowerOn,
.lowPowerOff = cameraLowPowerOff,
.setImageQuality = cameraSetImageQuality,
};
extern ArducamCamera camera;
ArducamCamera createArducamCamera(int CS) {
// ArducamCamera camera;
CameraType[0] = &CameraInfo_5MP;
CameraType[1] = &CameraInfo_3MP;
// cameraDefaultInfo[0] = &DefaultState_5mp;
// cameraDefaultInfo[1] = &DefaultState_3mp;
camera.cameraId = FALSE;
camera.currentPixelFormat = CAM_IMAGE_PIX_FMT_NONE;
camera.currentPictureMode = CAM_IMAGE_MODE_NONE;
camera.burstFirstFlag = FALSE;
camera.previewMode = FALSE;
camera.csPin = CS;
camera.arducamCameraOp = &ArducamcameraOperations;
camera.currentSDK = ¤tSDK;
cameraInit(&camera);
return camera;
}