summaryrefslogtreecommitdiff
path: root/moticam.c
diff options
context:
space:
mode:
authorNicolas Schodet2019-11-10 13:53:08 +0100
committerNicolas Schodet2019-11-14 00:41:59 +0100
commit1bdf71f47e5f9f75308c5fef664814c2c125f305 (patch)
treeb60fa6352cff7864d0474c24dab049d000818216 /moticam.c
parent4832457478133cd9610a17070b07d1abbdd45443 (diff)
Rework device API, drop raw output
Diffstat (limited to 'moticam.c')
-rw-r--r--moticam.c165
1 files changed, 118 insertions, 47 deletions
diff --git a/moticam.c b/moticam.c
index 2e46144..03dccd6 100644
--- a/moticam.c
+++ b/moticam.c
@@ -25,6 +25,7 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
+#include <stdbool.h>
#include "device.h"
#include "image.h"
@@ -36,18 +37,17 @@
struct moticam_device {
struct device device;
libusb_device_handle *handle;
- int width;
- int height;
- bool raw;
+ double exposure_ms;
+ double gain;
size_t rawbuffer_size;
uint8_t *rawbuffer;
- uint32_t *buffer;
+ struct device_image image;
};
static char *
moticam_usb_poll(struct libusb_device_descriptor *desc);
static struct device *
-moticam_usb_open(libusb_device *usb_device, struct options *options);
+moticam_usb_open(libusb_device *usb_device);
const struct device_driver moticam_device_driver = {
"Moticam USB cameras",
@@ -55,6 +55,25 @@ const struct device_driver moticam_device_driver = {
&moticam_usb_open,
};
+static const struct device_info_resolution moticam_device_info_resolution[] = {
+ { 2048, 1536 },
+ { 1024, 768 },
+ { 512, 384 },
+};
+
+static const struct device_info moticam_device_info = {
+ .exposure_min_ms = 1,
+ .exposure_max_ms = 5000,
+ .exposure_default_ms = 100,
+ .exposure_step_ms = 1,
+ .gain_min = 0.33,
+ .gain_max = 42.66,
+ .gain_default = 1,
+ .gain_step = 1.0 / 24,
+ .resolutions = 3,
+ .resolution = moticam_device_info_resolution,
+};
+
static void
moticam_control_vendor(struct device *device, uint16_t wValue,
const uint8_t *data, int data_cnt)
@@ -75,14 +94,14 @@ moticam_control_vendor_w(struct device *device, uint16_t wValue,
}
static void
-moticam_reset(struct device *device)
+moticam_control_reset(struct device *device)
{
moticam_control_vendor_w(device, 0xba00, 0x0000);
moticam_control_vendor_w(device, 0xba00, 0x0001);
}
static void
-moticam_set_exposure(struct device *device, double exposure_ms)
+moticam_control_exposure(struct device *device, double exposure_ms)
{
int exposure_w = exposure_ms * 12.82;
if (exposure_w < 0x000c)
@@ -93,7 +112,7 @@ moticam_set_exposure(struct device *device, double exposure_ms)
}
static void
-moticam_set_gain(struct device *device, double gain)
+moticam_control_gain(struct device *device, double gain)
{
double gmin, gmax;
int xmin, xmax;
@@ -129,7 +148,7 @@ moticam_set_gain(struct device *device, double gain)
}
static void
-moticam_set_resolution(struct device *device, int width, int height)
+moticam_control_resolution(struct device *device, int width, int height)
{
static const uint8_t control_init[] = {
0x00, 0x14, 0x00, 0x20, 0x05, 0xff, 0x07, 0xff };
@@ -160,11 +179,69 @@ moticam_set_resolution(struct device *device, int width, int height)
}
}
-static const uint8_t *
-moticam_read_raw(struct device *device, size_t *size)
+static const struct device_info *
+moticam_get_info(struct device *device)
+{
+ return &moticam_device_info;
+}
+
+static void
+moticam_set_exposure(struct device *device, double exposure_ms)
+{
+ struct moticam_device *mdev = (struct moticam_device *) device;
+ mdev->exposure_ms = exposure_ms;
+ if (mdev->image.pixels)
+ moticam_control_exposure(device, exposure_ms);
+}
+
+static void
+moticam_set_gain(struct device *device, double gain)
+{
+ struct moticam_device *mdev = (struct moticam_device *) device;
+ mdev->gain = gain;
+ if (mdev->image.pixels)
+ moticam_control_gain(device, gain);
+}
+
+static void
+moticam_set_resolution(struct device *device, int width, int height,
+ int stride)
+{
+ struct moticam_device *mdev = (struct moticam_device *) device;
+ /* Release previous configuration. */
+ if (mdev->image.pixels) {
+ free(mdev->rawbuffer);
+ free(mdev->image.pixels);
+ moticam_control_exposure(&mdev->device, 30.0);
+ }
+ /* Choose stride. */
+ if (!stride)
+ stride = width * sizeof(uint32_t);
+ assert(stride >= width * sizeof(uint32_t));
+ /* Store parameters. */
+ mdev->image.width = width;
+ mdev->image.height = height;
+ mdev->image.stride = stride;
+ /* Prepare sizes and buffers, request an extra frame to read the zero
+ * length packet. */
+ int image_size = width * height;
+ int frame_size = 16384;
+ mdev->rawbuffer_size = (image_size + frame_size)
+ / frame_size * frame_size;
+ mdev->rawbuffer = utils_malloc(mdev->rawbuffer_size);
+ mdev->image.pixels = utils_malloc(stride * height);
+ /* Configure camera. */
+ moticam_control_gain(&mdev->device, mdev->gain);
+ moticam_control_resolution(&mdev->device, width, height);
+ moticam_control_exposure(&mdev->device, mdev->exposure_ms);
+ utils_delay_us(100000);
+}
+
+static bool
+moticam_read_raw(struct device *device)
{
struct moticam_device *mdev = (struct moticam_device *) device;
- int image_size = mdev->width * mdev->height;
+ int image_size = mdev->image.width * mdev->image.height;
int transfered = 0;
int r = libusb_bulk_transfer(mdev->handle, 0x83, mdev->rawbuffer,
mdev->rawbuffer_size, &transfered, 0);
@@ -172,23 +249,21 @@ moticam_read_raw(struct device *device, size_t *size)
utils_fatal("can not read data: %s", libusb_strerror(r));
if (transfered != image_size) {
utils_warning("bad image size (%d), drop", transfered);
- return NULL;
+ return false;
} else {
- *size = mdev->rawbuffer_size;
- return mdev->rawbuffer;
+ return true;
}
}
-static const uint32_t *
+static const struct device_image *
moticam_read(struct device *device)
{
struct moticam_device *mdev = (struct moticam_device *) device;
- size_t rawbuffer_size;
- const uint8_t *rawbuffer = moticam_read_raw(device, &rawbuffer_size);
- if (rawbuffer) {
- image_bayer2argb(rawbuffer, mdev->buffer, mdev->width,
- mdev->height);
- return mdev->buffer;
+ assert(mdev->image.pixels);
+ if (moticam_read_raw(device)) {
+ image_bayer2argb(mdev->rawbuffer, mdev->image.pixels, mdev->image.width,
+ mdev->image.height, mdev->image.stride);
+ return &mdev->image;
} else {
return NULL;
}
@@ -198,13 +273,14 @@ static void
moticam_close(struct device *device)
{
struct moticam_device *mdev = (struct moticam_device *) device;
- moticam_set_exposure(device, 0.0);
- moticam_set_exposure(device, 0.0);
- moticam_set_exposure(device, 0.0);
+ moticam_control_exposure(device, 0.0);
+ moticam_control_exposure(device, 0.0);
+ moticam_control_exposure(device, 0.0);
libusb_close(mdev->handle);
- free(mdev->rawbuffer);
- if (mdev->buffer)
- free(mdev->buffer);
+ if (mdev->image.pixels) {
+ free(mdev->rawbuffer);
+ free(mdev->image.pixels);
+ }
free(device);
}
@@ -218,38 +294,33 @@ moticam_usb_poll(struct libusb_device_descriptor *desc)
}
static struct device *
-moticam_usb_open(libusb_device *usb_device, struct options *options)
+moticam_usb_open(libusb_device *usb_device)
{
/* Create context. */
struct moticam_device *mdev =
utils_malloc(sizeof(struct moticam_device));
- mdev->device.read_raw = &moticam_read_raw;
- mdev->device.read = &moticam_read;
+ mdev->device.get_info = &moticam_get_info;
mdev->device.set_exposure = &moticam_set_exposure;
mdev->device.set_gain = &moticam_set_gain;
+ mdev->device.set_resolution = &moticam_set_resolution;
+ mdev->device.read = &moticam_read;
mdev->device.close = &moticam_close;
mdev->handle = NULL;
- mdev->width = options->width;
- mdev->height = options->height;
- mdev->raw = options->raw;
- int image_size = mdev->width * mdev->height;
- int frame_size = 16384;
- /* Request an extra frame to read the zero length packet. */
- mdev->rawbuffer_size = (image_size + frame_size) / frame_size * frame_size;
- mdev->rawbuffer = utils_malloc(mdev->rawbuffer_size);
- mdev->buffer = mdev->raw ? NULL :
- utils_malloc(mdev->width * mdev->height * sizeof(uint32_t));
+ mdev->exposure_ms = moticam_device_info.exposure_default_ms;
+ mdev->gain = moticam_device_info.gain_default;
+ mdev->rawbuffer_size = 0;
+ mdev->rawbuffer = NULL;
+ mdev->image.width = 0;
+ mdev->image.height = 0;
+ mdev->image.stride = 0;
+ mdev->image.pixels = NULL;
/* Open USB device. */
int r = libusb_open(usb_device, &mdev->handle);
if (r)
utils_fatal("can not open device: %s", libusb_strerror(r));
/* Initialize camera. */
- moticam_reset(&mdev->device);
- moticam_set_gain(&mdev->device, options->gain);
- moticam_set_exposure(&mdev->device, 30.0);
- moticam_set_resolution(&mdev->device, options->width, options->height);
- moticam_set_exposure(&mdev->device, options->exposure_ms);
- utils_delay_us(100000);
+ moticam_control_reset(&mdev->device);
+ moticam_control_exposure(&mdev->device, 30.0);
/* Done. */
return &mdev->device;
}