/* * Copyright (C) 2023 Daniele Lacamera * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . */ #include #include "adc.h" /* ADC */ #define APB2_CLOCK_ER (*(volatile uint32_t *)(0x40023844)) #define ADC3_APB2_CLOCK_ER_VAL (1 << 10) #define ADC3_BASE (0x40012200) #define ADC_COM_BASE (0x40012300) #define ADC_COM_CCR (*(volatile uint32_t *)(ADC_COM_BASE + 0x04)) #define ADC3_SR (*(volatile uint32_t *)(ADC3_BASE + 0x00)) #define ADC3_CR1 (*(volatile uint32_t *)(ADC3_BASE + 0x04)) #define ADC3_CR2 (*(volatile uint32_t *)(ADC3_BASE + 0x08)) #define ADC3_SMPR1 (*(volatile uint32_t *)(ADC3_BASE + 0x0c)) #define ADC3_SMPR2 (*(volatile uint32_t *)(ADC3_BASE + 0x10)) #define ADC3_SQR3 (*(volatile uint32_t *)(ADC3_BASE + 0x34)) #define ADC3_DR (*(volatile uint32_t *)(ADC3_BASE + 0x4c)) #define ADC_CR1_SCAN (1 << 8) #define ADC_CR2_EN (1 << 0) #define ADC_CR2_CONT (1 << 1) #define ADC_CR2_SWSTART (1 << 30) #define ADC_SR_EOC (1 << 1) #define ADC_SMPR_SMP_480CYC (0x7) // A0: ADC3_IN0 // F6: ADC3_IN4 // F8: ADC3_IN6 // F9: ADC3_IN7 int adc_init(void) { int i; uint32_t val; /* Enable clock */ APB2_CLOCK_ER |= ADC3_APB2_CLOCK_ER_VAL; /* Power off */ ADC3_CR2 &= ~(ADC_CR2_EN); /* Set common clock prescaler */ ADC_COM_CCR &= ~(0x03 << 16); /* Disable scan mode */ ADC3_CR1 &= ~(ADC_CR1_SCAN); /* Set one-shot (disable continuous mode) */ ADC3_CR2 &= ~(ADC_CR2_CONT); /* Set sample time for all channels */ val = ADC3_SMPR1; for (i = 0; i < 10; i++) { val |= ADC_SMPR_SMP_480CYC << (i * 3); ADC3_SMPR1 = val; val = ADC3_SMPR2; for (i = 10; i < 18; i++) val |= ADC_SMPR_SMP_480CYC << ((i-10) * 3); } ADC3_SMPR2 = val; ADC3_CR2 &= ~(ADC_CR2_EN); return 0; } void pot_read(uint32_t *potl, uint32_t *potr) { if (potl) { ADC3_SQR3 |= (POTL_CHANNEL); ADC3_CR2 |= ADC_CR2_EN; ADC3_CR2 |= ADC_CR2_SWSTART; while (ADC3_CR2 & ADC_CR2_SWSTART);; while ((ADC3_SR & ADC_SR_EOC) == 0);; *potl = ADC3_DR; if (*potl < 15) *potl = 0; if (*potl > 4080) *potl = 4096; ADC3_SQR3 &= ~(POTL_CHANNEL); } if (potr) { ADC3_SQR3 |= (POTR_CHANNEL); ADC3_CR2 |= ADC_CR2_EN; ADC3_CR2 |= ADC_CR2_SWSTART; while (ADC3_CR2 & ADC_CR2_SWSTART);; while ((ADC3_SR & ADC_SR_EOC) == 0);; *potr = ADC3_DR; if (*potr < 15) *potr = 0; if (*potr > 4080) *potr = 4096; ADC3_SQR3 &= ~(POTR_CHANNEL); } } void joy_read(uint32_t *joy_x, uint32_t *joy_y) { if (joy_x) { ADC3_SQR3 |= (JOYX_CHANNEL); ADC3_CR2 |= ADC_CR2_EN; ADC3_CR2 |= ADC_CR2_SWSTART; while (ADC3_CR2 & ADC_CR2_SWSTART);; while ((ADC3_SR & ADC_SR_EOC) == 0);; *joy_x = ADC3_DR; ADC3_SQR3 &= ~(JOYX_CHANNEL); } if (joy_y) { ADC3_SQR3 |= (JOYY_CHANNEL); ADC3_CR2 |= ADC_CR2_EN; ADC3_CR2 |= ADC_CR2_SWSTART; while (ADC3_CR2 & ADC_CR2_SWSTART);; while ((ADC3_SR & ADC_SR_EOC) == 0);; *joy_y = ADC3_DR; ADC3_SQR3 &= ~(JOYY_CHANNEL); } }