uart

Dependencies:   MAX32620FTHR USBDevice

Files at this revision

API Documentation at this revision

Comitter:
rsjawale24
Date:
Sun Oct 16 15:35:01 2022 +0000
Commit message:
ok

Changed in this revision

MAX32620FTHR.lib Show annotated file Show diff for this revision Revisions of this file
USBDevice.lib Show annotated file Show diff for this revision Revisions of this file
cmd.cpp Show annotated file Show diff for this revision Revisions of this file
cmd.h Show annotated file Show diff for this revision Revisions of this file
config.h Show annotated file Show diff for this revision Revisions of this file
controller.cpp Show annotated file Show diff for this revision Revisions of this file
controller.h Show annotated file Show diff for this revision Revisions of this file
gesture.c Show annotated file Show diff for this revision Revisions of this file
gesture_common.h Show annotated file Show diff for this revision Revisions of this file
gesture_config.h Show annotated file Show diff for this revision Revisions of this file
gesture_init.c Show annotated file Show diff for this revision Revisions of this file
gesture_lib.h Show annotated file Show diff for this revision Revisions of this file
img_utils.c Show annotated file Show diff for this revision Revisions of this file
img_utils.h Show annotated file Show diff for this revision Revisions of this file
interface.cpp Show annotated file Show diff for this revision Revisions of this file
interface.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
readme.txt Show annotated file Show diff for this revision Revisions of this file
tracking.c Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r c62425b2f286 MAX32620FTHR.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/MAX32620FTHR.lib	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/teams/MaximIntegrated/code/MAX32620FTHR/#7fb8d4388fe1
diff -r 000000000000 -r c62425b2f286 USBDevice.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/USBDevice.lib	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,1 @@
+https://os.mbed.com/users/psionprime/code/USBDevice/#6ef9c5c0250e
diff -r 000000000000 -r c62425b2f286 cmd.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd.cpp	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,283 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "cmd.h"
+#include <stdlib.h>
+#include <string.h>
+#include "USBSerial.h"
+#include "controller.h"
+#include "interface.h"
+#include "gesture_lib.h"
+#include "config.h"
+
+extern const char *version_string;
+
+#if ENABLE_USER_FRAMES
+extern uint32_t userDataFrameFlag;
+extern int user_pixels[60];
+int cmd_frame(char *toks[], const unsigned int tokCount);
+#endif
+
+#if USE_UART_INTERFACE
+extern Serial *serial;
+#else
+extern USBSerial *serial;
+#endif
+
+commandTable cmdTable[] =
+{
+  {"ping","Ping the processor.", cmd_ping},
+  {"help","Display help.", cmd_help},
+  {"ver","Display firmware version", cmd_ver},
+  {"reg", "reg <read/write> <addr> <num/value>. Read or write to a device register.", cmd_reg},
+  {"stream", "stream <on/off> [nopixels]. Enable data streaming mode. Use nopixels parameter to suppress pixel data.", cmd_stream},
+  {"forcecal", "Force bias calibration (tracking mode).", cmd_force_tracking_cal},
+  {"reset", "reset device register settings.", cmd_reset},
+  {"poll", "Request gesture results", cmd_poll},
+  {CMD_TABLE_END, "", NULL} // last command must be NULL
+};
+
+// Parses command string and calls appropriate function, passing arguments
+int processCmdString(char *st)
+{
+  char *toks[MAX_TOKENS];
+  unsigned int tokCount = 0;
+  int cmdIndex = 0;
+
+  // Get tokens
+  toks[tokCount] = strtok(st, " ");
+  while((toks[tokCount] != NULL) && (tokCount < MAX_TOKENS)) {
+    tokCount++;
+    toks[tokCount] = strtok(NULL, " ");
+  }
+
+  // Find a valid command
+  cmdIndex = lookupCmd(toks[0]);
+
+  // If command found call the function
+  if(cmdIndex >= 0) {
+    return cmdTable[cmdIndex].fp(toks, tokCount);
+  }
+  return CMD_NACK;
+}
+
+// Returns index of command if found. Returns -1 if no command found
+int lookupCmd(const char *str)
+{
+  int i = 0;
+  while(1) {
+    if(strcmp(cmdTable[i].cmd, CMD_TABLE_END) == 0) // no command found
+      return -1;
+    if(strcmp(str, cmdTable[i].cmd) == 0)
+      return(i);
+    i++;
+  }
+}
+
+// Custom implementation of polling of serial port
+// to build a command string and pass it to processCmdString()
+int checkUserCmd()
+{
+  static int index = 0;
+  static char cmdString[CMD_BUFFER_SIZE];
+  int status = 0;
+  while ((*serial).readable()) {
+    char ch = (char)(*serial).getc();
+    if (ch == 0x08 && index > 0) { // got a backspace, delete the previous character
+      index--;
+    }
+    else if (ch == '\r') {/*ignore*/}
+    else if (ch == '\n') {    // Command string is ready to be processed
+      cmdString[index] = 0;   // NULL terminate the string
+      index = 0;              // reset the index
+      if (processCmdString(cmdString) == CMD_NACK) {
+        (*serial).printf("Invalid command received: %s\n", cmdString);
+      }
+      else {
+        status = 1;
+      }
+    }
+    else {
+        cmdString[index++] = ch;
+    }
+  }
+  return status;
+}
+
+int cmd_ping(char *toks[], const unsigned int tokCount)
+{
+  (*serial).puts("ack\n");
+  return CMD_ACK;
+}
+
+int cmd_ver(char *toks[], const unsigned int tokCount)
+{
+  (*serial).puts(version_string);
+  (*serial).puts("\n");
+  return CMD_ACK;
+}
+
+int cmd_help(char *toks[], const unsigned int tokCount)
+{
+  if (tokCount == 1) {
+    (*serial).printf("Commands available. Type 'help <command>' for additional info: ");
+    int i = 0;
+    while (strcmp(cmdTable[i].cmd, CMD_TABLE_END) != 0) {
+        (*serial).printf("%s ", cmdTable[i++].cmd);
+    }
+    (*serial).printf("\n");
+  }
+  else {
+    int cmdIndex = lookupCmd(toks[1]);
+    if(cmdIndex == -1) {
+      (*serial).printf("No help on that topic. Type 'help' for list of commands\n");
+    }
+    else {
+      (*serial).printf("%s: ", cmdTable[cmdIndex].cmd);
+      (*serial).printf(cmdTable[cmdIndex].helpStr);
+      (*serial).printf("\n");
+    }
+  }
+  return CMD_ACK;
+}
+
+int cmd_reg(char *toks[], const unsigned int tokCount)
+{
+  if (tokCount < 4)
+    return CMD_NACK;
+  char * cmd = toks[1];
+  uint8_t reg_addr = strtoul(toks[2], NULL, 0);
+
+  if (strcmp(cmd, "read") == 0) {
+    uint8_t num_bytes = strtoul(toks[3], NULL, 0);
+    uint8_t reg_vals[MAX_REG_READ_SIZE];
+    uint8_t output[MAX_REG_OUTPUT_LENGTH]; // char array to store string output
+    char *output_idx = (char*) output; // used to iterate through char array, must be a char for sprintf
+
+    reg_read(reg_addr, num_bytes, reg_vals);
+    for(int i=0; i<num_bytes; i++) {
+      sprintf(output_idx, "%02X", reg_vals[i]);
+      output_idx += 2; // increment by two characters
+      if (i<num_bytes-1) {
+        sprintf(output_idx++, " "); // values separated by a space
+      }
+    }
+    sprintf(output_idx, "\n"); // add a newline to indicate end-of-frame
+
+    sendDataStream(output, num_bytes * 3); // Send as a data stream for better speed, in case application is polling frame data.
+  }
+  else if (strcmp(cmd, "write") == 0) {
+    uint8_t reg_val = strtoul(toks[3], NULL, 0);
+    reg_write(reg_addr, reg_val);
+  }
+  else {
+    return CMD_NACK;
+  }
+  return CMD_ACK;
+}
+
+// Enable data streaming mode, based on hardware interrupt from the INTb pin */
+int cmd_stream(char *toks[], const unsigned int tokCount)
+{
+  if (tokCount < 2) {
+    return CMD_NACK;
+  }
+  char * enable_stream = toks[1];
+  if (strcmp(enable_stream, "on") == 0) {
+    if (tokCount > 2) {
+      char * no_data_parameter = toks[2];
+      if (strcmp(no_data_parameter, "nopixels") == 0) {
+        set_stream_on(0);
+      }
+      else {
+        return CMD_NACK;
+      }
+    }
+    else {
+      set_stream_on(1);
+    }
+  }
+  else if (strcmp(enable_stream, "off") == 0) {
+    set_stream_off();
+  }
+  else {
+    return CMD_NACK;
+  }
+  return CMD_ACK;
+}
+
+int cmd_track(char *toks[], const unsigned int tokCount)
+{
+  uint32_t cols, rows;
+  if (tokCount < 2) {
+    cols = 3;
+    rows = 2;
+  }
+  else {
+    cols = strtoul(toks[1], NULL, 0);
+    rows = strtoul(toks[2], NULL, 0);
+  }
+  return CMD_ACK;
+}
+
+int cmd_force_tracking_cal(char *toks[], const unsigned int tokCount)
+{
+  forceTrackingCalibration();
+  return CMD_ACK;
+}
+
+int cmd_reset(char *toks[], const unsigned int tokCount)
+{
+  set_default_register_settings();
+  return CMD_ACK;
+}
+
+extern GestureResult gesResult;
+extern GestureEvent latched_gesture;
+int cmd_poll(char *toks[], const unsigned int tokCount)
+{
+  (*serial).printf("%d,%d,%d,%d,%.2f,%.2f,%.2f,%d,%d,%d\n",
+    gesResult.int_placeholder,
+    gesResult.state,
+    gesResult.n_sample,
+    gesResult.maxpixel,
+    gesResult.x,
+    gesResult.y,
+    gesResult.float_placeholder,
+    gesResult.int_placeholder,
+    gesResult.int_placeholder,
+    gesResult.int_placeholder
+  );
+}
diff -r 000000000000 -r c62425b2f286 cmd.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmd.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,74 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef CMDS_H_INCLUDED
+#define CMDS_H_INCLUDED
+
+#include "mbed.h"
+
+#define MAX_TOKENS          16 /*Increased for frame read over usb. Can reduce to 10*/
+#define CMD_BUFFER_SIZE     129 /*Increased size for frame read over usb. Can reduce to 65*/
+#define CMD_TABLE_END       "NULL"
+#define CMD_ACK             0
+#define CMD_NACK            1
+
+#define MAX_REG_OUTPUT_LENGTH 512
+#define MAX_REG_READ_SIZE 256
+
+extern void enable_read_sensor_frames();
+extern void disable_read_sensor_frames();
+extern void set_stream_on(uint32_t send_pixel_data);
+extern void set_stream_off();
+extern void set_default_register_settings();
+
+typedef struct {
+    char cmd[128];
+    const char *helpStr;
+    int (*fp)(char *toks[], const unsigned int tokCount);
+}commandTable;
+
+int processCmdString(char *st);
+int lookupCmd(const char *str);
+int checkUserCmd();
+
+int cmd_ping(char *toks[], const unsigned int tokCount);
+int cmd_ver(char *toks[], const unsigned int tokCount);
+int cmd_help(char *toks[], const unsigned int tokCount);
+int cmd_reg(char *toks[], const unsigned int tokCount);
+int cmd_stream(char *toks[], const unsigned int tokCount);
+int cmd_force_tracking_cal(char *toks[], const unsigned int tokCount);
+int cmd_poll(char *toks[], const unsigned int tokCount);
+int cmd_reset(char *toks[], const unsigned int tokCount);
+#endif
diff -r 000000000000 -r c62425b2f286 config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,45 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+// Uncomment one device option
+//#define MAX25205_DEVICE
+#define MAX25405_DEVICE
+
+// Uncomment one platform option
+//#define COMPILE_FOR_MAX32630
+#define COMPILE_FOR_MAX32620
+
+// With EVKIT hardware, cannot instantiate SPI and also use I2C (these share clk and data lines on HW)
+#define USE_SPI 1
diff -r 000000000000 -r c62425b2f286 controller.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/controller.cpp	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,151 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "mbed.h"
+#include "controller.h"
+#include "config.h"
+
+static uint32_t i2c_device_addr = 0x9E; // LSB justified
+
+#define I2C_ADDR_SELECT 0
+
+void i2c_init()
+{
+  if (I2C_ADDR_SELECT) {
+    csb = 0; // set low for default i2c address
+    i2c_device_addr = 0x9E;
+  }
+  else {
+    csb = 1;
+    i2c_device_addr = 0xA0;
+  }
+  sel = 1; // set high for i2c
+}
+
+void spi_init()
+{
+  sel = 0; // set low for SPI
+}
+
+int reg_read(const uint8_t reg_addr, const uint8_t num_bytes, uint8_t reg_vals[])
+{
+  if (serial_mode == SPI_MODE) {
+    spi_read(reg_addr, num_bytes, reg_vals);
+  }
+  else {
+    i2c_read(reg_addr, num_bytes, reg_vals);
+  }
+  return 0;
+}
+
+int reg_write(const uint8_t reg_addr, const uint8_t reg_val)
+{
+  int result = (serial_mode == SPI_MODE ? spi_write(reg_addr, reg_val) : i2c_write(reg_addr, reg_val));
+  return result;
+}
+
+int i2c_read(const uint8_t reg_addr, const uint8_t num_bytes, uint8_t reg_vals[])
+{
+  #if !USE_SPI
+  char read_addr = (char)reg_addr;
+  i2c.write(i2c_device_addr, &read_addr, 1);
+  i2c.read(i2c_device_addr, (char*)reg_vals, (int)num_bytes);
+  #endif
+  return 0;
+}
+
+int i2c_write(const uint8_t reg_addr, const uint8_t reg_val)
+{
+  #if !USE_SPI
+  char data[2];
+  data[0] = reg_addr;
+  data[1] = reg_val;
+  i2c.write(i2c_device_addr, data, 2);
+  #endif
+  return 0;
+}
+
+int spi_read(const uint8_t reg_addr, const uint8_t num_bytes, uint8_t reg_vals[])
+{
+  #if USE_SPI
+  csb = 0;
+  spi.write(reg_addr);                // byte 1: register address
+  spi.write(0x80);                    // byte 2: read command 0x80
+  for(int i=0; i<num_bytes; i++) {
+    reg_vals[i] = spi.write(0x00);  // byte3: read byte
+  }
+  csb = 1;
+  #endif
+  return 0;
+}
+
+int spi_write(const uint8_t reg_addr, const uint8_t reg_val)
+{
+  #if USE_SPI
+  csb = 0;
+  spi.write(reg_addr);    // byte1: register address
+  spi.write(0x00);        // byte2: write command 0x00
+  spi.write(reg_val);     // byte3: write byte
+  csb = 1;
+  #endif
+  return 0;
+}
+
+void getSensorPixels(int pixels[], const uint8_t flip_sensor_pixels)
+{
+  unsigned char reg_vals[NUM_SENSOR_PIXELS*2];
+  reg_read(0x10, NUM_SENSOR_PIXELS*2, reg_vals);
+
+  for (int i = 0; i < NUM_SENSOR_PIXELS; i++) {
+    pixels[i] = convertTwoUnsignedBytesToInt(reg_vals[2 * i], reg_vals[2 * i + 1]);
+  }
+
+  if (flip_sensor_pixels) {
+    for (int i = 0; i < NUM_SENSOR_PIXELS/2; i++) {
+      int temp = pixels[i];
+      pixels[i] = pixels[NUM_SENSOR_PIXELS-1-i];
+      pixels[NUM_SENSOR_PIXELS-1-i] = temp;
+    }
+  }
+}
+
+int convertTwoUnsignedBytesToInt(uint8_t hi_byte, uint8_t lo_byte)
+{
+  int intval = (int)(hi_byte << 8 | lo_byte);
+  // Convert unsigned to 2's complement
+  if ((1 << 15) < intval)
+    intval -= (1 << 16);
+  return intval;
+}
diff -r 000000000000 -r c62425b2f286 controller.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/controller.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,64 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef CONTROLLER_H_INCLUDED
+#define CONTROLLER_H_INCLUDED
+
+#include "gesture_common.h"
+
+extern DigitalOut rLED;
+extern DigitalOut gLED;
+extern DigitalOut csb; // sensor 1
+extern DigitalOut sel;
+
+enum ser_modes {SPI_MODE, I2C_MODE};
+extern uint32_t serial_mode;
+
+// Serial Interfaces to device
+extern I2C i2c;
+extern SPI spi;
+
+void i2c_init();
+void spi_init();
+int reg_read(const uint8_t reg_addr, const uint8_t num_bytes, uint8_t reg_vals[]);
+int reg_write(const uint8_t reg_addr, const uint8_t reg_val);
+int i2c_read(const uint8_t reg_addr, uint8_t const num_bytes, uint8_t reg_vals[]);
+int i2c_write(const uint8_t reg_addr, const uint8_t reg_val);
+int spi_read(const uint8_t reg_addr, const uint8_t num_bytes, uint8_t reg_vals[]);
+int spi_write(const uint8_t reg_addr, const uint8_t reg_val);
+void getSensorPixels(int pixels[], const uint8_t flip_sensor_pixels);
+int convertTwoUnsignedBytesToInt(const unsigned char hi_byte, const unsigned char lo_byte);
+
+#endif
diff -r 000000000000 -r c62425b2f286 gesture.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gesture.c	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,203 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "gesture_common.h"
+
+// Gesture states
+typedef enum {STATE_INACTIVE, GESTURE_IN_PROGRESS} GestureState;
+
+static uint32_t reset_flag = TRUE;
+
+// Create a static instance of the configuration to maintain current config parameters
+static GestureConfig gestCfg;
+
+static void runDynamicGesture(const GestureConfig *cfg, int _pixels[], DynamicGestureResult *gesResult);
+void noiseWindow3Filter(int pixels[], const float alpha, const uint32_t reset_flag);
+
+void resetGesture()
+{
+  reset_flag = TRUE;
+  // Reset submodules
+  resetTracking();
+}
+
+// Get a copy of the config struct
+void getGestureConfig(GestureConfig *_cfg)
+{
+  *_cfg = gestCfg;
+}
+
+// Get a pointer to the config struct
+GestureConfig * getGestureConfigPtr()
+{
+  return &gestCfg;
+}
+
+// Copy the user's config struct to the local struct, and initialize calculated values
+void configGesture(const GestureConfig *_cfg)
+{
+  if (!_cfg) {
+    initConfigStructToDefaults(&gestCfg); // Use default configuration if pointer is NULL
+  }
+  else {
+    gestCfg = *_cfg; // make a copy of the struct
+  }
+
+  configTracking(gestCfg.sample_period_ms, gestCfg.adc_full_scale, &gestCfg.trackingConfig);
+
+  resetGesture();
+}
+
+void runGesture(int pixels[], GestureResult *gesResult)
+{
+  // Initialize result structure
+  memset(gesResult, 0, sizeof(GestureResult));
+  gesResult->state = STATE_INACTIVE;
+  gesResult->gesture = GEST_NONE;
+
+  // Noise filter
+  if (gestCfg.enable_window_filter) {
+    noiseWindow3Filter(pixels, gestCfg.window_filter_alpha, reset_flag);
+  }
+
+  // Process pixels for dynamic gesture
+  if (1) {
+    DynamicGestureResult dynamicResult;
+    runDynamicGesture(&gestCfg, pixels, &dynamicResult);
+    gesResult->state = dynamicResult.state;
+    gesResult->n_sample = dynamicResult.n_sample;
+    gesResult->maxpixel = dynamicResult.maxpixel;
+    gesResult->x = dynamicResult.x;
+    gesResult->y = dynamicResult.y;
+  }
+  // Process pixels for tracking
+  if (0) {
+    TrackingResult trackResult;
+    runTracking(&gestCfg.trackingConfig, pixels, &trackResult);
+    gesResult->state = trackResult.state;
+    gesResult->maxpixel = trackResult.maxpixel; // Will override dynamic result if any
+    gesResult->x = trackResult.x; // Will override dynamic result if any
+    gesResult->y = trackResult.y; // Will override dynamic result if any
+  }
+}
+
+static void runDynamicGesture(const GestureConfig *cfg, int pixels[], DynamicGestureResult *gesResult)
+{
+  memset(gesResult, 0, sizeof(DynamicGestureResult));
+
+  static GestureState state = STATE_INACTIVE;
+  GestureEvent gest_event = GEST_NONE;
+  static uint32_t n_sample = 0, n_frame =0;
+
+  if (reset_flag) {
+    state = STATE_INACTIVE;
+  }
+
+  int rawmaxpixel = getMaxPixelValue(pixels, NUM_SENSOR_PIXELS);
+
+  // Static background subtraction
+  {
+    static float foreground_pixels[NUM_SENSOR_PIXELS], background_pixels[NUM_SENSOR_PIXELS];
+    if (reset_flag) {
+      for(uint32_t i=0; i<NUM_SENSOR_PIXELS; i++) {
+        foreground_pixels[i] = pixels[i]; // clear the filter
+        background_pixels[i] = pixels[i]; // clear the filter
+      }
+    }
+
+    float background_alpha = cfg->background_filter_alpha;
+
+    subtractBackground(pixels, foreground_pixels, background_pixels, NUM_SENSOR_PIXELS, cfg->low_pass_filter_alpha, background_alpha);
+  }
+
+  // Clear the reset flag. All reset activity should be done by now
+  if (reset_flag) {
+    reset_flag = FALSE;
+  }
+
+  // Find post-filter max pixel
+  int maxpixel=getMaxPixelValue(pixels, NUM_SENSOR_PIXELS);
+
+  float cmx,cmy;
+  {
+    #if INTERP_FACTOR == 1
+      int *interp_pixels;
+      interp_pixels = pixels;
+    #else
+      static int interp_pixels[NUM_INTERP_PIXELS];
+      interpn(pixels, interp_pixels, SENSOR_XRES, SENSOR_YRES, INTERP_FACTOR);
+    #endif
+
+    // Thresholding
+    zeroPixelsBelowThreshold(interp_pixels,NUM_INTERP_PIXELS,(int)(maxpixel/cfg->zero_clamp_threshold_factor)); // zero out pixels below some percent of peak
+    zeroPixelsBelowThreshold(interp_pixels,NUM_INTERP_PIXELS,cfg->zero_clamp_threshold); // and also zero out below fixed threshold
+
+    // Center of mass
+    int totalmass=0;
+    if (maxpixel >= cfg->end_detection_threshold) {
+      calcCenterOfMass(interp_pixels, INTERP_XRES, INTERP_YRES, &cmx, &cmy, &totalmass); // Only calculate COM if there is a pixel above the noise (avoid divide-by-zero)
+      cmx = cmx/INTERP_FACTOR;
+      cmy = cmy/INTERP_FACTOR * DY_PIXEL_SCALE; // scale y so it has same unit dimension as x
+    }
+  }
+
+  n_frame++;
+
+  gesResult->n_sample = n_sample;
+  gesResult->maxpixel = maxpixel; //rawmaxpixel;
+  gesResult->state = maxpixel >= cfg->end_detection_threshold ? GESTURE_IN_PROGRESS : STATE_INACTIVE;
+  gesResult->x = maxpixel >= cfg->end_detection_threshold ? cmx : -1.00;
+  gesResult->y = maxpixel >= cfg->end_detection_threshold ? cmy : -1.00;
+}
+
+void noiseWindow3Filter(int pixels[], const float alpha, const uint32_t reset_flag)
+{
+  static int nwin[3][NUM_SENSOR_PIXELS];
+  if (reset_flag) {
+    for(uint32_t i=0; i<NUM_SENSOR_PIXELS; i++) {
+      nwin[0][i] = pixels[i]; // clear the filter
+      nwin[1][i] = pixels[i]; // clear the filter
+      nwin[2][i] = pixels[i]; // clear the filter
+    }
+  }
+  else {
+    for (uint32_t i=0; i<NUM_SENSOR_PIXELS; i++) {
+      nwin[0][i] = nwin[1][i];
+      nwin[1][i] = nwin[2][i];
+      nwin[2][i] = pixels[i];
+      pixels[i] = alpha * nwin[1][i] + (1-alpha)*(nwin[0][i] + nwin[2][i])/2;
+    }
+  }
+}
diff -r 000000000000 -r c62425b2f286 gesture_common.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gesture_common.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,95 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef GESTURE_COMMON_H_INCLUDED
+#define GESTURE_COMMON_H_INCLUDED
+
+#include "img_utils.h"
+#include "gesture_lib.h"
+
+//#define USE_MBED
+
+#ifdef USE_MBED
+	#include "mbed.h"
+#else
+	#include <math.h>
+	#include <string.h>
+	#include <stdlib.h>
+	#define TRUE 1
+	#define FALSE 0
+#endif
+
+// Sensor constants. Declared as constants so arrays can be statically sized
+#define SENSOR_XRES 10
+#define SENSOR_YRES 6
+#define NUM_SENSOR_PIXELS (SENSOR_XRES * SENSOR_YRES)
+
+// Interpolation used in gesture algorithm
+#define INTERP_FACTOR 4
+#define INTERP_XRES ((SENSOR_XRES-1)*INTERP_FACTOR+1)
+#define INTERP_YRES ((SENSOR_YRES-1)*INTERP_FACTOR+1)
+#define NUM_INTERP_PIXELS (INTERP_XRES*INTERP_YRES)
+
+#define DY_PIXEL_SCALE  1.42857f /*10.0f/7.0f*/
+
+
+// Error condition constants
+static const float MAX_ABS_ACCUM_DX = SENSOR_XRES*2; 	// Total x motion should not exceed 2x the screen size
+static const float MAX_ABS_ACCUM_DY = SENSOR_YRES*2 * DY_PIXEL_SCALE; 	// Total x motion should not exceed 2x the screen size
+
+// Structure to store tracking results
+typedef struct {
+	uint32_t state;             // 0: inactive; 1: object detected
+	int maxpixel;               // Maximum pixel value for this frame
+	float x;                    // Object x-position
+	float y;                    // Object y-position
+} TrackingResult;
+
+// Functions in tracking.cpp
+void configTracking(const uint32_t _sampleT, const uint32_t _adc_full_scale, const TrackingConfig *cfg);
+void runTracking(const TrackingConfig *cfg, int in_pixels[], TrackingResult *gesResult);
+void resetTracking();
+void clearTrackingCalibration();
+
+// Structure to store dynamic gesture results
+typedef struct {
+	uint32_t state;             // 0: inactive; 1: object detected; 2: rotation in progress
+	uint32_t n_sample;          // The current sample number of this gesture
+	int maxpixel;               // Maximum pixel value for this frame
+	float x;                    // Object x-position
+	float y;                    // Object y-position
+} DynamicGestureResult;
+
+#endif
diff -r 000000000000 -r c62425b2f286 gesture_config.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gesture_config.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,67 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+  /* Paramaters for gesture configuration */
+  #define FLIP_SENSOR_PIXELS 0
+  #define PIXEL_DATA_MODE 0
+  #define SAMPLE_PERIOD_MS 19.8F /*Changed from 12.5f for 400um device*/
+  #define ADC_FULL_SCALE 16384 /*Changed from 8192 for 400um device*/
+  #define BACKGROUND_FILTER_ALPHA 0.05F /*Changed from 0.10f for 400um device*/
+  #define LOW_PASS_FILTER_ALPHA 1.0F
+  #define ZERO_CLAMP_THRESHOLD 10
+  #define ZERO_CLAMP_THRESHOLD_FACTOR 6
+  #define ENABLE_WINDOW_FILTER 1
+  #define WINDOW_FILTER_ALPHA 0.5F
+  #define START_DETECTION_THRESHOLD 150 /*Changed from 400 for 400um device*/
+  #define END_DETECTION_THRESHOLD 50 /*Changed from 250 for 400um device*/
+
+
+
+  /* Paramaters for tracking configuration */
+  #define ENABLE_AUTO_BIAS_CALIBRATION 1
+  #define STATIC_STATE_BIAS_MS 2000
+  #define TRACKING_LOW_PASS_FILTER_ALPHA 1.0F
+  #define TRACKING_ZERO_CLAMP_THRESHOLD 50
+  #define TRACKING_ZERO_CLAMP_THRESHOLD_FACTOR 6
+  #define TRACKING_START_DETECTION_THRESHOLD 400
+  #define TRACKING_END_DETECTION_THRESHOLD 300
+  #define STATIC_STATE_BIAS_DELTA_MAX 200
+  #define BIAS_FULLSCALE_FACTOR_MAX 2
+  #define TRACK_WIDTH 6.0F
+  #define TRACK_HEIGHT 3.0F
+  #define ENABLE_GAIN_CORRECTION 1
+  #define GAIN_FACTOR_0 0.5;
+  #define GAIN_FACTOR_1 0.75;
+  #define GAIN_FACTOR_2 1.0;
diff -r 000000000000 -r c62425b2f286 gesture_init.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gesture_init.c	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,78 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "gesture_lib.h"
+#include "config.h"
+#include "gesture_config.h"
+
+// Initialize configuration structs to default values
+
+void initTrackingConfigStructToDefaults(TrackingConfig *cfg)
+{
+  cfg->enable_auto_bias_calibration = ENABLE_AUTO_BIAS_CALIBRATION;
+  cfg->static_state_bias_ms = STATIC_STATE_BIAS_MS;
+  cfg->low_pass_filter_alpha = TRACKING_LOW_PASS_FILTER_ALPHA;
+  cfg->zero_clamp_threshold = TRACKING_ZERO_CLAMP_THRESHOLD;
+  cfg->zero_clamp_threshold_factor = TRACKING_ZERO_CLAMP_THRESHOLD_FACTOR;
+  cfg->start_detection_threshold = TRACKING_START_DETECTION_THRESHOLD;
+  cfg->end_detection_threshold = TRACKING_END_DETECTION_THRESHOLD;
+  cfg->static_state_bias_delta_max = STATIC_STATE_BIAS_DELTA_MAX;
+  cfg->bias_fullscale_factor_max = BIAS_FULLSCALE_FACTOR_MAX;
+  cfg->track_width = TRACK_WIDTH;
+  cfg->track_height = TRACK_HEIGHT;
+  cfg->enable_gain_correction = ENABLE_GAIN_CORRECTION;
+  cfg->gain_factor_0 = GAIN_FACTOR_0;
+  cfg->gain_factor_1 = GAIN_FACTOR_1;
+  cfg->gain_factor_2 = GAIN_FACTOR_2;
+}
+
+void initConfigStructToDefaults(GestureConfig *cfg)
+{
+  cfg->flip_sensor_pixels = FLIP_SENSOR_PIXELS;
+  cfg->pixel_data_mode = PIXEL_DATA_MODE;
+  cfg->sample_period_ms = SAMPLE_PERIOD_MS;
+  cfg->adc_full_scale = ADC_FULL_SCALE;
+  cfg->background_filter_alpha = BACKGROUND_FILTER_ALPHA;
+  cfg->low_pass_filter_alpha = LOW_PASS_FILTER_ALPHA;
+  cfg->zero_clamp_threshold = ZERO_CLAMP_THRESHOLD;
+  cfg->zero_clamp_threshold_factor = ZERO_CLAMP_THRESHOLD_FACTOR;
+  cfg->enable_window_filter = ENABLE_WINDOW_FILTER;
+  cfg->window_filter_alpha = WINDOW_FILTER_ALPHA;
+  cfg->start_detection_threshold = START_DETECTION_THRESHOLD;
+  cfg->end_detection_threshold = END_DETECTION_THRESHOLD;
+
+  // Initialize tracking config strucutre
+  initTrackingConfigStructToDefaults(&cfg->trackingConfig);
+}
diff -r 000000000000 -r c62425b2f286 gesture_lib.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gesture_lib.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,209 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef GESTURE_LIB_H_INCLUDED
+#define GESTURE_LIB_H_INCLUDED
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/*
+* Enumerate gesture events here
+*/
+typedef enum {
+	GEST_NONE,
+	GEST_PLACEHOLDER
+} GestureEvent;
+
+/*
+* Structure to store gesture results.
+*/
+typedef struct {
+	GestureEvent gesture;        // Gesture event reported for this processed frame
+	uint32_t state;              // 0: inactive; 1: object detected; 2: rotation in progress
+	uint32_t n_sample;           // The current sample number of the gesture in progress
+	int maxpixel;                // Maximum pixel value for this frame
+	float x;                     // Object x-position. Only accurate if TRACKING_ENABLE mask is set.
+	float y;                     // Object y-position. Only accurate if TRACKING_ENABLE mask is set.
+	float float_placeholder;
+	uint32_t int_placeholder;
+
+} GestureResult;
+
+
+/*
+* Structure for configuration parameters that apply to tracking mode, region selection, and linger-to-click.
+* An instance of this structure is a member of the GestureConfig stucture.
+*/
+typedef struct {
+	uint32_t enable_auto_bias_calibration;  // Enable automatic bias calibration
+	uint32_t static_state_bias_ms;          // How many milliseconds of static condition before performing an automoatic bias calibration
+	float low_pass_filter_alpha;            // Smoothing factor for low pass filter. The lower the value, the more low pass filtering
+	int zero_clamp_threshold;               // Any pixel below this value is clamped to zero. Must be less than detection thresholds
+	float zero_clamp_threshold_factor;   // Any pixel below maxpixel divided by this factor is clamped to zero. This is to reduce optical clutter and background noise
+	int start_detection_threshold;           // Pixel activation (bias corrected) to start gesture tracking
+	int end_detection_threshold;      // Pixel activation (bias corrected) to stop gesture tracking
+	uint32_t static_state_bias_delta_max;   // Max current pixel to reference delta to be considered static state for bias calibration
+	uint32_t bias_fullscale_factor_max;     // Only calibrate if raw pixel range below this factor of ADC FS
+	float track_width;                      // Width (in pixels) of sensor array over which to scale tracking cursor (thereby ignoring edge pixels)
+	float track_height;                     // Height (in pixels) of sensor array over which to scale tracking cursor (thereby ignoring edge pixels)
+	uint32_t enable_gain_correction;        // Enable pixel gain correction
+	float gain_factor_0; 										// Inner gain factor
+	float gain_factor_1; 										// Mid gain factor
+	float gain_factor_2;										// Outer gain factor
+} TrackingConfig;
+
+/*
+* Struture for gesture configuration parameters
+* An instance of this structure can be modified by the application and passed to the configGesture function
+*/
+typedef struct {
+	uint32_t flip_sensor_pixels;              // Set true to if device is mounted upside-down
+	uint32_t pixel_data_mode;									// Set to 0 for raw data, 1 for bias-compensated pixels, 2 for background subtracted (gesture) pixels
+	float sample_period_ms;                   // Sample period of sensor in milliseconds
+	uint32_t adc_full_scale;                  // ADC full scale of sensor for current register configuration
+	float background_filter_alpha;            // Smoothing factor for dynamic background cancellation. Larger value results in more aggressive high pass filtering
+	float low_pass_filter_alpha;              // Smoothing factor for low pass filter. Set to 1 for no filtering
+	int zero_clamp_threshold;                 // Any pixel below this value (background corrected) is clamped to zero. Must be less than detection thresholds
+	float zero_clamp_threshold_factor;     		// Any pixel below maxpixel/x is clamped to zero. This is to reduce optical clutter and background noise
+	uint32_t enable_window_filter;
+	float window_filter_alpha;
+	int start_detection_threshold;            // Pixel activation level (background corrected) to start gesture tracking
+	int end_detection_threshold;              // Pixel threshold (background corrected) to end gesture tracking
+	TrackingConfig trackingConfig;
+} GestureConfig;
+
+
+/**
+* This function obtains a copy of the GestureConfig structure.
+* Obtain a copy in order to modify parameters and then pass the struct back using configGesture.
+*
+* Parameters
+* cfg: A pointer to a GestureConfig structure
+*
+* Return Value
+* None
+*/
+void getGestureConfig(GestureConfig *_cfg);
+
+/**
+* This function obtains a pointer to the GestureConfig structure.
+* Obtain a pointer to use the VALUE of specific parameter. Parameters should never be SET directly using the pointer
+* to the Config struct. Instead use getGestureConfig() above.
+*
+* Parameters
+* none
+*
+* Return Value
+* cfg: A pointer to the GestureConfig structure contained in the gesture library
+*/
+
+GestureConfig * getGestureConfigPtr();
+
+
+/**
+* This function initializes the gesture algorithm with the parameters defined in the GestureConfig structure.
+*
+* Parameters
+* cfg: A pointer to the GestureConfig structure. If the pointer is NULL, the algorithm will be configured with default values.
+*
+* Return Value
+* None
+*/
+void configGesture(const GestureConfig *cfg);
+
+
+/**
+* This function initializes an instance of a GestureConfig structure to the default values.
+* After calling this function, the structure instance can then be modified selectively by the application
+* and passed into the configGesture function to implement a custom configuration.
+*
+* Parameters
+* cfg: A pointer to the GestureConfig structure
+*
+* Return Value
+* None
+*/
+void initConfigStructToDefaults(GestureConfig *cfg);
+
+
+/**
+* This function executes the algorithm for a single frame. This function should be called for every sample period of the sensor.
+*
+* Parameters
+* pixels:    An integer array of sensor pixel data; length is determined by the sensor resolution defined in gesture_common.h
+* gesResult: A pointer to a GestureResult struct instance; this instance will be populated with results by the algorithm.
+*
+* Return Value
+* None
+*/
+void runGesture(int pixels[], GestureResult *gesResult);
+
+
+/**
+* This function resets the gesture algorithm by resetting the state machine and clearing filters.
+* Note that the initialization parameters are not changed
+*
+* Parameters
+* None
+*
+* Return Value
+* None
+*/
+void resetGesture();
+
+
+/**
+* This function forces a tracking mode calibration.
+* Note that the calibration only applies to tracking mode (region selection and linger to click); it is not used
+* for dynamic gesture mode.
+*
+* Parameters
+* None
+*
+* Return Value
+* None
+*/
+void forceTrackingCalibration();
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif
diff -r 000000000000 -r c62425b2f286 img_utils.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/img_utils.c	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,155 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "img_utils.h"
+
+int getMaxPixelValue(const int pixels[], const unsigned int num_pixels)
+{
+  int maxpixel=-99999;
+  for (unsigned int i = 0; i < num_pixels; i++) {
+    if (maxpixel < pixels[i]) {
+        maxpixel = pixels[i];
+    }
+  }
+  return maxpixel;
+}
+
+int getMinPixelValue(const int pixels[], const unsigned int num_pixels)
+{
+  int minpixel=99999;
+  for (unsigned int i = 0; i < num_pixels; i++) {
+    if (minpixel > pixels[i]) {
+        minpixel = pixels[i];
+    }
+  }
+  return minpixel;
+}
+
+// Zero out pixels below threshold value. Returns the number of pixels above the threshold
+unsigned int zeroPixelsBelowThreshold(int pixels[], const unsigned int num_pixels, const int threshold)
+{
+  int pixelsAboveThresholdCount = num_pixels;
+  for (unsigned int i = 0; i < num_pixels; i++) {
+    if (pixels[i] < threshold) {
+      pixels[i] = 0;
+      pixelsAboveThresholdCount--;
+    }
+  }
+  return pixelsAboveThresholdCount;
+}
+
+// Caller must keep static filtpixels array
+void filterLowPassPixels(int pixels[], float filtpixels[], const unsigned int num_pixels, const float alpha)
+{
+  for (unsigned int i=0; i< num_pixels; i++) {
+    filtpixels[i] = (1.0 - alpha) * filtpixels[i] + alpha * pixels[i];
+  }
+  for (unsigned int i=0; i< num_pixels; i++) {
+    pixels[i] = (int)filtpixels[i];
+  }
+}
+
+// Implement background subtraction by subtracting long exponential smoothing average from a shorter one
+// (or simply the current pixel if alpha_short_avg is set to 1.0)
+// alpha_long_avg should be smaller than alpha_short_avg
+// Caller must keep static shart_avg_pixels[] and long_avg_pixels[]
+// The bigger alpha long is, the more aggressive the high pass filter.
+void subtractBackground(int pixels[], float short_avg_pixels[], float long_avg_pixels[], const unsigned int num_pixels, const float alpha_short_avg, const float alpha_long_avg)
+{
+  for (unsigned int i=0; i< num_pixels; i++) {
+    long_avg_pixels[i] = (1.0f - alpha_long_avg) * long_avg_pixels[i] + alpha_long_avg * pixels[i];
+  }
+  for (unsigned int i=0; i< num_pixels; i++) {
+    short_avg_pixels[i] = (1.0f - alpha_short_avg) * short_avg_pixels[i] + alpha_short_avg * pixels[i];
+  }
+  for (unsigned int i=0; i< num_pixels; i++) {
+    pixels[i] = short_avg_pixels[i] - (int)long_avg_pixels[i];
+  }
+}
+
+void calcCenterOfMass(const int pixels[], const unsigned int xres, const unsigned int yres, float *cmx, float *cmy, int *totalmass)
+{
+  int cmx_numer=0, cmy_numer=0;
+  for (unsigned int i = 0; i < xres*yres; i++) {
+    cmx_numer += (i%xres)*pixels[i];
+    cmy_numer += (i/xres)*pixels[i];
+    *totalmass += pixels[i];
+  }
+  if (*totalmass == 0) {
+    *totalmass = 1; // avoid NaN
+  }
+  *cmx = (float)cmx_numer/(float)(*totalmass);
+  *cmy = (float)cmy_numer/(float)(*totalmass);
+}
+
+void interpn(const int pixels[], int interp_pixels[], const int w, const int h, const int interpolation_factor)
+{
+  int w2 = (w - 1) * interpolation_factor + 1;
+  int h2 = (h - 1) * interpolation_factor + 1;
+  int A, B, C, x, y;
+  float x_ratio = 1.0f / (float)interpolation_factor;
+  float y_ratio = 1.0f / (float)interpolation_factor;
+
+  // First stretch in x-direction, index through each pixel of destination array. Skip rows in destination array
+  for (int i = 0; i < h; i++) {
+    for (int j = 0; j < w2; j++) {
+      x = (int)(x_ratio * j);  // x index of original frame
+      int index = i * w + x;  // pixel index of original frame
+      if (x == w - 1) // last pixel on right edge of original frame
+        interp_pixels[i * w2 * interpolation_factor + j] = pixels[index]; // skip rows in dest array
+      else {
+        A = pixels[index];
+        B = pixels[index + 1];
+        float x_diff = (x_ratio * j) - x; // For 2x interpolation, will be 0, 1/2, 0, 1/2...
+        interp_pixels[i * w2 * interpolation_factor + j] = (int)(A + (B - A) * x_diff); // skip rows in dest array
+      }
+    }
+  }
+  // Then stretch in y-direction, index through each pixel of destination array
+  for (int i = 0; i < h2; i++) {
+    for (int j = 0; j < w2; j++) {
+      y = (int)(y_ratio * i);  // y index of original frame
+      int index = y * w2 * interpolation_factor + j;  // pixel index of frame
+      if (y == h - 1) //  pixel on bottom of original frame
+        interp_pixels[i * w2 + j] = interp_pixels[index];
+      else {
+        A = interp_pixels[index];
+        C = interp_pixels[index + w2 * interpolation_factor];
+        float y_diff = (y_ratio * i) - y;
+        interp_pixels[i * w2 + j] = (int)(A + (C - A) * y_diff);
+      }
+    }
+  }
+}
diff -r 000000000000 -r c62425b2f286 img_utils.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/img_utils.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,49 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef IMG_UTILS_H_INCLUDED
+#define IMG_UTILS_H_INCLUDED
+
+#include <stdint.h>
+
+int getMaxPixelValue(const int pixels[], const unsigned int num_pixels);
+int getMinPixelValue(const int pixels[], const unsigned int num_pixels);
+unsigned int zeroPixelsBelowThreshold(int pixels[], const unsigned int num_pixels, const int threshold);
+void filterLowPassPixels(int pixels[], float filtpixels[], const unsigned int num_pixels, const float alpha);
+void subtractBackground(int pixels[], float short_avg_pixels[], float long_avg_pixels[], const unsigned int num_pixels, const float alpha_short_avg, const float alpha_long_avg);
+void calcCenterOfMass(const int pixels[], const unsigned int xres, const unsigned int yres, float *cmx, float *cmy, int *totalmass);
+void interpn(const int pixels[], int interp_pixels[], const int w, const int h, const int interpolation_factor);
+
+#endif
diff -r 000000000000 -r c62425b2f286 interface.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interface.cpp	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,77 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "interface.h"
+#include "USBSerial.h"
+#include "controller.h"
+#include "config.h"
+
+// Serial port for full interface with streaming data. Select USB or UART with USE_UART_INTERFACE constant.
+// Files that use these objects should declare them as externs.
+#if USE_UART_INTERFACE
+Serial *serial = new Serial(P3_1,P3_0,UART_BAUD_RATE);
+#else
+USBSerial *serial = new USBSerial(0x0b6a, 0x4360, 0x0001, false);
+#endif
+
+// UART over daplink, 9600 baud. This can be used for debugging
+//Serial daplink(P2_1, P2_0);
+
+// USBSerial putc and printf are slow. Use writeBlock to stream data over USB
+void sendDataStream(uint8_t *str, const unsigned int num_chars)
+{
+#if USE_UART_INTERFACE
+
+  for (int i=0; i<num_chars; i++) {
+    (*serial).putc(str[i]);
+  }
+
+#else // This section needs to be #defined because writeBlock does not exist for UART serial object
+  uint8_t *output_ptr = (uint8_t *)str; // writeBlock requires pointer to uint8_t
+  unsigned int bytes_remaining = num_chars;
+
+  while (bytes_remaining > 0) {
+    if (bytes_remaining < USB_BLOCK_SIZE) {
+      (*serial).writeBlock(output_ptr, bytes_remaining);
+      bytes_remaining = 0;
+    }
+    else {
+      (*serial).writeBlock(output_ptr, USB_BLOCK_SIZE);
+      bytes_remaining -= USB_BLOCK_SIZE;
+      output_ptr += USB_BLOCK_SIZE;
+    }
+  }
+#endif
+}
diff -r 000000000000 -r c62425b2f286 interface.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interface.h	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,54 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#ifndef INTERFACE_H_INCLUDED
+#define INTERFACE_H_INCLUDED
+
+#include "mbed.h"
+#include "gesture_lib.h"
+
+// Option to implement serial API over UART instead of USB
+#define USE_UART_INTERFACE 1
+#define UART_BAUD_RATE 115200
+
+// Bytes prefixed to pixel data to create data frame
+const int NUM_INFO_BYTES = 40;
+
+const unsigned int USB_BLOCK_SIZE = 64;
+
+// Data streaming over USB or UART, depending on which is enabled
+void sendDataStream(uint8_t *str, const unsigned int num_chars);
+
+#endif
diff -r 000000000000 -r c62425b2f286 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,256 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "mbed.h"
+#include "USBSerial.h"
+
+#include "config.h"
+#include "gesture_lib.h"
+#include "interface.h"
+#include "controller.h"
+#include "cmd.h"
+
+#if defined(COMPILE_FOR_MAX32630)
+  #include "max32630fthr.h"
+  MAX32630FTHR fthr(MAX32630FTHR::VIO_3V3);
+#elif defined(COMPILE_FOR_MAX32620)
+  #include "MAX32620FTHR.h"
+  MAX32620FTHR fthr(MAX32620FTHR::VIO_3V3);
+#endif
+
+const char *version_string = "gesture firmware framework version 1.0";
+
+// MCU board status LEDs
+DigitalOut rLED(LED1);
+DigitalOut gLED(LED2);
+
+// Device pins
+DigitalOut csb(P5_5); // sensor 1
+//DigitalOut csb2(P54); // sensor 2
+DigitalOut sel(P3_2);
+
+InterruptIn intb(P5_3); // sensor 1
+//InterruptIn intb2(P3_3); // sensor 2
+
+#if USE_SPI
+  SPI spi(P5_1, P5_2, P5_0);
+#else
+  I2C i2c(P3_4, P3_5);
+#endif
+
+uint32_t i2c_addr_select = 0;
+
+uint32_t serial_mode = SPI_MODE;
+
+static uint32_t read_sensor_frames_enabled = 0;
+static uint32_t data_stream_enabled = 0;
+
+static uint32_t send_pixel_data_with_stream = 1;
+
+// Data ready flags
+static uint32_t sensorDataReadyFlag = 0; // Data ready flag, set by the end-of-conversion interrupt
+
+// Declare functions called in main
+static void processFrame(int pixels[]);
+void set_default_register_settings();
+
+int main()
+{
+  static int pixels[NUM_SENSOR_PIXELS];
+  gLED = LED_OFF;
+  rLED = LED_ON;
+
+  #if USE_SPI
+    spi.frequency(6e6);
+    serial_mode = SPI_MODE;
+    spi_init();
+  #else
+    i2c.frequency(400e3);
+    serial_mode = I2C_MODE;
+    i2c_init();
+  #endif
+
+  // Write register settings to device
+  set_default_register_settings();
+
+  // Set FTHR board status LEDs
+  gLED = LED_ON;
+  rLED = LED_OFF;
+
+  // Configure gesture library
+  // Declare a configuration object
+  GestureConfig gestCfg;
+  // First get a GestureConfig struct that is populated with default values
+  initConfigStructToDefaults(&gestCfg);
+  // Then pass this struct to the configGesture function to initialize the gesture library
+  configGesture(&gestCfg);
+  //configGesture(NULL); // If configGesture is called with NULL, then default parameters will be used.
+
+  // Enable reading of sensor frames
+  enable_read_sensor_frames();
+
+  while (1) {
+    // Check if a command was received over the serial interface
+    checkUserCmd();
+
+    // If using INTB interrupt, the sensorDataReadyFlag will be set when the end-of-conversion occurs
+    if (sensorDataReadyFlag) {
+        getSensorPixels(pixels, getGestureConfigPtr()->flip_sensor_pixels);
+        processFrame(pixels);
+        sensorDataReadyFlag = 0;
+    }
+  }
+}
+
+/*
+* This function calls the gesture library for a single sensor frame
+* It builds a data stream frame from the gesture results
+* And sends the stream over the serial connection
+*/
+GestureResult gesResult;
+void processFrame(int pixels[])
+{
+  runGesture(pixels, &gesResult);
+  // For raw pixels, instead uncomment out the following line
+  //memset(&gesResult, 0, sizeof(GestureResult));
+
+  if (data_stream_enabled) {
+
+    uint8_t frm_data[NUM_SENSOR_PIXELS*2+NUM_INFO_BYTES];
+
+    // The frame data is per the serial API used by the gesture EVKit GUI
+    // SYNC bits are used by receiver to know the start of frame
+    frm_data[0] = 255;  // SYNC
+    frm_data[1] = 255;  // SYNC2
+    frm_data[3] = gesResult.state;
+    frm_data[4] = gesResult.n_sample;
+    frm_data[6] = (gesResult.maxpixel>>8) & 0xFF;  // maxpixel high byte
+    frm_data[7] = gesResult.maxpixel & 0xFF;      // maxpixel low byte
+    float x = gesResult.x;
+    memcpy(frm_data+10, &x, 4);
+    float y = gesResult.y;
+    memcpy(frm_data+15, &y, 4);
+
+    for (uint32_t i=0; i<NUM_SENSOR_PIXELS; i++) {
+      frm_data[2*i + NUM_INFO_BYTES] = (pixels[i]>>8) & 0xFF;
+      frm_data[2*i+1 + NUM_INFO_BYTES] = pixels[i] & 0xFF;
+    }
+
+    if (send_pixel_data_with_stream)
+      sendDataStream(frm_data, NUM_SENSOR_PIXELS*2 + NUM_INFO_BYTES);
+    else
+      sendDataStream(frm_data, NUM_INFO_BYTES);
+  }
+}
+
+
+void set_default_register_settings()
+{
+  uint32_t ledDrvLevel = 0x0F;
+  reg_write(0x01, 0x04);
+  reg_write(0x02, 0x02);
+  #if defined(MAX25405_DEVICE)
+  reg_write(0x03, 0x24); // SDLY=2, TIM=2
+  reg_write(0x04, 0x8C); // NRPT=4, NCDS=3
+  #elif defined(MAX25205_DEVICE)
+  reg_write(0x03, 0x04); // SDLY=0, TIM=2
+  reg_write(0x04, 0xAC); // NRPT=5, NCDS=3
+  ledDrvLevel = 0x0A;
+  #endif
+  reg_write(0x05, 0x08);
+  reg_write(0x06, ledDrvLevel); // LED power
+  reg_write(0xa5, 0x88);
+  reg_write(0xa6, 0x88);
+  reg_write(0xa7, 0x88);
+  reg_write(0xa8, 0x88);
+  reg_write(0xa9, 0x88);
+  reg_write(0xc1, 0x0A); // PWM LED driver
+}
+
+/*
+* This is the interrupt handler to handle end-of-conversion interrupts on the INTB pin
+*/
+void intb_handler()
+{
+  sensorDataReadyFlag = 1;
+}
+
+/*
+* This function starts the monitoring of the INTB interrupt
+*/
+void enable_read_sensor_frames()
+{
+  resetGesture();
+
+  intb.fall(&intb_handler); // Add INTB interrupt handler
+
+  // Read status reg to clear interrupt
+  uint8_t status_reg;
+  reg_read(0x00, 1, &status_reg);
+
+  // Turn off the status LEDs on the MCU board
+  gLED = LED_OFF;
+  rLED = LED_OFF;
+  read_sensor_frames_enabled = 1;
+}
+
+/*
+* This function stops the monitoring of the INTB interrupt or polling
+*/
+void disable_read_sensor_frames()
+{
+  intb.fall(0); // Remove interrupt handler
+
+  // Turn on the status LEDs on the MCU board
+  gLED = LED_ON;
+  rLED = LED_OFF;
+  read_sensor_frames_enabled = 0;
+}
+
+/*
+* These functions set the data reporting mode and starts sending of data
+*/
+void set_stream_on(uint32_t send_pixel_data)
+{
+  send_pixel_data_with_stream = send_pixel_data;
+  data_stream_enabled = 1;
+  if (read_sensor_frames_enabled == 0)
+    enable_read_sensor_frames(); // make sure
+}
+
+void set_stream_off()
+{
+  data_stream_enabled = 0;
+}
diff -r 000000000000 -r c62425b2f286 mbed-os.lib
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#0fdfcf7350896a9c0b57c4a18237677abfe25f1a
diff -r 000000000000 -r c62425b2f286 readme.txt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/readme.txt	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,61 @@
+
+# Application files:
+
+main.cpp: Top level source file
+controller.cpp / controller.h: These files handle low level communication to the sensor device
+cmd.cpp / cmd.h: These files are for the command-line interface over the USB serial
+interface.cpp / interface.h: These files handle communications over the serial connection
+
+# Gesture Library Files:
+
+gesture_lib.h: defines the Gesture Library API
+
+Other gesture library source files:
+	gesture.cpp
+	gesture_init.cpp
+	gesture_config.h
+	gesture_common.h
+	img_utils.cpp / img_utils.h
+
+# Setup with mbed CLI
+
+This project was compiled under mbed CLI.
+
+*Installing mbed CLI*
+Follow the mbed CLI installation instructions on the mbed site:
+https://os.mbed.com/docs/mbed-os/v6.6/quick-start/build-with-mbed-cli.html
+
+*Initialize a new mbed project*
+Add the mbed-os library to the directory containing the source files with the following command (note the period):
+  mbed new .
+Use the "--scm none" option to prevent revision control initialization
+
+*Add required libraries*
+Add libraries to support the MAX32630FTHR or MAX32620FTHR development. In the same directory, type:
+  mbed add https://os.mbed.com/teams/MaximIntegrated/code/max32630fthr/
+or
+	mbed add https://os.mbed.com/teams/MaximIntegrated/code/MAX32620FTHR/
+
+And library to support the USB serial interface. In same directory type:
+  mbed add https://os.mbed.com/teams/MaximIntegrated/code/USBDevice/
+
+
+# Configuration
+
+Stack size needs to be increased from the default of 4k.
+The stack size is defined by an mbed_app.json file in the root directory of your project.
+
+mbed_app.json should contain:
+
+{
+    "config": {
+        "main-stack-size": {
+            "value": 65536
+        }
+    }
+}
+
+# Compiling
+  mbed compile -t GCC_ARM -m MAX32630FTHR
+or
+	mbed compile -t GCC_ARM -m MAX32620FTHR
diff -r 000000000000 -r c62425b2f286 tracking.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracking.c	Sun Oct 16 15:35:01 2022 +0000
@@ -0,0 +1,258 @@
+/*******************************************************************************
+* Copyright (C) Maxim Integrated Products, Inc., All rights Reserved.
+*
+* This software is protected by copyright laws of the United States and
+* of foreign countries. This material may also be protected by patent laws
+* and technology transfer regulations of the United States and of foreign
+* countries. This software is furnished under a license agreement and/or a
+* nondisclosure agreement and may only be used or reproduced in accordance
+* with the terms of those agreements. Dissemination of this information to
+* any party or parties not specified in the license agreement and/or
+* nondisclosure agreement is expressly prohibited.
+*
+* The above copyright notice and this permission notice shall be included
+* in all copies or substantial portions of the Software.
+*
+* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+* IN NO EVENT SHALL MAXIM INTEGRATED BE LIABLE FOR ANY CLAIM, DAMAGES
+* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+* OTHER DEALINGS IN THE SOFTWARE.
+*
+* Except as contained in this notice, the name of Maxim Integrated
+* Products, Inc. shall not be used except as stated in the Maxim Integrated
+* Products, Inc. Branding Policy.
+*
+* The mere transfer of this software does not imply any licenses
+* of trade secrets, proprietary technology, copyrights, patents,
+* trademarks, maskwork rights, or any other form of intellectual
+* property whatsoever. Maxim Integrated Products, Inc. retains all
+* ownership rights.
+*******************************************************************************
+*/
+
+#include "gesture_common.h"
+
+static uint32_t reset_flag = TRUE;
+static uint32_t reset_bias_flag = TRUE;
+
+// Calculated from parameters
+static uint32_t sampleT;
+static uint32_t adc_full_scale;
+static uint32_t static_state_bias_n;
+
+static uint32_t force_calibration_flag = FALSE;
+
+typedef enum { INACTIVE_STATE, TRACKING_STATE } TrackingState;
+
+void configTracking(const uint32_t _sampleT, const uint32_t _adc_full_scale, const TrackingConfig *cfg)
+{
+  sampleT = _sampleT;
+  adc_full_scale = _adc_full_scale;
+  static_state_bias_n = cfg->static_state_bias_ms/sampleT;
+  resetTracking();
+
+  // Reset calibration only if sample period or full-scale changed, so calibration is not cleared.
+  static uint32_t last_sampleT = 0;
+  static uint32_t last_adc_full_scale = 0;
+  if ((sampleT != last_sampleT) || (adc_full_scale != last_adc_full_scale)) {
+    clearTrackingCalibration();
+  }
+  last_sampleT = sampleT;
+  last_adc_full_scale = adc_full_scale;
+}
+
+// Force a single bias configuration
+void forceTrackingCalibration()
+{
+  force_calibration_flag = TRUE;
+}
+
+void clearTrackingCalibration()
+{
+  reset_bias_flag = TRUE;
+}
+
+// Reset the state machine and clear the filter
+void resetTracking()
+{
+  reset_flag = TRUE;
+}
+
+void runTracking(const TrackingConfig *cfg, int pixels[], TrackingResult *gesResult)
+{
+  static TrackingState state = INACTIVE_STATE;
+  static uint32_t calibration_done = FALSE;
+  static uint32_t static_state_bias_count = 0;
+
+  static uint32_t reset_filter_flag = TRUE;
+  static uint32_t reset_linger_flag = TRUE;
+
+  memset(gesResult, 0, sizeof(TrackingResult));
+
+  // A reset will reset the calibration, so filters and static state counters must also be reset once a calibration is performed
+  if (reset_flag) {
+    state = INACTIVE_STATE;
+    static_state_bias_count = 0; // Reset the bias calibration counter but don't clear the bias cal.
+    reset_filter_flag = TRUE;
+    reset_flag = FALSE;
+  }
+
+  // -----------------------------------------
+  // Bias Compenstation
+  // -----------------------------------------
+  {
+    static int biaspixels[NUM_SENSOR_PIXELS];
+    static float refpixels[NUM_SENSOR_PIXELS];
+
+    int max_raw_pixel=getMaxPixelValue(pixels, NUM_SENSOR_PIXELS);
+    int min_raw_pixel=getMinPixelValue(pixels, NUM_SENSOR_PIXELS);
+
+    if (reset_bias_flag) {
+      for(uint32_t i=0; i<NUM_SENSOR_PIXELS; i++) {
+        biaspixels[i] = 0;         // clear the bias compensation
+        refpixels[i] = pixels[i];  // reset reference pixels
+      }
+      static_state_bias_count = 0;
+      reset_bias_flag = FALSE;
+      calibration_done = FALSE;
+    }
+
+    if (cfg->enable_auto_bias_calibration) {
+      // Compare current pixel to reference
+      int maxdelta = -99999;
+      for (uint32_t i = 0; i < NUM_SENSOR_PIXELS; i++) {
+        int delta = abs(pixels[i]  - refpixels[i]);
+        if (maxdelta < delta) {
+          maxdelta = delta;
+        }
+      }
+      // Check for static condition
+      if (maxdelta < (int)cfg->static_state_bias_delta_max
+        && max_raw_pixel-min_raw_pixel < (int)adc_full_scale/(int)cfg->bias_fullscale_factor_max
+        && state != TRACKING_STATE)
+      {
+        static_state_bias_count++;
+      }
+      else {
+        // Sensor not static, reset the counter and set new reference
+        static_state_bias_count = 0;
+        for(uint32_t i=0; i<NUM_SENSOR_PIXELS; i++) {
+          refpixels[i] = pixels[i];
+        }
+      }
+      // If static condition, recalculate bias compenstation
+      if (static_state_bias_count > static_state_bias_n) {
+        for (uint32_t i = 0; i < NUM_SENSOR_PIXELS; i++) {
+          biaspixels[i] = refpixels[i];
+        }
+        static_state_bias_count = 0;
+        calibration_done = TRUE;
+      }
+    }
+    // If force_calibration_flag is set, set bias to current pixel values
+    if (force_calibration_flag) {
+      for (uint32_t i = 0; i < NUM_SENSOR_PIXELS; i++) {
+        biaspixels[i] = pixels[i];
+      }
+      calibration_done = TRUE;
+      force_calibration_flag = FALSE;
+    }
+    // Apply bias compensation
+    for (uint32_t i = 0; i < NUM_SENSOR_PIXELS; i++) {
+      pixels[i] -= biaspixels[i];
+    }
+  }
+
+  // -----------------------------------------
+  // Low pass filter
+  // -----------------------------------------
+  if (calibration_done) {
+    static float filtpixels[NUM_SENSOR_PIXELS];
+    if (reset_filter_flag) {
+      for(uint32_t i=0; i<NUM_SENSOR_PIXELS; i++)
+      {
+        filtpixels[i] = pixels[i]; // Clear the filter
+      }
+      reset_filter_flag = FALSE;
+    }
+    filterLowPassPixels(pixels, filtpixels, NUM_SENSOR_PIXELS, cfg->low_pass_filter_alpha);
+  }
+
+  // -----------------------------------------
+  // Software gain
+  // -----------------------------------------
+  {
+    double gain_factor = 0.0f;
+    for (uint32_t i = 0; i < NUM_SENSOR_PIXELS; i++) {
+      if (i%SENSOR_XRES == 0 || i%SENSOR_XRES == 9 || i%SENSOR_XRES == 1 || i%SENSOR_XRES == 8 || i/SENSOR_XRES == 0 || i/SENSOR_XRES == 5)
+        gain_factor = cfg->gain_factor_2;
+      else if (i%SENSOR_XRES == 2 || i%SENSOR_XRES == 7 || i/SENSOR_XRES == 1 || i/SENSOR_XRES == 4)
+        gain_factor = cfg->gain_factor_1;
+      else if (i%SENSOR_XRES == 3 || i%SENSOR_XRES == 6 || i%SENSOR_XRES == 4 || i%SENSOR_XRES == 5)
+        gain_factor = cfg->gain_factor_0;
+
+      pixels[i] *= gain_factor;
+    }
+  }
+
+  // -----------------------------------------
+  // Determine tracking state
+  // -----------------------------------------
+
+  // Get max/min pixel after applying bias compensation and filtering
+  int maxpixel=getMaxPixelValue(pixels, NUM_SENSOR_PIXELS);
+
+  // Determine state
+  if (calibration_done
+    && ((state == INACTIVE_STATE
+    && maxpixel > cfg->start_detection_threshold) || (state == TRACKING_STATE
+    && maxpixel > cfg->end_detection_threshold)))
+  {
+    state = TRACKING_STATE;
+  }
+  else {
+    state = INACTIVE_STATE;
+  }
+
+  // -----------------------------------------
+  // Object position
+  // -----------------------------------------
+  float x_scaled = -1.0, y_scaled = -1.0;
+  if (state == TRACKING_STATE) {
+    #if INTERP_FACTOR == 1
+      int *interp_pixels;
+      interp_pixels = pixels;
+    #else
+      int interp_pixels[NUM_INTERP_PIXELS];
+      interpn(pixels, interp_pixels, SENSOR_XRES, SENSOR_YRES, INTERP_FACTOR);
+    #endif
+
+    // Zero out low pixels to reduce artifacts and noise
+    zeroPixelsBelowThreshold(interp_pixels,NUM_INTERP_PIXELS,(int)(maxpixel/cfg->zero_clamp_threshold_factor)); // zero out pixels below some percent of peak
+    zeroPixelsBelowThreshold(interp_pixels,NUM_INTERP_PIXELS,cfg->zero_clamp_threshold);
+
+    // Find center of mass.
+    float cmx,cmy;
+    if (maxpixel > 0) {
+      int totalmass=0;
+      calcCenterOfMass(interp_pixels, INTERP_XRES, INTERP_YRES, &cmx, &cmy, &totalmass); // only calculate COM if there is a pixel above the noise (avoid divide-by-zero)
+      cmx = cmx/(float)INTERP_FACTOR;
+      cmy = cmy/(float)INTERP_FACTOR;
+    }
+
+    // Scale position according to tracking width/height parameter. This scales to values (0,9) in x, (0,5) in y
+    x_scaled = (cmx - ((float)SENSOR_XRES - cfg->track_width)/2.0f) * (SENSOR_XRES-1)/(cfg->track_width-1);
+    x_scaled = x_scaled >= (SENSOR_XRES-1) ? SENSOR_XRES - 1.001 : x_scaled < 0.0f ? 0.0f : x_scaled;
+    y_scaled = (cmy - ((float)SENSOR_YRES - cfg->track_height)/2.0f) * (SENSOR_YRES-1)/(cfg->track_height-1);
+    y_scaled = y_scaled >= (SENSOR_YRES-1) ? SENSOR_YRES - 1.001 : y_scaled < 0.0f ? 0.0f : y_scaled;
+  }
+
+  // Update gesture result struct
+  gesResult->state = state == TRACKING_STATE ? 1 : 0;
+  gesResult->x = state == TRACKING_STATE ? x_scaled : -1.00f;
+  gesResult->y = state == TRACKING_STATE ? y_scaled : -1.00f;
+  gesResult->maxpixel = maxpixel;
+}