Initial HW PWM (Delta-Sigma) (#609)

This commit is contained in:
Zaltora 2018-05-19 23:47:29 +02:00 committed by Ruslan V. Uss
parent 10f361c8ca
commit 4dc7d825bc
6 changed files with 238 additions and 11 deletions

View file

@ -70,7 +70,7 @@ struct GPIO_REGS {
uint32_t volatile STATUS_SET; // 0x20 uint32_t volatile STATUS_SET; // 0x20
uint32_t volatile STATUS_CLEAR; // 0x24 uint32_t volatile STATUS_CLEAR; // 0x24
uint32_t volatile CONF[16]; // 0x28 - 0x64 uint32_t volatile CONF[16]; // 0x28 - 0x64
uint32_t volatile PWM; // 0x68 uint32_t volatile DSM; // 0x68
uint32_t volatile RTC_CALIB; // 0x6c uint32_t volatile RTC_CALIB; // 0x6c
uint32_t volatile RTC_CALIB_RESULT; // 0x70 uint32_t volatile RTC_CALIB_RESULT; // 0x70
}; };
@ -117,9 +117,9 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size");
* GPIO_CONF_OPEN_DRAIN does not appear to work on all pins. * GPIO_CONF_OPEN_DRAIN does not appear to work on all pins.
* *
* *
* GPIO_CONF_SOURCE_PWM (boolean) * GPIO_CONF_SOURCE_DSM (boolean)
* When set, GPIO pin output will be connected to the sigma-delta PWM * When set, GPIO pin output will be connected to the sigma-delta
* generator (controlled by the GPIO.PWM register). When cleared, pin * generator (controlled by the GPIO.DSM register). When cleared, pin
* output will function as a normal GPIO output (controlled by the * output will function as a normal GPIO output (controlled by the
* GPIO.OUT* registers). * GPIO.OUT* registers).
*/ */
@ -130,7 +130,7 @@ _Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size");
#define GPIO_CONF_INTTYPE_M 0x00000007 #define GPIO_CONF_INTTYPE_M 0x00000007
#define GPIO_CONF_INTTYPE_S 7 #define GPIO_CONF_INTTYPE_S 7
#define GPIO_CONF_OPEN_DRAIN BIT(2) #define GPIO_CONF_OPEN_DRAIN BIT(2)
#define GPIO_CONF_SOURCE_PWM BIT(0) #define GPIO_CONF_SOURCE_DSM BIT(0)
/* Valid values for the GPIO_CONF_INTTYPE field */ /* Valid values for the GPIO_CONF_INTTYPE field */
typedef enum { typedef enum {
@ -142,13 +142,13 @@ typedef enum {
GPIO_INTTYPE_LEVEL_HIGH = 5, GPIO_INTTYPE_LEVEL_HIGH = 5,
} gpio_inttype_t; } gpio_inttype_t;
/* Details for PWM register */ /* Details for DSM register */
#define GPIO_PWM_ENABLE BIT(16) #define GPIO_DSM_ENABLE BIT(16)
#define GPIO_PWM_PRESCALER_M 0x000000ff #define GPIO_DSM_PRESCALER_M 0x000000ff
#define GPIO_PWM_PRESCALER_S 8 #define GPIO_DSM_PRESCALER_S 8
#define GPIO_PWM_TARGET_M 0x000000ff #define GPIO_DSM_TARGET_M 0x000000ff
#define GPIO_PWM_TARGET_S 0 #define GPIO_DSM_TARGET_S 0
/* Details for RTC_CALIB register */ /* Details for RTC_CALIB register */

View file

@ -0,0 +1,4 @@
# Simple makefile for simple example
PROGRAM=dsm_test
EXTRA_COMPONENTS = extras/dsm
include ../../common.mk

View file

@ -0,0 +1,67 @@
/* Very basic example to test the dsm library
* Led intensity from module will change over time.
*
* Part of esp-open-rtos
* Copyright (C) 2018 zaltora (https://github.com/Zaltora)
* BSD Licensed as described in the file LICENSE
*/
#include "espressif/esp_common.h"
#include "esp/uart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "dsm.h"
#define TEST_WITH_160MHZ (0)
#define DSM_PIN (2)
void task1(void *pvParameters)
{
uint32_t const init_count = 0;
uint32_t count = init_count;
while(1)
{
vTaskDelay(100/portTICK_PERIOD_MS);
printf("Target set to %3u, ", count);
//Freq = (80,000,000/prescale) * (target / 256) HZ (0 < target < 128)
//Freq = (80,000,000/prescale) * ((256 - target) / 256) HZ (128 < target < 256)
if (count < 128)
{
printf("Freqency: %.1f Hz\r\n", (80000000.0/255.0 * (count/ 256.0)));
}
else
{
printf("Freqency: %.1f Hz\r\n", 80000000.0/255.0 * ((256.0-count)/ 256.0));
}
dsm_set_target(count);
count++;
if (count > UINT8_MAX)
count = init_count;
}
}
void user_init(void)
{
uint8_t pins[1];
uart_set_baud(0, 115200);
#if (TEST_WITH_160MHZ)
sdk_system_update_cpu_freq(160);
#endif
printf("SDK version:%s\r\n", sdk_system_get_sdk_version());
pins[0] = DSM_PIN;
/* register pin to use with DSM */
dsm_init(1, pins);
/* Set prescale to FF to get a proper signal */
dsm_set_prescale(0xFF);
/* Target initial */
dsm_set_target(0);
/* start dsm to pin */
dsm_start();
printf("dsm start\r\n");
xTaskCreate(task1, "tsk1", 256, NULL, 2, NULL);
}

9
extras/dsm/component.mk Normal file
View file

@ -0,0 +1,9 @@
# Component makefile for extras/dsm
INC_DIRS += $(ROOT)extras/dsm
# args for passing into compile rule generation
extras/dsm_INC_DIR = $(ROOT)extras/dsm
extras/dsm_SRC_DIR = $(ROOT)extras/dsm
$(eval $(call component_compile_rules,extras/dsm))

111
extras/dsm/dsm.c Normal file
View file

@ -0,0 +1,111 @@
/* Implementation of Delta-Sigma modulator support.
*
* Part of esp-open-rtos
* Copyright (C) 2018 ourairquality (https://github.com/ourairquality)
* Copyright (C) 2018 Zaltora (https://github.com/Zaltora)
* BSD Licensed as described in the file LICENSE
*/
#include "dsm.h"
#include <espressif/esp_common.h>
#include <esp8266.h>
#if (DSM_DEBUG)
#define debug(fmt, ...) printf("%s: " fmt "\n", "DSM", ## __VA_ARGS__)
#else
#define debug(fmt, ...)
#endif
typedef struct dsmInfoDefinition
{
uint8_t running;
uint8_t preScale;
uint8_t target;
bool output;
/* private */
uint8_t usedPins;
uint8_t pins[8];
} DSMInfo;
static DSMInfo dsmInfo;
void dsm_init(uint8_t npins, const uint8_t* pins)
{
/* Assert number of pins is correct */
if (npins > MAX_DSM_PINS)
{
debug("Incorrect number of DSM pins (%d)\n", npins);
return;
}
/* Save pins information */
dsmInfo.usedPins = npins;
for (uint8_t i = 0 ; i < npins; ++i)
{
dsmInfo.pins[i] = pins[i];
/* configure GPIOs */
gpio_enable(pins[i], GPIO_OUTPUT);
}
/* Set output to LOW */
dsm_stop();
/* Flag not running */
dsmInfo.running = 0;
}
void dsm_set_prescale(uint8_t prescale)
{
//TODO: Add a freq/prescale converter
dsmInfo.preScale = prescale;
debug("Set Prescale: %u",dsmInfo.preScale);
}
void dsm_set_target(uint8_t target)
{
dsmInfo.target = target;
if (target == 0 || target == UINT8_MAX)
{
dsmInfo.output = (target == UINT8_MAX);
}
debug("Duty set at %u",dsmInfo.target);
if (dsmInfo.running)
{
dsm_start();
}
}
void dsm_start()
{
if (dsmInfo.target > 0 && dsmInfo.target < UINT8_MAX)
{
for (uint8_t i = 0; i < dsmInfo.usedPins; ++i)
{
SET_MASK_BITS(GPIO.CONF[dsmInfo.pins[i]], GPIO_CONF_SOURCE_DSM);
}
GPIO.DSM = GPIO_DSM_ENABLE | (dsmInfo.preScale << 8) | dsmInfo.target;
}
else
{
for (uint8_t i = 0; i < dsmInfo.usedPins; ++i)
{
gpio_write(dsmInfo.pins[i], dsmInfo.output );
}
}
debug("start");
dsmInfo.running = 1;
}
void dsm_stop()
{
for (uint8_t i = 0; i < dsmInfo.usedPins; ++i)
{
CLEAR_MASK_BITS(GPIO.CONF[dsmInfo.pins[i]], GPIO_CONF_SOURCE_DSM);
gpio_write(dsmInfo.pins[i], false);
}
debug("stop");
dsmInfo.running = 0;
}

36
extras/dsm/dsm.h Normal file
View file

@ -0,0 +1,36 @@
/* Implementation of Delta-Sigma modulator support.
*
* Part of esp-open-rtos
* Copyright (C) 2018 ourairquality (https://github.com/ourairquality)
* Copyright (C) 2018 Zaltora (https://github.com/Zaltora)
* BSD Licensed as described in the file LICENSE
*/
#ifndef EXTRAS_DSM_H_
#define EXTRAS_DSM_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#define MAX_DSM_PINS (8)
#define DSM_DEBUG (0)
/*
* Freq = (80,000,000/prescale) * (target / 256) HZ (0 < target < 128)
* Freq = (80,000,000/prescale) * ((256 - target) / 256) HZ (128 < target < 256)
*/
void dsm_init(uint8_t npins, const uint8_t* pins);
void dsm_set_prescale(uint8_t prescale);
void dsm_set_target(uint8_t target);
void dsm_start();
void dsm_stop();
#ifdef __cplusplus
}
#endif
#endif /* EXTRAS_DSM_H_ */