mirror of
https://github.com/openglow-org/forgefirm.git
synced 2026-09-27 08:41:13 -07:00
An ESP32-S3 DevKitC-1 on the bench network drives three relays at the machine's connectors so the acceptance tool can open the lid loop, pull the interlock loop and press the button with nobody in the room. Two contacts are normally closed in loops the safety chain already reads, the third is normally open across the button input and only ever pulsed (20 to 500 ms, the end armed before the line rises); every line is low at boot and after any reset, the task watchdog panics and reboots, and the button channel needs a jumper. HTTP on port 80 under a key in X-Fixture-Key; the hostname announced over DHCP and mDNS. ESP-IDF v5.5 native, the mDNS component pinned in dependencies.lock; fixture.env (git-ignored) is the one input: the wifi, the key, the hostname. fixture.sh builds with idf.py or in the espressif/idf container, flashes with esptool from pip. The decisions that need no hardware live in policy.c with a gcc host test; CI runs it and builds the firmware in the pinned container.
48 lines
1.5 KiB
C
48 lines
1.5 KiB
C
/*
|
|
* forgefixture relays: the three channels on their GPIOs, the button's
|
|
* pulse timer, and the enable jumper that gates the button.
|
|
*
|
|
* (C) Copyright 2026
|
|
* Scott Wiederhold, s.e.wiederhold@gmail.com
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
#pragma once
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include "esp_err.h"
|
|
#include "policy.h"
|
|
|
|
/* DevKitC-1 pins with no strapping, USB, flash or PSRAM role. Active
|
|
* high into the relay modules' opto inputs. */
|
|
#define RELAY_GPIO_LID 4
|
|
#define RELAY_GPIO_INTERLOCK 5
|
|
#define RELAY_GPIO_BUTTON 6
|
|
/* The enable jumper for the button channel: input with the pull-up on,
|
|
* the jumper shorts it to GND. No jumper = high = button disabled. */
|
|
#define ENABLE_GPIO_BUTTON 7
|
|
|
|
typedef struct {
|
|
bool energized[CH_COUNT];
|
|
bool button_enabled; /* the jumper is in */
|
|
bool button_pulsing; /* a press is in progress */
|
|
} relays_state_t;
|
|
|
|
/* Every line low before anything else runs. */
|
|
void relays_init(void);
|
|
|
|
/* Lid or interlock: hold the channel energized (loop open) or released
|
|
* (loop closed). ESP_ERR_INVALID_ARG for the button, which is never
|
|
* held. */
|
|
esp_err_t relays_set_loop(channel_t ch, bool energize);
|
|
|
|
/* The button: one pulse of `ms` (already clamped by policy_button_ms).
|
|
* ESP_ERR_NOT_ALLOWED without the enable jumper, ESP_ERR_INVALID_STATE
|
|
* while a pulse is still in progress. */
|
|
esp_err_t relays_pulse_button(int ms);
|
|
|
|
/* Everything low, a pulse in progress cut short. */
|
|
void relays_release(void);
|
|
|
|
relays_state_t relays_state(void);
|