main
John Lauer Rev 2: aim, status-dot lights, Adafruit 1317 battery, rev 2 cost, revisions, firmware 363a22f 1d ago
/*
 * board.h : Ghost Hand rev A pin map and board constants
 *
 * MCU: ATtiny1616-MNR (tinyAVR 1-series, VQFN-20), 3.3 V from a TPS7A0233 LDO.
 * Source of truth: design/netlist.json (U1) and design/calcs.json.
 *
 *  VQFN pin | Port | Net            | Function used by the firmware
 *  ---------+------+----------------+--------------------------------------------
 *     19    | PA0  | UPDI           | programming only
 *     20    | PA1  | CHG_STAT       | input, MCP73831 STAT via 68k/100k (low = charging)
 *      1    | PA2  | ACC_INT1       | input, LIS2DW12 INT1, fully async pin (wakes power-down)
 *      2    | PA3  | IR940_G        | TCB1 WO (default PORTMUX), 2 x 940 nm emitters
 *      5    | PA4  | RX_PWR         | GPIO high = TLV9062 receiver and RX_REF bias on
 *      6    | PA5  | IR850_G        | TCB0 WO (default PORTMUX), 850 nm emitter
 *      7    | PA6  | VBAT_SENSE     | ADC0 AIN6, VBAT/2 from an always-on 4.7M/4.7M divider
 *      8    | PA7  | RX_SIG         | AC0 AINP0 (receiver output)
 *     14    | PB0  | SCL            | TWI0 SCL (default pins), 4.7k pull-up
 *     13    | PB1  | SDA            | TWI0 SDA (default pins), 4.7k pull-up
 *     12    | PB2  | VBUS_SENSE     | input, 5 V USB -> 3.0 V, fully async pin
 *     11    | PB3  | (unconnected)  | input with pull-up (was VBAT_SENSE_EN on the first draft)
 *     10    | PB4  | LED_EN_N       | output, low = WS2812 rail on (P-FET Q3)
 *      9    | PB5  | LED_DIN        | output, WS2812B-2020 data (bit-banged)
 *     15    | PC0  | ACC_INT2       | input, unused by this firmware
 *     16    | PC1  | (unused)       | input with pull-up
 *     17    | PC2  | ECHO_EVT       | EVOUT2 debug output (AC0 event) during a session
 *     18    | PC3  | (unused)       | input with pull-up
 */
#ifndef BOARD_H
#define BOARD_H

#ifndef F_CPU
#define F_CPU 5000000UL            /* OSC20M (20 MHz fuse) / 4 */
#endif

/* ---- PORTA ---- */
#define PIN_CHG_STAT      1        /* PA1 */
#define PIN_ACC_INT1      2        /* PA2 */
#define PIN_IR940_G       3        /* PA3, TCB1 WO */
#define PIN_RX_PWR        4        /* PA4 */
#define PIN_IR850_G       5        /* PA5, TCB0 WO */
#define PIN_VBAT_SENSE    6        /* PA6, ADC0 AIN6 */
#define PIN_RX_SIG        7        /* PA7, AC0 AINP0 */

/* ---- PORTB ---- */
#define PIN_SCL           0        /* PB0 */
#define PIN_SDA           1        /* PB1 */
#define PIN_VBUS_SENSE    2        /* PB2 */
#define PIN_PB3_UNUSED    3        /* PB3, no longer connected */
#define PIN_LED_EN_N      4        /* PB4 */
#define PIN_LED_DIN       5        /* PB5 */

/* ---- PORTC ---- */
#define PIN_ACC_INT2      0        /* PC0 */
#define PIN_PC1_UNUSED    1
#define PIN_ECHO_EVT      2        /* PC2, EVOUT2 */
#define PIN_PC3_UNUSED    3

/* ---- LEDs ---- */
#define LED_COUNT         5        /* chain: 0 = D4 STATUS dot, 1..4 = D5..D8 gauge 25/50/75/100 % */
#define LED_STATUS        0        /* rev 2: the status dot shows what the rev 1 logo showed */
#define LED_GAUGE0        1

/* ---- Accelerometer ---- */
#define ACC_I2C_ADDR      0x19     /* LIS2DW12, SA0 tied high */

/*
 * Resting orientation of the device in accelerometer axes (unit vector * 1000 mg).
 * The case stands the board so that +Z points up when it sits on the counter.
 * If the case puts the board on edge, change this (e.g. X = -1000 for "board
 * vertical, IR window facing the faucet"). Only used for the "level-ish" check
 * before a session starts; pick-up and tilt are measured against the actual
 * orientation captured at set-down.
 */
#define REST_X_MG         0
#define REST_Y_MG         0
#define REST_Z_MG         1000

/* ---- Timing and thresholds (calcs.json "timing") ---- */
#define SESSION_CAP_MS        600000UL   /* hard 10 minute cap */
#define SETTLE_STILL_MS       1500U      /* still and level for 1.5 s -> session */
#define SETTLE_GIVEUP_MS      15000U     /* no set-down within 15 s -> sleep */
#define GAUGE_SHOW_MS         3000U      /* charge shown at session start */
#define LISTEN_MS             2000U      /* listen with echo disabled */
#define LISTEN_MAX_MS         5000U      /* extend if the faucet pulses slowly */
#define STILL_TOL_MG          60         /* still = within 60 mg of the anchor sample */
#define PICKUP_DELTA_MG       250        /* 0.25 g change vs set-down vector -> stop */
#define TILT_LIMIT_DEG        30         /* > 30 deg from rest -> stop / not level */
#define LOW_BATT_MV           3450U      /* stop under load below this */
#define NO_LIGHT_BATT_MV      3330U      /* below this, do not even light the red LED */
#define BATT_CHECK_MS         10000U     /* battery re-check period in a session */

/* ---- Echo limits (calcs.json "echo") ---- */
#define ECHO_EXTRA_US         5          /* echo = faucet pulse + 5 us */
#define ECHO_MIN_US           8
#define ECHO_MAX_US           40         /* emitter limit: <= 40 us */
#define ECHO_DEFAULT_US       25         /* used when no width was measured */
#define ECHO_BLANK_US         150        /* comparator blanking after each echo */
#define ECHO_DUTY_WINDOW_MS   10         /* duty guard window */
#define ECHO_DUTY_MAX_US      200        /* <= 2 % of 10 ms */
#define EMITTER_ROTATE_MS     300        /* 850 / 940 / both rotation ("moving hand") */
#define PULSE_GROUP_MS        3          /* pulses closer than this = one interrogation */

/* ---- Receiver threshold (DAC0 against VREF 1.1 V) ---- */
#define RX_REF_MV             300        /* nominal RX_REF bias */
#define RX_THRESH_OVER_MV     60         /* threshold = noise floor + 60 mV */
#define RX_THRESH_MIN_MV      330
#define RX_THRESH_MAX_MV      1000
#define RX_SETTLE_MS          60         /* RX_REF: 1 uF with ~9 k -> 9 ms tau */

/* ---- LED current cap ----
 * WS2812B-2020-V6: 12 mA per colour channel at full scale. Rev 2 lights are
 * 1.5 mm clear-resin dots sitting right on each LED, so a dot looks several
 * times brighter than rev 1's spread-out logo at the same drive: the levels in
 * leds.c are about half of rev 1's, and the cap is 640 (~30 mA for all five)
 * to keep the 150 mAh cell's peak load low (0.2 C) and the 3.3 V LDO well
 * under its 60 mA budget with the MCU and receiver (about 4 mA). */
#define LED_SUM_MAX           640

#endif