parent
6440543da1
commit
1315d5c5fa
@ -0,0 +1,283 @@ |
||||
#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), |
||||
|
||||
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); |
Loading…
Reference in new issue