Skip to content

Commit 7d7da2d

Browse files
committed
analogWrite() with Timer Counter device
1 parent d07099d commit 7d7da2d

File tree

4 files changed

+177
-102
lines changed

4 files changed

+177
-102
lines changed

hardware/sam/cores/sam/Arduino.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ typedef enum _EAnalogChannel
117117

118118
#define ADC_CHANNEL_NUMBER_NONE 0xffffffff
119119

120-
// Definition for PWM channels
120+
// Definitions for PWM channels
121121
typedef enum _EPWMChannel
122122
{
123123
NO_PWM=-1,
@@ -127,6 +127,18 @@ typedef enum _EPWMChannel
127127
PWM_CH3
128128
} EPWMChannel ;
129129

130+
// Definitions for TC channels
131+
typedef enum _ETCChannel
132+
{
133+
NO_TC=-1,
134+
TC0_CHA0=0,
135+
TC0_CHB0,
136+
TC0_CHA1,
137+
TC0_CHB1,
138+
TC0_CHA2,
139+
TC0_CHB2
140+
} ETCChannel ;
141+
130142
/**
131143
* Pin Attributes to be OR-ed
132144
*/
@@ -148,6 +160,7 @@ typedef struct _PinDescription
148160
EAnalogChannel ulAnalogChannel ; /* Describe which Analog pin is linked to a MCU pin */
149161
EAnalogChannel ulADCChannelNumber ; /* We use the same enum than for ADC pins to describe the ADC channel in use on this pin */
150162
EPWMChannel ulPWMChannel ;
163+
ETCChannel ulTCChannel ;
151164
} PinDescription ;
152165

153166
/* Pins table to be instanciated into variant.cpp */

hardware/sam/cores/sam/wiring_analog.c

Lines changed: 61 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,27 @@ uint32_t analogRead(uint32_t ulPin)
110110
return ulValue;
111111
}
112112

113+
static void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v )
114+
{
115+
TcChannel* ch = tc->TC_CHANNEL+chan;
116+
ch->TC_RA = v;
117+
}
118+
119+
static void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v )
120+
{
121+
TcChannel* ch = &tc->TC_CHANNEL+chan;
122+
ch->TC_RB = v;
123+
}
124+
125+
static void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v )
126+
{
127+
TcChannel* ch = &tc->TC_CHANNEL+chan;
128+
ch->TC_RC = v;
129+
}
130+
113131
static uint8_t PWMEnabled = 0;
114-
static uint8_t TCEnabled = 0;
115132
static uint8_t pinEnabled[PINS_COUNT];
133+
static uint8_t TCChanEnabled[] = {0, 0, 0};
116134

117135
void analogOutputInit() {
118136
uint8_t i;
@@ -130,7 +148,7 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
130148
if ((attr & PIN_ATTR_PWM) == PIN_ATTR_PWM) {
131149
if (!PWMEnabled) {
132150
// PWM Startup code
133-
PMC_EnablePeripheral(ID_PWM);
151+
PMC_EnablePeripheral(PWM_INTERFACE_ID);
134152
PWMC_ConfigureClocks(PWM_FREQUENCY * PWM_MAX_DUTY_CYCLE, 0, VARIANT_MCK);
135153
PWMEnabled = 1;
136154
}
@@ -147,25 +165,57 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) {
147165
PWMC_SetDutyCycle(PWM_INTERFACE, chan, ulValue);
148166
PWMC_EnableChannel(PWM_INTERFACE, chan);
149167
pinEnabled[ulPin] = 1;
150-
} else {
151-
PWMC_SetDutyCycle(PWM_INTERFACE, chan, ulValue);
152168
}
169+
170+
PWMC_SetDutyCycle(PWM_INTERFACE, chan, ulValue);
153171
return;
154172
}
155173

156174
if ((attr & PIN_ATTR_TIMER) == PIN_ATTR_TIMER) {
157-
// TODO
158-
/*
159-
if (!TCEnabled) {
160-
TCEnabled = 1;
161-
}
175+
// We use MCLK/2 => 96Mhz/2 => 48Mhz as clock.
176+
// To get 1KHz we should use 48000 as TC
177+
// 48Mhz/48000 = 1KHz
178+
const uint32_t TC = VARIANT_MCK / 2 / TC_FREQUENCY;
179+
180+
// Map value to Timer ranges 0..255=>0..48000
181+
ulValue = ulValue * TC;
182+
ulValue = ulValue / TC_MAX_DUTY_CYCLE;
162183

163184
// Setup Timer for this pin
185+
ETCChannel channel = g_APinDescription[ulPin].ulTCChannel;
186+
static const channelToChNo[] = { 0, 0, 1, 1, 2, 2 };
187+
static const channelToAB[] = { 1, 0, 1, 0, 1, 0 };
188+
uint32_t chNo = channelToChNo[channel];
189+
uint32_t chA = channelToAB[channel];
190+
191+
if (!TCChanEnabled[chNo]) {
192+
PMC_EnablePeripheral(TC_INTERFACE_ID + chNo);
193+
TC_Configure(TC_INTERFACE, chNo,
194+
TC_CMR_TCCLKS_TIMER_CLOCK1 |
195+
TC_CMR_WAVE |
196+
TC_CMR_WAVSEL_UP_RC |
197+
TC_CMR_ACPA_CLEAR | // RA Compare Effect on OA: clear
198+
TC_CMR_ACPC_SET | // RC Compare Effect on OA: set
199+
TC_CMR_BCPB_CLEAR | // RB Compare Effect on OB: clear
200+
TC_CMR_BCPC_SET); // RC Compare Effect on OB: set
201+
TC_SetRC(TC_INTERFACE, chNo, TC);
202+
}
203+
if (chA)
204+
TC_SetRA(TC_INTERFACE, chNo, ulValue);
205+
else
206+
TC_SetRB(TC_INTERFACE, chNo, ulValue);
164207
if (!pinEnabled[ulPin]) {
165-
} else {
208+
PIO_Configure(g_APinDescription[ulPin].pPort,
209+
g_APinDescription[ulPin].ulPinType,
210+
g_APinDescription[ulPin].ulPin,
211+
g_APinDescription[ulPin].ulPinConfiguration);
212+
pinEnabled[ulPin] = 1;
213+
}
214+
if (!TCChanEnabled[chNo]) {
215+
TC_Start(TC_INTERFACE, chNo);
216+
TCChanEnabled[chNo] = 1;
166217
}
167218
return;
168-
*/
169219
}
170220

171221
// Default to digital write

0 commit comments

Comments
 (0)