Initial HW PWM (Delta-Sigma) (#609)
This commit is contained in:
		
							parent
							
								
									10f361c8ca
								
							
						
					
					
						commit
						4dc7d825bc
					
				
					 6 changed files with 238 additions and 11 deletions
				
			
		| 
						 | 
				
			
			@ -70,7 +70,7 @@ struct GPIO_REGS {
 | 
			
		|||
    uint32_t volatile STATUS_SET;       // 0x20
 | 
			
		||||
    uint32_t volatile STATUS_CLEAR;     // 0x24
 | 
			
		||||
    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_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_SOURCE_PWM (boolean)
 | 
			
		||||
 *     When set, GPIO pin output will be connected to the sigma-delta PWM
 | 
			
		||||
 *     generator (controlled by the GPIO.PWM register).  When cleared, pin
 | 
			
		||||
 * GPIO_CONF_SOURCE_DSM (boolean)
 | 
			
		||||
 *     When set, GPIO pin output will be connected to the sigma-delta
 | 
			
		||||
 *     generator (controlled by the GPIO.DSM register).  When cleared, pin
 | 
			
		||||
 *     output will function as a normal GPIO output (controlled by the
 | 
			
		||||
 *     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_S      7
 | 
			
		||||
#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 */
 | 
			
		||||
typedef enum {
 | 
			
		||||
| 
						 | 
				
			
			@ -142,13 +142,13 @@ typedef enum {
 | 
			
		|||
    GPIO_INTTYPE_LEVEL_HIGH = 5,
 | 
			
		||||
} gpio_inttype_t;
 | 
			
		||||
 | 
			
		||||
/* Details for PWM register */
 | 
			
		||||
/* Details for DSM register */
 | 
			
		||||
 | 
			
		||||
#define GPIO_PWM_ENABLE          BIT(16)
 | 
			
		||||
#define GPIO_PWM_PRESCALER_M     0x000000ff
 | 
			
		||||
#define GPIO_PWM_PRESCALER_S     8
 | 
			
		||||
#define GPIO_PWM_TARGET_M        0x000000ff
 | 
			
		||||
#define GPIO_PWM_TARGET_S        0
 | 
			
		||||
#define GPIO_DSM_ENABLE          BIT(16)
 | 
			
		||||
#define GPIO_DSM_PRESCALER_M     0x000000ff
 | 
			
		||||
#define GPIO_DSM_PRESCALER_S     8
 | 
			
		||||
#define GPIO_DSM_TARGET_M        0x000000ff
 | 
			
		||||
#define GPIO_DSM_TARGET_S        0
 | 
			
		||||
 | 
			
		||||
/* Details for RTC_CALIB register */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								examples/dsm_test/Makefile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								examples/dsm_test/Makefile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,4 @@
 | 
			
		|||
# Simple makefile for simple example
 | 
			
		||||
PROGRAM=dsm_test
 | 
			
		||||
EXTRA_COMPONENTS = extras/dsm
 | 
			
		||||
include ../../common.mk
 | 
			
		||||
							
								
								
									
										67
									
								
								examples/dsm_test/dsm_test.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								examples/dsm_test/dsm_test.c
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										9
									
								
								extras/dsm/component.mk
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										111
									
								
								extras/dsm/dsm.c
									
										
									
									
									
										Normal 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
									
								
							
							
						
						
									
										36
									
								
								extras/dsm/dsm.h
									
										
									
									
									
										Normal 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_ */
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue