timdac/inc/timdac_ll.h

107 lines
4.2 KiB
C

// intellectual property is bullshit bgdc
#ifndef TIMDAC_LL_H
#define TIMDAC_LL_H
// ============================================================================
// TIMDAC LOW LEVEL DRIVER
// ----------------------------------------------------------------------------
// This module provides the low-level (but still hardware-abstracted) part of
// TIMDAC. It implements the state machine that provides each individual cycle
// of operation, but must be sequenced through cycles correctly. You are not
// generally meant to use it directly; see the high-level interface in timdac.h
// which handles this sequencing.
// ============================================================================
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
// Diagnostic info struct. If TIMDAC_DIAGNOSTIC is defined nonzero, this is the
// struct that timdac_ll_diagnostic() will fill.
typedef struct timdac_lldiag_s {
// Total number of tuning cycles run (will overflow)
uint16_t cycles;
// Tuning clobber counter.
uint16_t clobbers;
// Current tune value.
uint16_t tune;
// Tuning noise accumulator. This will hold the sum of the squares of
// the tuning errors, and will be reset to zero each time cycles wraps
// around. To get the RMS tuning noise, divide this by cycles, take
// the square root, then divide by 65536.
uint64_t noise;
} timdac_lldiag_t;
// Initialize the DAC.
void timdac_ll_init(void);
// Initiate a tuning cycle. Once the tuning cycle has been started, it will
// proceed through a sequence as stepped through by timdac_ll_poll(). Note that
// a full tuning requires multiple cycles -- the initial tuning is not complete
// until timdac_ll_tuned() returns true.
//
// Undefined (analog) behavior will be produced if this is called when
// timdac_ll_poll() is not yet returning false. Don't do that.
//
// Returns whether the timer is now busy. If not, this "cycle" was
// purely computational and has completed immediately.
bool timdac_ll_tune(void);
// Start to emit a voltage on a channel. Once the cycle has been started, it
// will proceed through a sequence as stepped through by timdac_ll_poll().
//
// Undefined (analog) behavior will be produced if this is called when
// timdac_ll_poll() is not yet returning false. Don't do that.
//
// chan: channel number to select; will be passed to the hardware driver
// value: DAC code to emit
// slow: whether to perform a slow transfer at the end of the cycle
void timdac_ll_emit(uint8_t chan, int16_t value, bool slow);
// Run one step of the low-level DAC process. Should be called from
// timdac_poll() every time the timer stops. Returns whether the timer is now
// busy - if not, the last cycle finished and a new one may be started.
bool timdac_ll_poll(void);
// Run a single idle cycle. This can be used to kickstart an interrupt driven
// timdac. If the timdac is not already at the idle state, does nothing.
void timdac_ll_idle(void);
// Return whether the first tuning cycle has completed. Scanning should not
// begin until the DAC has been tuned.
bool timdac_ll_tuned(void);
// Get low-level diagnostics. TIMDAC_DIAGNOSTIC must be defined in
// timdac_config.h for this to work; otherwise the struct will be filled with
// zeros.
//
// This is the only low-level function that may be called by normal users
// rather than the high-level driver, but it is probably not of much interest
// to them.
void timdac_ll_diagnostic(timdac_lldiag_t * diag);
// ----------------------------------------------------------------------------
// HARDWARE DRIVER INTERFACE
// These functions are implemented by each hardware driver.
void timdac_hw_init(void);
void timdac_hw_timer_set_period(uint16_t counts);
void timdac_hw_timer_set_compare(uint16_t counts);
void timdac_hw_timer_set_oc_enabled(bool en);
void timdac_hw_timer_start(void);
bool timdac_hw_timer_running(void);
void timdac_hw_gpio_muxinhibit(bool en);
void timdac_hw_gpio_discharge(bool en);
void timdac_hw_gpio_polarity(bool pos);
void timdac_hw_gpio_select_channel(uint8_t chan);
bool timdac_hw_gpio_tune_is_high(void);
// This is a high-level function, but declared here as it is never meant to be
// called by the user. Instead, the hardware driver will call it from an ISR.
void timdac_poll(void);
#endif // !defined(TIMDAC_LL_H)