You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
286 lines
7.2 KiB
286 lines
7.2 KiB
#pragma once
|
|
|
|
#include <libopencm3/cm3/common.h>
|
|
#include <libopencm3/stm32/f3/memorymap.h>
|
|
|
|
|
|
// Opamp base address (just one register)
|
|
#define OPAMP1_BASE OPAMP_BASE + 0x38
|
|
#define OPAMP2_BASE OPAMP_BASE + 0x3C
|
|
#define OPAMP3_BASE OPAMP_BASE + 0x40
|
|
#define OPAMP4_BASE OPAMP_BASE + 0x44
|
|
|
|
// opamp constants
|
|
#define OPAMP1 OPAMP1_BASE
|
|
#define OPAMP2 OPAMP2_BASE
|
|
#define OPAMP3 OPAMP3_BASE
|
|
#define OPAMP4 OPAMP4_BASE
|
|
|
|
#define OPAMP_CSR(opamp_base) MMIO32(opamp_base + 0)
|
|
|
|
|
|
#define OPAMP_CSR_LOCK (1 << 31)
|
|
|
|
|
|
#define OPAMP_CSR_OUTCAL (1 << 30)
|
|
|
|
|
|
#define OPAMP_CSR_TSTREF (1 << 29)
|
|
|
|
|
|
// trim registers
|
|
#define OPAMP_CSR_TRIMOFFSETN_SHIFT 24
|
|
#define OPAMP_CSR_TRIMOFFSETP_SHIFT 19
|
|
|
|
#define OPAMP_CSR_TRIMOFFSETN_MSK (0x1F << OPAMP_CSR_TRIMOFFSETN_SHIFT)
|
|
#define OPAMP_CSR_TRIMOFFSETP_MSK (0x1F << OPAMP_CSR_TRIMOFFSETP_SHIFT)
|
|
|
|
|
|
// user trim
|
|
#define OPAMP_CSR_USER_TRIM (1 << 18)
|
|
|
|
|
|
|
|
// PGA gain
|
|
#define OPAMP_CSR_PGA_GAIN_SHIFT 14
|
|
#define OPAMP_CSR_PGA_GAIN_MSK (0b0011 << OPAMP_CSR_PGA_GAIN_SHIFT)
|
|
#define OPAMP_CSR_PGA_MIDPOINT_MSK (0b1100 << OPAMP_CSR_PGA_GAIN_SHIFT)
|
|
|
|
|
|
// lower two bits
|
|
enum OPAMP_PGA_GAIN {
|
|
OPAMP_PGA_GAIN_2 = (0 << OPAMP_CSR_PGA_GAIN_SHIFT),
|
|
OPAMP_PGA_GAIN_4 = (1 << OPAMP_CSR_PGA_GAIN_SHIFT),
|
|
OPAMP_PGA_GAIN_8 = (2 << OPAMP_CSR_PGA_GAIN_SHIFT),
|
|
OPAMP_PGA_GAIN_16 = (3 << OPAMP_CSR_PGA_GAIN_SHIFT)
|
|
};
|
|
|
|
// Masks that can be used to adjust PGA value
|
|
enum OPAMP_PGA_MIDPOINT {
|
|
OPAMP_PGA_MIDPOINT_NONE = 0,
|
|
OPAMP_PGA_MIDPOINT_VM0 = (0b1000 << OPAMP_CSR_PGA_GAIN_SHIFT),
|
|
OPAMP_PGA_MIDPOINT_VM1 = (0b1100 << OPAMP_CSR_PGA_GAIN_SHIFT)
|
|
};
|
|
|
|
|
|
// Calibration select
|
|
#define OPAMP_CSR_CALSEL_SHIFT 12
|
|
#define OPAMP_CSR_CALSEL_MSK (0b11 << OPAMP_CSR_CALSEL_SHIFT)
|
|
|
|
enum OPAMP_CALSEL {
|
|
OPAMP_CALSEL_3P3 = (0 << OPAMP_CSR_CALSEL_SHIFT),
|
|
OPAMP_CALSEL_10 = (1 << OPAMP_CSR_CALSEL_SHIFT),
|
|
OPAMP_CALSEL_50 = (2 << OPAMP_CSR_CALSEL_SHIFT),
|
|
OPAMP_CALSEL_90 = (3 << OPAMP_CSR_CALSEL_SHIFT),
|
|
};
|
|
|
|
|
|
|
|
// Cal On
|
|
#define OPAMP_CSR_CALON (1 << 11)
|
|
|
|
|
|
|
|
// Non-inverting input, secondary
|
|
#define OPAMP_CSR_VPS_SEL_SHIFT 9
|
|
#define OPAMP_CSR_VPS_SEL_MSK (0b11 << OPAMP_CSR_VPS_SEL_SHIFT)
|
|
|
|
enum OPAMP_VPS_SEL {
|
|
OPAMP_VPS_SEL_VP0 = (0 << OPAMP_CSR_VPS_SEL_SHIFT),
|
|
OPAMP_VPS_SEL_VP1 = (1 << OPAMP_CSR_VPS_SEL_SHIFT),
|
|
OPAMP_VPS_SEL_VP2 = (2 << OPAMP_CSR_VPS_SEL_SHIFT),
|
|
OPAMP_VPS_SEL_VP3 = (3 << OPAMP_CSR_VPS_SEL_SHIFT),
|
|
|
|
// The following are just aliases for convenience, mapped for F303.
|
|
// probably should not be included in the library, as they're too specific.
|
|
// same for the following enums.
|
|
OPAMP1_VPS_SEL_PA7 = OPAMP_VPS_SEL_VP0,
|
|
OPAMP1_VPS_SEL_PA5 = OPAMP_VPS_SEL_VP1,
|
|
OPAMP1_VPS_SEL_PA3 = OPAMP_VPS_SEL_VP2,
|
|
OPAMP1_VPS_SEL_PA1 = OPAMP_VPS_SEL_VP3,
|
|
|
|
OPAMP2_VPS_SEL_PD14 = OPAMP_VPS_SEL_VP0,
|
|
OPAMP2_VPS_SEL_PB14 = OPAMP_VPS_SEL_VP1,
|
|
OPAMP2_VPS_SEL_PB0 = OPAMP_VPS_SEL_VP2,
|
|
OPAMP2_VPS_SEL_PA7 = OPAMP_VPS_SEL_VP3,
|
|
|
|
OPAMP3_VPS_SEL_PB13 = OPAMP_VPS_SEL_VP0,
|
|
OPAMP3_VPS_SEL_PA5 = OPAMP_VPS_SEL_VP1,
|
|
OPAMP3_VPS_SEL_PA1 = OPAMP_VPS_SEL_VP2,
|
|
OPAMP3_VPS_SEL_PB0 = OPAMP_VPS_SEL_VP3,
|
|
|
|
OPAMP4_VPS_SEL_PD11 = OPAMP_VPS_SEL_VP0,
|
|
OPAMP4_VPS_SEL_PB11 = OPAMP_VPS_SEL_VP1,
|
|
OPAMP4_VPS_SEL_PA4 = OPAMP_VPS_SEL_VP2,
|
|
OPAMP4_VPS_SEL_PB13 = OPAMP_VPS_SEL_VP3
|
|
};
|
|
|
|
|
|
|
|
// Inverting input, secondary
|
|
#define OPAMP_CSR_VMS_SEL_SHIFT 8
|
|
#define OPAMP_CSR_VMS_SEL_MSK (1 << OPAMP_CSR_VMS_SEL_SHIFT)
|
|
|
|
enum OPAMP_VMS_SEL {
|
|
OPAMP_VMS_SEL_VM0 = (0 << OPAMP_CSR_VMS_SEL_SHIFT),
|
|
OPAMP_VMS_SEL_VM1 = (1 << OPAMP_CSR_VMS_SEL_SHIFT),
|
|
|
|
OPAMP1_VMS_SEL_PC5 = OPAMP_VMS_SEL_VM0,
|
|
OPAMP1_VMS_SEL_PA3 = OPAMP_VMS_SEL_VM1,
|
|
|
|
OPAMP2_VMS_SEL_PC5 = OPAMP_VMS_SEL_VM0,
|
|
OPAMP2_VMS_SEL_PA5 = OPAMP_VMS_SEL_VM1,
|
|
|
|
OPAMP3_VMS_SEL_PB10 = OPAMP_VMS_SEL_VM0,
|
|
OPAMP3_VMS_SEL_PB2 = OPAMP_VMS_SEL_VM1,
|
|
|
|
OPAMP4_VMS_SEL_PB10 = OPAMP_VMS_SEL_VM0,
|
|
OPAMP4_VMS_SEL_PD8 = OPAMP_VMS_SEL_VM1,
|
|
};
|
|
|
|
|
|
|
|
// Cal On
|
|
#define OPAMP_CSR_TCM_EN (1 << 7)
|
|
|
|
|
|
|
|
// Inverting input, primary
|
|
#define OPAMP_CSR_VM_SEL_SHIFT 5
|
|
#define OPAMP_CSR_VM_SEL_MSK (0b11 << OPAMP_CSR_VM_SEL_SHIFT)
|
|
|
|
enum OPAMP_VM_SEL {
|
|
OPAMP_VM_SEL_VM0 = (0 << OPAMP_CSR_VM_SEL_SHIFT),
|
|
OPAMP_VM_SEL_VM1 = (1 << OPAMP_CSR_VM_SEL_SHIFT),
|
|
OPAMP_VM_SEL_PGA = (2 << OPAMP_CSR_VM_SEL_SHIFT),
|
|
OPAMP_VM_SEL_FLW = (3 << OPAMP_CSR_VM_SEL_SHIFT),
|
|
|
|
OPAMP1_VM_SEL_PC5 = OPAMP_VM_SEL_VM0,
|
|
OPAMP1_VM_SEL_PA3 = OPAMP_VM_SEL_VM1,
|
|
OPAMP1_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
|
|
OPAMP1_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
|
|
|
|
OPAMP2_VM_SEL_PC5 = OPAMP_VM_SEL_VM0,
|
|
OPAMP2_VM_SEL_PA5 = OPAMP_VM_SEL_VM1,
|
|
OPAMP2_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
|
|
OPAMP2_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
|
|
|
|
OPAMP3_VM_SEL_PB10 = OPAMP_VM_SEL_VM0,
|
|
OPAMP3_VM_SEL_PB2 = OPAMP_VM_SEL_VM1,
|
|
OPAMP3_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
|
|
OPAMP3_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
|
|
|
|
OPAMP4_VM_SEL_PB10 = OPAMP_VM_SEL_VM0,
|
|
OPAMP4_VM_SEL_PD8 = OPAMP_VM_SEL_VM1,
|
|
OPAMP4_VM_SEL_PGA = OPAMP_VM_SEL_PGA,
|
|
OPAMP4_VM_SEL_FLW = OPAMP_VM_SEL_FLW,
|
|
};
|
|
|
|
|
|
|
|
// Non-inverting input, primary
|
|
#define OPAMP_CSR_VP_SEL_SHIFT 2
|
|
#define OPAMP_CSR_VP_SEL_MSK (0b11 << OPAMP_CSR_VP_SEL_SHIFT)
|
|
|
|
enum OPAMP_VP_SEL {
|
|
OPAMP_VP_SEL_VP0 = (0 << OPAMP_CSR_VP_SEL_SHIFT),
|
|
OPAMP_VP_SEL_VP1 = (1 << OPAMP_CSR_VP_SEL_SHIFT),
|
|
OPAMP_VP_SEL_VP2 = (2 << OPAMP_CSR_VP_SEL_SHIFT),
|
|
OPAMP_VP_SEL_VP3 = (3 << OPAMP_CSR_VP_SEL_SHIFT),
|
|
|
|
OPAMP1_VP_SEL_PA7 = OPAMP_VP_SEL_VP0,
|
|
OPAMP1_VP_SEL_PA5 = OPAMP_VP_SEL_VP1,
|
|
OPAMP1_VP_SEL_PA3 = OPAMP_VP_SEL_VP2,
|
|
OPAMP1_VP_SEL_PA1 = OPAMP_VP_SEL_VP3,
|
|
|
|
OPAMP2_VP_SEL_PD14 = OPAMP_VP_SEL_VP0,
|
|
OPAMP2_VP_SEL_PB14 = OPAMP_VP_SEL_VP1,
|
|
OPAMP2_VP_SEL_PB0 = OPAMP_VP_SEL_VP2,
|
|
OPAMP2_VP_SEL_PA7 = OPAMP_VP_SEL_VP3,
|
|
|
|
OPAMP3_VP_SEL_PB13 = OPAMP_VP_SEL_VP0,
|
|
OPAMP3_VP_SEL_PA5 = OPAMP_VP_SEL_VP1,
|
|
OPAMP3_VP_SEL_PA1 = OPAMP_VP_SEL_VP2,
|
|
OPAMP3_VP_SEL_PB0 = OPAMP_VP_SEL_VP3,
|
|
|
|
OPAMP4_VP_SEL_PD11 = OPAMP_VP_SEL_VP0,
|
|
OPAMP4_VP_SEL_PB11 = OPAMP_VP_SEL_VP1,
|
|
OPAMP4_VP_SEL_PA4 = OPAMP_VP_SEL_VP2,
|
|
OPAMP4_VP_SEL_PB13 = OPAMP_VP_SEL_VP3
|
|
};
|
|
|
|
|
|
|
|
// Forve VP - VP connected to calibration reference
|
|
#define OPAMP_CSR_FORCE_VP (1 << 1)
|
|
|
|
|
|
|
|
// Enable opamp
|
|
#define OPAMP_CSR_OPAMPEN (1 << 0)
|
|
|
|
|
|
// -------------- Functions ----------------
|
|
|
|
/** Lock the opamp config. No way to unlock until restart. */
|
|
void opamp_lock(uint32_t opamp);
|
|
|
|
|
|
/**
|
|
* Enable OPAMP
|
|
* Must also enable RCC_SYSCFG_COMP in RCC
|
|
*/
|
|
void opamp_enable(uint32_t opamp);
|
|
|
|
|
|
/** Disable OPAMP */
|
|
void opamp_disable(uint32_t opamp);
|
|
|
|
|
|
/** Send reference to ADC input channel */
|
|
void opamp_ref_to_adc(uint32_t opamp, bool yes);
|
|
|
|
|
|
/** Send reference to non-inverting input */
|
|
void opamp_ref_to_vp(uint32_t opamp, bool yes);
|
|
|
|
|
|
/**
|
|
* Set PGA gain.
|
|
* To use PGA, call opamp_mode_pga() first.
|
|
*/
|
|
void opamp_pga_set_gain(uint32_t opamp, enum OPAMP_PGA_GAIN gain);
|
|
|
|
|
|
/** Set PGA midpoint routing */
|
|
void opamp_pga_set_midpoint(uint32_t opamp, enum OPAMP_PGA_MIDPOINT midpoint);
|
|
|
|
|
|
/** Connect VM pin (can be used to select follower and PGA mode) */
|
|
void opamp_vm_select(uint32_t opamp, enum OPAMP_VM_SEL vm);
|
|
|
|
|
|
/** Connect the VP pin */
|
|
void opamp_vp_select(uint32_t opamp, enum OPAMP_VP_SEL vp);
|
|
|
|
|
|
/**
|
|
* Set opamp to PGA mode (shortcut function)
|
|
* Midpoint can be connected to VM pins with opamp_pga_set_midpoint()
|
|
*/
|
|
void opamp_mode_pga(uint32_t opamp);
|
|
|
|
|
|
/**
|
|
* Set opamp to follower mode (shortcut function).
|
|
* VM is not connected to GPIO in this mode.
|
|
*/
|
|
void opamp_mode_follower(uint32_t opamp);
|
|
|
|
|
|
/** Select reference value to use */
|
|
void opamp_ref_select(uint32_t opamp, enum OPAMP_CALSEL ref);
|
|
|
|
|
|
/** Calibrate an OpAmp */
|
|
bool opamp_calibrate(uint32_t opamp);
|
|
|