Skip to content

Commit afcbcd5

Browse files
Add support for hardware Sigma Delta generator
Provides a simple interface to attach/detach pins to the sigma-delta generator, and get/set the 2 parameters prescaler & target. Working example that fades the onboard LED is provided. Code and sample by @stefaandesmet2003.
1 parent 3b269c4 commit afcbcd5

File tree

4 files changed

+339
-5
lines changed

4 files changed

+339
-5
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
core_esp8266_sigma_delta.c - sigma delta library for esp8266
3+
4+
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
5+
This file is part of the esp8266 core for Arduino environment.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
22+
#include "Arduino.h" // using pinMode
23+
24+
// definitions in esp8266_peri.h style
25+
#define GPSD ESP8266_REG(0x368) // GPIO_SIGMA_DELTA register @ 0x600000368
26+
#define GPSDT 0 // target, 8 bits
27+
#define GPSDP 8 // prescaler, 8 bits
28+
#define GPSDE 16 // enable
29+
30+
void sigmaDeltaSetPrescaler(uint8_t prescaler); // avoids compiler warning
31+
32+
/******************************************************************************
33+
* FunctionName : sigmaDeltaEnable
34+
* Description : enable the internal sigma delta source
35+
* Parameters : none
36+
* Returns : none
37+
*******************************************************************************/
38+
void ICACHE_FLASH_ATTR sigmaDeltaEnable()
39+
{
40+
GPSD = (0 << GPSDT) | (0 << GPSDP) | (1 << GPSDE); //SIGMA_DELTA_TARGET(0) | SIGMA_DELTA_PRESCALER(0) | SIGMA_DELTA_ENABLE(ENABLED)
41+
}
42+
43+
/******************************************************************************
44+
* FunctionName : sigmaDeltaDisable
45+
* Description : stop the internal sigma delta source
46+
* Parameters : none
47+
* Returns : none
48+
*******************************************************************************/
49+
void ICACHE_FLASH_ATTR sigmaDeltaDisable()
50+
{
51+
GPSD = (0 << GPSDT) | (0 << GPSDP) | (0 << GPSDE); //SIGMA_DELTA_TARGET(0) | SIGMA_DELTA_PRESCALER(0) | SIGMA_DELTA_ENABLE(DISABLED)
52+
}
53+
54+
/******************************************************************************
55+
* FunctionName : sigmaDeltaAttachPin
56+
* Description : connects the sigma delta source to a physical output pin
57+
* Parameters : pin (0..15), channel = unused, for compatibility with ESP32
58+
* Returns : none
59+
*******************************************************************************/
60+
void ICACHE_FLASH_ATTR sigmaDeltaAttachPin(uint8_t pin, uint8_t channel)
61+
{
62+
(void) channel;
63+
// make the chosen pin an output pin
64+
pinMode (pin, OUTPUT);
65+
if (pin < 16) {
66+
// set its source to the sigma delta source
67+
GPC(pin) |= (1 << GPCS); //SOURCE 0:GPIO_DATA,1:SigmaDelta
68+
}
69+
}
70+
71+
/******************************************************************************
72+
* FunctionName : sigmaDeltaDetachPin
73+
* Description : disconnects the sigma delta source from a physical output pin
74+
* Parameters : pin (0..16)
75+
* Returns : none
76+
*******************************************************************************/
77+
void ICACHE_FLASH_ATTR sigmaDeltaDetachPin(uint8_t pin)
78+
{
79+
if (pin < 16) {
80+
// set its source to the sigma delta source
81+
GPC(pin) &= ~(1 << GPCS); //SOURCE 0:GPIO_DATA,1:SigmaDelta
82+
}
83+
}
84+
85+
/******************************************************************************
86+
* FunctionName : sigmaDeltaIsPinAttached
87+
* Description : query if pin is attached
88+
* Parameters : pin (0..16)
89+
* Returns : bool
90+
*******************************************************************************/
91+
bool ICACHE_FLASH_ATTR sigmaDeltaIsPinAttached(uint8_t pin)
92+
{
93+
if (pin < 16) {
94+
// set its source to the sigma delta source
95+
return (GPC(pin) & (1 << GPCS)); //SOURCE 0:GPIO_DATA,1:SigmaDelta
96+
}
97+
else
98+
return false;
99+
}
100+
101+
/******************************************************************************
102+
* FunctionName : sigmaDeltaSetup
103+
* Description : start the sigma delta generator with the chosen parameters
104+
* Parameters : channel = unused (for compatibility with ESP32),
105+
* freq : 1220-312500 (lowest frequency in the output signal's spectrum)
106+
* Returns : uint32_t the actual frequency, closest to the input parameter
107+
*******************************************************************************/
108+
uint32_t ICACHE_FLASH_ATTR sigmaDeltaSetup(uint8_t channel, uint32_t freq)
109+
{
110+
(void) channel;
111+
112+
uint32_t prescaler = ((uint32_t)10000000/(freq*32)) - 1;
113+
114+
if(prescaler > 0xFF) {
115+
prescaler = 0xFF;
116+
}
117+
sigmaDeltaEnable();
118+
sigmaDeltaSetPrescaler ((uint8_t) prescaler);
119+
120+
return 10000000/((prescaler + 1) * 32);
121+
}
122+
123+
/******************************************************************************
124+
* FunctionName : sigmaDeltaWrite
125+
* Description : set the duty cycle for the sigma-delta source
126+
* Parameters : uint8 duty, 0-255, duty cycle = target/256,
127+
* channel = unused, for compatibility with ESP32
128+
* Returns : none
129+
*******************************************************************************/
130+
void ICACHE_FLASH_ATTR sigmaDeltaWrite(uint8_t channel, uint8_t duty)
131+
{
132+
uint32_t reg = GPSD;
133+
(void) channel;
134+
135+
reg = (reg & ~(0xFF << GPSDT)) | ((duty & 0xFF) << GPSDT);
136+
GPSD = reg;
137+
138+
}
139+
/******************************************************************************
140+
* FunctionName : sigmaDeltaRead
141+
* Description : get the duty cycle for the sigma-delta source
142+
* Parameters : channel = unused, for compatibility with ESP32
143+
* Returns : uint8_t duty cycle value 0..255
144+
*******************************************************************************/
145+
uint8_t ICACHE_FLASH_ATTR sigmaDeltaRead(uint8_t channel)
146+
{
147+
(void) channel;
148+
return (uint8_t)((GPSD >> GPSDT) & 0xFF);
149+
}
150+
151+
/******************************************************************************
152+
* FunctionName : sigmaDeltaSetPrescaler
153+
* Description : set the clock divider for the sigma-delta source
154+
* Parameters : uint8 prescaler, 0-255, divides the 80MHz base clock by this amount
155+
* Returns : none
156+
*******************************************************************************/
157+
void ICACHE_FLASH_ATTR sigmaDeltaSetPrescaler(uint8_t prescaler)
158+
{
159+
uint32_t reg = GPSD;
160+
161+
reg = (reg & ~(0xFF << GPSDP)) | ((prescaler & 0xFF) << GPSDP);
162+
GPSD = reg;
163+
}
164+
165+
/******************************************************************************
166+
* FunctionName : sigmaDeltaGetPrescaler
167+
* Description : get the prescaler value from the GPIO_SIGMA_DELTA register
168+
* Parameters : none
169+
* Returns : uint8 prescaler, CLK_DIV , 0-255
170+
*******************************************************************************/
171+
uint8_t ICACHE_FLASH_ATTR sigmaDeltaGetPrescaler(void)
172+
{
173+
return (uint8_t)((GPSD >> GPSDP) & 0xFF);
174+
}

cores/esp8266/sigma_delta.h

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,55 @@
1818
License along with this library; if not, write to the Free Software
1919
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2020
*/
21+
22+
/*******************************************************************************
23+
* Info Sigma delta module
24+
25+
This module controls the esp8266 internal sigma delta source
26+
Each pin can be connected to the sigma delta source
27+
The target duty and frequency can be modified via the register GPIO_SIGMA_DELTA
28+
29+
THE TARGET FREQUENCY IS DEFINED AS:
30+
31+
FREQ = 80,000,000/prescaler * target /256 HZ, 0<target<128
32+
FREQ = 80,000,000/prescaler * (256-target) /256 HZ, 128<target<256
33+
target: duty cycle,range 0-255
34+
prescaler: is a clock divider, range 0-255
35+
so the target and prescale will both affect the freq.
36+
CPU_FREQ has no influence on the sigma delta frequency.
37+
38+
Usage :
39+
1. sigmaDeltaSetup(0,f) : activate the sigma delta source with frequency f and default duty cycle (0)
40+
2. sigmaDeltaAttachPin(pin), any pin 0..15, TBC if gpio16 supports sigma-delta source
41+
This will set the pin to NORMAL output mode (pinMode(pin,OUTPUT))
42+
3. sigmaDeltaWrite(0,dc) : set the output signal duty cycle, duty cycle = dc/256
43+
44+
*******************************************************************************/
2145

2246
#ifndef SIGMA_DELTA_H
2347
#define SIGMA_DELTA_H
2448

25-
#include <stdint.h>
49+
#ifdef __cplusplus
50+
extern "C" {
51+
#endif
52+
53+
//channel parameter is unused (only for ESP32 compatibility) freq 1220-312500 duty 0-255
54+
void sigmaDeltaEnable(void);
55+
void sigmaDeltaDisable(void);
56+
uint32_t sigmaDeltaSetup(uint8_t channel, uint32_t freq);
57+
void sigmaDeltaWrite(uint8_t channel, uint8_t duty);
58+
uint8_t sigmaDeltaRead(uint8_t channel = 0);
59+
void sigmaDeltaAttachPin(uint8_t pin, uint8_t channel = 0);
60+
void sigmaDeltaDetachPin(uint8_t pin);
61+
bool sigmaDeltaIsPinAttached(uint8_t pin);
62+
63+
// alternative way to control the sigma delta generator frequency
64+
uint8_t sigmaDeltaGetPrescaler(void);
65+
void sigmaDeltaSetPrescaler(uint8_t prescaler);
66+
2667

27-
void sigma_delta_close(uint32_t gpio);
28-
void set_sigma_target(uint8_t target);
29-
void set_sigma_prescale(uint8_t prescale);
30-
void set_sigma_duty_312KHz(uint8_t duty);
68+
#ifdef __cplusplus
69+
}
70+
#endif
3171

3272
#endif//SIGMA_DELTA_H
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* Any copyright is dedicated to the Public Domain. */
2+
3+
#include "sigma_delta.h"
4+
5+
void setup() {
6+
7+
Serial.begin(115200);
8+
pinMode(LED_BUILTIN, OUTPUT); // blinkie & sigma-delta mix
9+
uint32_t reqFreq = 1000;
10+
uint32_t realFreq;
11+
12+
realFreq = sigmaDeltaSetup(0, reqFreq); // chose a low frequency
13+
14+
Serial.println();
15+
Serial.println("Start Sigma Delta Example\n");
16+
Serial.printf("Frequency = %u\n", realFreq);
17+
18+
}
19+
20+
void loop() {
21+
22+
uint8_t duty, iRepeat;
23+
24+
Serial.println("Attaching the built in led to the sigma delta source now\n");
25+
Serial.printf("Current duty = %i, prescaler = %i\n", sigmaDeltaRead(), sigmaDeltaGetPrescaler());
26+
sigmaDeltaAttachPin(LED_BUILTIN);
27+
28+
Serial.println("Dimming builtin led...\n");
29+
for (iRepeat = 0; iRepeat < 10; iRepeat++) {
30+
for (duty = 0; duty < 255; duty = duty + 5) {
31+
sigmaDeltaWrite(0, duty);
32+
delay(10);
33+
}
34+
35+
for (duty = 255; duty > 0; duty = duty - 5) {
36+
sigmaDeltaWrite(0, duty);
37+
delay(10);
38+
}
39+
40+
}
41+
42+
Serial.println("Detaching builtin led & playing a blinkie\n");
43+
sigmaDeltaDetachPin(LED_BUILTIN);
44+
for (iRepeat = 0; iRepeat < 20; iRepeat++) {
45+
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
46+
delay(500);
47+
}
48+
}

sigma_delta.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
/*
2+
sigma_delta.h - esp8266 sigma-delta source
3+
4+
Copyright (c) 2014 Ivan Grokhotkov. All rights reserved.
5+
This file is part of the esp8266 core for Arduino environment.
6+
7+
This library is free software; you can redistribute it and/or
8+
modify it under the terms of the GNU Lesser General Public
9+
License as published by the Free Software Foundation; either
10+
version 2.1 of the License, or (at your option) any later version.
11+
12+
This library is distributed in the hope that it will be useful,
13+
but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
Lesser General Public License for more details.
16+
17+
You should have received a copy of the GNU Lesser General Public
18+
License along with this library; if not, write to the Free Software
19+
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*/
21+
22+
/*
23+
/******************************************************************************
24+
* Info Sigma delta module
25+
26+
This module controls the esp8266 internal sigma delta source
27+
Each pin can be connected to the sigma delta source
28+
The target duty and frequency can be modified via the register GPIO_SIGMA_DELTA
29+
30+
THE TARGET FREQUENCY IS DEFINED AS:
31+
32+
FREQ = 80,000,000/prescaler * target /256 HZ, 0<target<128
33+
FREQ = 80,000,000/prescaler * (256-target) /256 HZ, 128<target<256
34+
target: duty ,0-255
35+
prescaler: clk_div,0-255
36+
so the target and prescale will both affect the freq.
37+
38+
Usage :
39+
1. sigma_delta_enable() : activate the sigma delta source with default prescalar (0) & target (0)
40+
2. sigma_delta_attachPin(pin), any pin 0..15, TBC if gpio16 supports sigma-delta source
41+
This will set the pin to NORMAL output mode (pinMode(pin,OUTPUT))
42+
3. sigma_delta_setPrescaler(uint8_t) : reduce the output frequencies
43+
4. sigma_delta_setTarget(uint8_t) : set the output signal duty cycle, duty cycle = target/256
44+
45+
5. sigma_delta_detachPin(pin), this will revert the pin to NORMAL output mode & GPIO source.
46+
The sigma delta source remains on until :
47+
6. sigma_delta_disable()
48+
49+
*******************************************************************************/
50+
51+
#ifndef SIGMA_DELTA_H
52+
#define SIGMA_DELTA_H
53+
54+
#ifdef __cplusplus
55+
extern "C" {
56+
#endif
57+
58+
void sigma_delta_enable(void);
59+
void sigma_delta_disable(void);
60+
void sigma_delta_attachPin(uint8_t pin);
61+
void sigma_delta_detachPin(uint8_t pin);
62+
bool sigma_delta_isPinAttached(uint8_t pin);
63+
uint8_t sigma_delta_getTarget(void);
64+
void sigma_delta_setTarget(uint8_t target);
65+
uint8_t sigma_delta_getPrescaler(void);
66+
void sigma_delta_setPrescaler(uint8_t prescaler);
67+
68+
#ifdef __cplusplus
69+
}
70+
#endif
71+
72+
#endif//SIGMA_DELTA_H

0 commit comments

Comments
 (0)