107 lines
4.2 KiB
C
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)
|