From 1315d5c5fa8611aef5368fb126834277e285a189 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Tue, 5 Jan 2016 16:32:59 +0100 Subject: [PATCH] Create opamp.h --- opamp.h | 283 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 283 insertions(+) create mode 100644 opamp.h diff --git a/opamp.h b/opamp.h new file mode 100644 index 0000000..5ee8f6b --- /dev/null +++ b/opamp.h @@ -0,0 +1,283 @@ +#pragma once + +#include +#include + + +// 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);