Skip to content

Commit

Permalink
adc_touch: Add adc handler for nrfx/stm32f7/stm32f4
Browse files Browse the repository at this point in the history
adc_touch driver requires code that actually reads ADC.
This change provides implementations for nrfx and two STM32 families.

Signed-off-by: Jerzy Kasenberg <jerzy.kasenberg@codecoup.pl>
  • Loading branch information
kasjer committed May 18, 2023
1 parent 1fe7cb6 commit e400681
Show file tree
Hide file tree
Showing 8 changed files with 628 additions and 0 deletions.
31 changes: 31 additions & 0 deletions hw/drivers/display/lvgl/touch/adc_touch/adc_nrfx/pkg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

pkg.name: hw/drivers/display/lvgl/touch/adc_touch/adc_nrfx
pkg.description: ADC driver for touch driver
pkg.keywords:
- display
- touch
- nrfx

pkg.apis:
- adc_touch_adc

pkg.deps:
- hw/drivers/display/lvgl/touch/adc_touch
117 changes: 117 additions & 0 deletions hw/drivers/display/lvgl/touch/adc_touch/adc_nrfx/src/adc_nrfx.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include <assert.h>

#include <os/os.h>

#include <adc_nrf52/adc_nrf52.h>
#include <nrf_saadc.h>
#include <adc_touch.h>

static adc_dev_t adc_dev;

static struct ain_pin {
int pin;
nrf_saadc_input_t ain;
} const ain_pins[8] = {
#if defined (NRF52)
{2, NRF_SAADC_INPUT_AIN0},
{3, NRF_SAADC_INPUT_AIN1},
{4, NRF_SAADC_INPUT_AIN2},
{5, NRF_SAADC_INPUT_AIN3},
{28, NRF_SAADC_INPUT_AIN4},
{29, NRF_SAADC_INPUT_AIN5},
{30, NRF_SAADC_INPUT_AIN6},
{31, NRF_SAADC_INPUT_AIN7},
#elif defined (NRF53_SERIES)
{4, NRF_SAADC_INPUT_AIN0},
{5, NRF_SAADC_INPUT_AIN1},
{6, NRF_SAADC_INPUT_AIN2},
{7, NRF_SAADC_INPUT_AIN3},
{25, NRF_SAADC_INPUT_AIN4},
{26, NRF_SAADC_INPUT_AIN5},
{27, NRF_SAADC_INPUT_AIN6},
{28, NRF_SAADC_INPUT_AIN7},
#endif
};

static struct adc_chan_cfg adc_x = {
.acq_time = ADC_ACQTIME_40US,
.differential = false,
.gain = ADC_GAIN1_4,
.pin = NRF_SAADC_INPUT_DISABLED,
.pin_negative = NRF_SAADC_INPUT_DISABLED,
.reference = ADC_REFERENCE_VDD_DIV_4,
};

static struct adc_chan_cfg adc_y = {
.acq_time = ADC_ACQTIME_40US,
.differential = false,
.gain = ADC_GAIN1_4,
.pin = NRF_SAADC_INPUT_DISABLED,
.pin_negative = NRF_SAADC_INPUT_DISABLED,
.reference = ADC_REFERENCE_VDD_DIV_4,
};

static int adc_x_pin;
static int adc_y_pin;

adc_dev_t
adc_touch_adc_open(int x_pin, int y_pin)
{
struct adc_dev_cfg adc_cfg = {
.calibrate = 1,
.oversample = ADC_OVERSAMPLE_DISABLED,
.resolution = ADC_RESOLUTION_14BIT,
};
for (int i = 0; i < ARRAY_SIZE(ain_pins); ++i) {
if (x_pin == ain_pins[i].pin) {
adc_x.pin = ain_pins[i].ain;
adc_x_pin = x_pin;
}
if (y_pin == ain_pins[i].pin) {
adc_y.pin = ain_pins[i].ain;
adc_y_pin = y_pin;
}
}
assert(adc_x.pin != NRF_SAADC_INPUT_DISABLED);
assert(adc_y.pin != NRF_SAADC_INPUT_DISABLED);
adc_dev = (struct adc_dev *)os_dev_open("adc0", 0, &adc_cfg);
adc_chan_config(adc_dev, 0, &adc_x);
adc_chan_config(adc_dev, 1, &adc_y);

return adc_dev;
}

uint16_t
adc_touch_adc_read(adc_dev_t adc, int pin)
{
int val = -1;

(void)adc;

if (pin == adc_x_pin) {
adc_read_channel(adc_dev, 0, &val);
} else if (pin == adc_y_pin) {
adc_read_channel(adc_dev, 1, &val);
}

return (uint16_t)val;
}
30 changes: 30 additions & 0 deletions hw/drivers/display/lvgl/touch/adc_touch/adc_stm32f4/pkg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

pkg.name: hw/drivers/display/lvgl/touch/adc_touch/adc_stm32f4
pkg.description: ADC driver for touch driver
pkg.keywords:
- display
- touch

pkg.apis:
- adc_touch_adc

pkg.deps:
- hw/drivers/display/lvgl/touch/adc_touch
179 changes: 179 additions & 0 deletions hw/drivers/display/lvgl/touch/adc_touch/adc_stm32f4/src/adc_stm32f4.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

#include <assert.h>

#include <os/os.h>

#include <stm32_common/mcu.h>

#include <stm32f4xx_hal_dma.h>
#include <stm32f4xx_hal_adc.h>
#include <stm32f4xx_hal_rcc.h>
#include <stm32f4xx_hal_gpio.h>
#include <mcu/stm32_hal.h>
#include <adc_touch.h>

#define ADC_ASYNC 1

static struct adc_pin {
int pin;
uint32_t adc_channel;
} const adc_pins[] = {
{MCU_GPIO_PORTA(0), ADC_CHANNEL_0},
{MCU_GPIO_PORTA(1), ADC_CHANNEL_1},
{MCU_GPIO_PORTA(2), ADC_CHANNEL_2},
{MCU_GPIO_PORTA(3), ADC_CHANNEL_3},
{MCU_GPIO_PORTA(4), ADC_CHANNEL_4},
{MCU_GPIO_PORTA(5), ADC_CHANNEL_5},
{MCU_GPIO_PORTA(6), ADC_CHANNEL_6},
{MCU_GPIO_PORTA(7), ADC_CHANNEL_7},
{MCU_GPIO_PORTB(0), ADC_CHANNEL_8},
{MCU_GPIO_PORTB(1), ADC_CHANNEL_9},
{MCU_GPIO_PORTC(0), ADC_CHANNEL_10},
{MCU_GPIO_PORTC(1), ADC_CHANNEL_11},
{MCU_GPIO_PORTC(2), ADC_CHANNEL_12},
{MCU_GPIO_PORTC(3), ADC_CHANNEL_13},
{MCU_GPIO_PORTC(4), ADC_CHANNEL_14},
{MCU_GPIO_PORTC(5), ADC_CHANNEL_15},
};

#define ADC_CHANNEL_NONE 0xFFFFFFFF

static ADC_ChannelConfTypeDef adc_x = {
.Channel = ADC_CHANNEL_4,
.Rank = 1,
.SamplingTime = ADC_SAMPLETIME_84CYCLES,
.Offset = 0,
};

static ADC_ChannelConfTypeDef adc_y = {
.Channel = ADC_CHANNEL_1,
.Rank = 1,
.SamplingTime = ADC_SAMPLETIME_84CYCLES,
.Offset = 0,
};

static int adc_x_pin;
static int adc_y_pin;

ADC_HandleTypeDef adc_handle = {
.Instance = ADC1,
.Init = {
.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2,
.Resolution = ADC_RESOLUTION_12B,
.DataAlign = ADC_DATAALIGN_RIGHT,
.ScanConvMode = DISABLE,
.EOCSelection = DISABLE,
.ContinuousConvMode = DISABLE,
.NbrOfConversion = 1,
.DiscontinuousConvMode = DISABLE,
.NbrOfDiscConversion = 0,
.ExternalTrigConv = ADC_SOFTWARE_START,
.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE,
.DMAContinuousRequests = DISABLE,
},
};

void
ADC_IRQHandler(void)
{
HAL_ADC_IRQHandler(&adc_handle);
}

adc_dev_t
adc_touch_adc_open(int x_pin, int y_pin)
{
for (int i = 0; i < ARRAY_SIZE(adc_pins); ++i) {
if (x_pin == adc_pins[i].pin) {
adc_x.Channel = adc_pins[i].adc_channel;
adc_x_pin = x_pin;
}
if (y_pin == adc_pins[i].pin) {
adc_y.Channel = adc_pins[i].adc_channel;
adc_y_pin = y_pin;
}
}
__HAL_RCC_ADC1_CLK_ENABLE();
HAL_ADC_Init(&adc_handle);
NVIC_SetVector(ADC_IRQn, (uint32_t)ADC_IRQHandler);
assert(adc_x.Channel != ADC_CHANNEL_NONE);
assert(adc_y.Channel != ADC_CHANNEL_NONE);

return &adc_handle;
}

static struct os_sem adc_sem;

void
HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
(void)hadc;

os_sem_release(&adc_sem);
}

uint16_t
adc_touch_adc_read(adc_dev_t adc, int pin)
{
int val = -1;
int rc;
ADC_HandleTypeDef *stm_adc = adc;
ADC_ChannelConfTypeDef *channel_config = NULL;
GPIO_InitTypeDef gpio_analog_init = {
.Mode = GPIO_MODE_ANALOG,
.Pull = GPIO_NOPULL,
.Alternate = 0
};

os_sem_init(&adc_sem, 0);

if (pin == adc_x_pin) {
channel_config = &adc_x;
} else if (pin == adc_y_pin) {
channel_config = &adc_y;
}
if (channel_config) {
hal_gpio_init_stm(pin, &gpio_analog_init);
HAL_ADC_ConfigChannel(stm_adc, channel_config);
NVIC_ClearPendingIRQ(ADC_IRQn);
if (ADC_ASYNC) {
rc = HAL_ADC_Start_IT(stm_adc);
if (rc == HAL_OK) {
NVIC_EnableIRQ(ADC_IRQn);
if (os_sem_pend(&adc_sem, 1000) == OS_TIMEOUT) {
HAL_ADC_Stop_IT(stm_adc);
} else {
val = (uint16_t) HAL_ADC_GetValue(stm_adc);
}
NVIC_DisableIRQ(ADC_IRQn);
}
} else {
rc = HAL_ADC_Start(stm_adc);
if (rc == HAL_OK) {
rc = HAL_ADC_PollForConversion(stm_adc, 1000);
if (rc == HAL_OK) {
val = (uint16_t) HAL_ADC_GetValue(stm_adc);
}
}
}
}

return (uint16_t)val;
}
30 changes: 30 additions & 0 deletions hw/drivers/display/lvgl/touch/adc_touch/adc_stm32f7/pkg.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
#

pkg.name: hw/drivers/display/lvgl/touch/adc_touch/adc_stm32f7
pkg.description: ADC driver for touch driver
pkg.keywords:
- display
- touch

pkg.apis:
- adc_touch_adc

pkg.deps:
- hw/drivers/display/lvgl/touch/adc_touch

0 comments on commit e400681

Please sign in to comment.