timdac/src/timdac.h

75 lines
2.6 KiB
C

// intellectual property is bullshit bgdc
#ifndef TIMDAC_H
#define TIMDAC_H
// ============================================================================
// TIMDAC
// ----------------------------------------------------------------------------
//
// NOTE - estimated CPU utilization - 0.9% at 72 MHz, 12.25us total
// (5.48us discharge, 2.29us pulse, 2.14us stabilize, 2.29us transfer) across a
// 1.29ms cycle
// ============================================================================
#include <stdbool.h>
#include <stddef.h>
#include <inttypes.h>
#include <stdatomic.h>
#include <signal.h>
#include "timdac_ll.h"
#define TIMDAC_SCANNER_MAX_CHANNELS 32
// timdac_scanner provides a higher level interface to timdac, allowing the
// user to simply write output values as they need changing. When in use, it
// takes full ownership of the timdac; you should never call any timdac_
// functions including timdac_init().
typedef struct timdac_s {
// #### BEGIN - USER MUST INITIALIZE ####
// Pointer to the timdac low-level instance in use
timdac_ll_t * td;
// Array of output channel values
atomic_uint * channels;
// Number of channels, must be no more than TIMDAC_SCANNER_MAX_CHANNELS
uint8_t n_channels;
// #### END - USER MUST INITIALIZE ####
sig_atomic_t volatile chan; // Current channel number
sig_atomic_t volatile count; // How many channels have been emitted since tuning
atomic_uint pend; // A pending immediate-update channel
} timdac_t;
// Initialize the DAC and DAC scanner. You must have filled in the "USER MUST
// INITIALIZE" fields in the struct.
void timdac_init(timdac_t * tds);
// Start the scanner, if using interrupts. If you are not using interrupts,
// simply poll in a loop when you want to run - do not call this.
void timdac_start(timdac_t * tds);
// Set a new value for an output channel. If no other channel has a pending
// immediate update, this channel will also be added to the pend slot so that
// it can be updated as soon as the DAC is ready without waiting for a full
// cycle.
//
// Returns true on success. Only fails on an invalid channel number.
bool timdac_set(timdac_t * tds, uint8_t chan, int32_t value);
// Return whether an update is currently pending. Only one channel can hold the
// pending slot at a time, so if you post an update while another channel is
// pending, the newer update will not be written to the output until it is
// next hit in the normal scanning cycle. To ensure the fastest update, you
// can poll for this flag to clear before calling timdac_set().
bool timdac_pending(timdac_t * tds);
// Poll the scanner. Should be called periodically.
void timdac_poll(timdac_t * tds);
#endif // !defined(TIMDAC_H)