Skip to content

Commit 434d79f

Browse files
committed
Added an additional PinDescription table format, which can be used to reduce code size (D11 chips only for now)
1 parent f0780cc commit 434d79f

File tree

14 files changed

+482
-171
lines changed

14 files changed

+482
-171
lines changed

cores/arduino/Tone.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -182,9 +182,9 @@ void tone (uint32_t outputPin, uint32_t frequency, uint32_t duration)
182182
TONE_TC->COUNT16.CC[TONE_TC_CHANNEL].reg = (uint16_t) ccValue;
183183
WAIT_TC16_REGS_SYNC(TONE_TC)
184184

185-
portToggleRegister = &(PORT->Group[g_APinDescription[outputPin].ulPort].OUTTGL.reg);
186-
portClearRegister = &(PORT->Group[g_APinDescription[outputPin].ulPort].OUTCLR.reg);
187-
portBitMask = (1ul << g_APinDescription[outputPin].ulPin);
185+
portToggleRegister = &(PORT->Group[GetPort(outputPin)].OUTTGL.reg);
186+
portClearRegister = &(PORT->Group[GetPort(outputPin)].OUTCLR.reg);
187+
portBitMask = (1ul << GetPin(outputPin));
188188

189189
// Enable the TONE_TC interrupt request
190190
TONE_TC->COUNT16.INTENSET.bit.MC0 = 1;

cores/arduino/Uart.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,10 @@ void Uart::begin(unsigned long baudrate, uint16_t config)
6464
if (uc_pinRTS != NO_RTS_PIN) {
6565
pinMode(uc_pinRTS, OUTPUT);
6666

67-
uint8_t rtsPort = g_APinDescription[uc_pinRTS].ulPort;
67+
uint8_t rtsPort = GetPort(uc_pinRTS);
6868
pul_outsetRTS = &PORT->Group[rtsPort].OUTSET.reg;
6969
pul_outclrRTS = &PORT->Group[rtsPort].OUTCLR.reg;
70-
ul_pinMaskRTS = (1ul << g_APinDescription[uc_pinRTS].ulPin);
70+
ul_pinMaskRTS = (1ul << GetPin(uc_pinRTS));
7171

7272
*pul_outclrRTS = ul_pinMaskRTS;
7373
}

cores/arduino/WInterrupts.c

+14-7
Original file line numberDiff line numberDiff line change
@@ -99,13 +99,17 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
9999

100100
#if (SAML21)
101101
// The CHANGE and RISING interrupt modes on pin A31 on the SAML21 do not seem to work properly
102-
if ((g_APinDescription[pin].ulPort == 0) && (g_APinDescription[pin].ulPin == 31) && ((mode == CHANGE) || (mode == RISING)))
102+
if ((GetPort(pin) == 0) && (GetPin(pin) == 31) && ((mode == CHANGE) || (mode == RISING)))
103103
return;
104104
#endif
105105

106-
EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
107-
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
108-
return;
106+
EExt_Interrupts in = GetExtInt(pin);
107+
108+
#if defined(EXTERNAL_INT_NMI)
109+
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI) return;
110+
#else
111+
if (in == NOT_AN_INTERRUPT) return;
112+
#endif
109113

110114
if (!enabled) {
111115
__initialize();
@@ -186,9 +190,12 @@ void attachInterrupt(uint32_t pin, voidFuncPtr callback, uint32_t mode)
186190
*/
187191
void detachInterrupt(uint32_t pin)
188192
{
189-
EExt_Interrupts in = g_APinDescription[pin].ulExtInt;
190-
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI)
191-
return;
193+
EExt_Interrupts in = GetExtInt(pin);
194+
#if defined(EXTERNAL_INT_NMI)
195+
if (in == NOT_AN_INTERRUPT || in == EXTERNAL_INT_NMI) return;
196+
#else
197+
if (in == NOT_AN_INTERRUPT) return;
198+
#endif
192199

193200
uint32_t inMask = 1 << in;
194201
EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(inMask);

cores/arduino/WVariant.h

+94-44
Original file line numberDiff line numberDiff line change
@@ -22,44 +22,16 @@
2222
#include <stdint.h>
2323
#include "sam.h"
2424
#include "variant.h"
25+
#include "../../config.h"
2526

2627
#ifdef __cplusplus
2728
extern "C" {
2829
#endif
2930

30-
/* Definitions and types for pins */
31-
typedef enum _EAnalogChannel
32-
{
33-
No_ADC_Channel=-1,
34-
ADC_Channel0=0,
35-
ADC_Channel1=1,
36-
ADC_Channel2=2,
37-
ADC_Channel3=3,
38-
ADC_Channel4=4,
39-
ADC_Channel5=5,
40-
ADC_Channel6=6,
41-
ADC_Channel7=7,
42-
ADC_Channel8=8,
43-
ADC_Channel9=9,
44-
ADC_Channel10=10,
45-
ADC_Channel11=11,
46-
ADC_Channel12=12,
47-
ADC_Channel13=13,
48-
ADC_Channel14=14,
49-
ADC_Channel15=15,
50-
ADC_Channel16=16,
51-
ADC_Channel17=17,
52-
ADC_Channel18=18,
53-
ADC_Channel19=19,
54-
DAC_Channel0,
55-
DAC_Channel1,
56-
} EAnalogChannel ;
57-
5831
// Definitions for TC channels
59-
// RESERVED (1 bit, used for negative) | Timer Number (3 bits: 0-7) | Timer Type (1 bit: 0=TCC, 1=TC) | Timer Channel (3 bits: 0-7)
32+
// Timer Enable (1 bit: 0=enabled, 1=disabled) | Timer Number (3 bits: 0-7) | Timer Type (1 bit: 0=TCC, 1=TC) | Timer Channel (3 bits: 0-7)
6033
typedef enum _ETCChannel
6134
{
62-
NOT_ON_TIMER=-1,
6335
TCC0_CH0 = (0<<4)|(0<<3)|(0),
6436
TCC0_CH1 = (0<<4)|(0<<3)|(1),
6537
TCC0_CH2 = (0<<4)|(0<<3)|(2),
@@ -113,6 +85,7 @@ typedef enum _ETCChannel
11385
TC6_CH1 = (6<<4)|(1<<3)|(1),
11486
TC7_CH0 = (7<<4)|(1<<3)|(0),
11587
TC7_CH1 = (7<<4)|(1<<3)|(1),
88+
NOT_ON_TIMER = (1<<7),
11689
} ETCChannel ;
11790

11891
extern const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM] ;
@@ -130,22 +103,66 @@ extern const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM] ;
130103
#error "WVariant.h: Unsupported chip"
131104
#endif
132105

133-
// Definitions for GCLK_CCL column TODO, AC?
134-
// RESERVED (1 bit, used for negative) | GCLK (3 bits: 0-7) | CCL (4 bits: 2 for CCL number, 2 for pin (or 4 for IN/OUT pin ID on D51))
106+
// TODO: Definitions for GCLK_CCL column, AC. The format may change.
107+
// GCLK/CCL Enable (1 bit: 0=enabled, 1=disabled) | GCLK (3 bits: 0-7) | CCL (4 bits: 2 for CCL number, 2 for pin (or 4 for IN/OUT pin ID on D51))
135108
typedef enum _EGCLK_CCL
136109
{
137-
GCLK_CCL_NONE=-1,
110+
GCLK_CCL_NONE = (1<<7),
138111
} EGCLK_CCL ;
139112

140113
typedef enum _EPortType
141114
{
142-
NOT_A_PORT=-1,
143115
PORTA=0,
144116
PORTB=1,
145117
PORTC=2,
146118
PORTD=3,
119+
NOT_A_PORT,
147120
} EPortType ;
148121

122+
// When PIN_DESCRIPTION_TABLE_SIMPLE defined, the port and pin are combined into one single byte element rather than two
123+
// PORT (3 bits: 0-7, EPortType) | PIN (5 bits: 0-31)
124+
#if defined(PIN_DESCRIPTION_TABLE_SIMPLE)
125+
// Use SetPortPin in the ulPortPin column of the PinDescription table (when using PIN_DESCRIPTION_TABLE_SIMPLE only).
126+
#define SetPortPin( port, pin ) ( (((port & 0x07) << 5) | (pin & 0x1F)) )
127+
#define GetPort( x ) ( ((g_APinDescription[x].ulPortPin) >> 5) & 0x07 )
128+
#define GetPin( x ) ( (g_APinDescription[x].ulPortPin) & 0x1F )
129+
#else
130+
#define GetPort( x ) g_APinDescription[x].ulPort
131+
#define GetPin( x ) g_APinDescription[x].ulPin
132+
#endif
133+
134+
/* Definitions and types for pins */
135+
typedef enum _EAnalogChannel
136+
{
137+
ADC_Channel0=0,
138+
ADC_Channel1=1,
139+
ADC_Channel2=2,
140+
ADC_Channel3=3,
141+
ADC_Channel4=4,
142+
ADC_Channel5=5,
143+
ADC_Channel6=6,
144+
ADC_Channel7=7,
145+
ADC_Channel8=8,
146+
ADC_Channel9=9,
147+
ADC_Channel10=10,
148+
ADC_Channel11=11,
149+
ADC_Channel12=12,
150+
ADC_Channel13=13,
151+
ADC_Channel14=14,
152+
#if defined(PIN_DESCRIPTION_TABLE_SIMPLE)
153+
No_ADC_Channel = 15,
154+
#else
155+
ADC_Channel15=15,
156+
ADC_Channel16=16,
157+
ADC_Channel17=17,
158+
ADC_Channel18=18,
159+
ADC_Channel19=19,
160+
DAC_Channel0,
161+
DAC_Channel1,
162+
No_ADC_Channel,
163+
#endif
164+
} EAnalogChannel ;
165+
149166
typedef enum
150167
{
151168
EXTERNAL_INT_0 = 0,
@@ -163,13 +180,31 @@ typedef enum
163180
EXTERNAL_INT_12,
164181
EXTERNAL_INT_13,
165182
EXTERNAL_INT_14,
183+
#if defined(PIN_DESCRIPTION_TABLE_SIMPLE)
184+
NOT_AN_INTERRUPT = 15,
185+
EXTERNAL_NUM_INTERRUPTS = NOT_AN_INTERRUPT,
186+
#else
166187
EXTERNAL_INT_15,
167188
EXTERNAL_INT_NMI,
168189
EXTERNAL_NUM_INTERRUPTS,
169-
NOT_AN_INTERRUPT = -1,
190+
NOT_AN_INTERRUPT,
191+
#endif
170192
EXTERNAL_INT_NONE = NOT_AN_INTERRUPT,
171193
} EExt_Interrupts ;
172194

195+
// When PIN_DESCRIPTION_TABLE_SIMPLE defined, the ExtInt and ADCChannelNumber fields are combined into one single byte element (ulExtIntADC) rather than two
196+
// Because of this, only interrupts 0 through 14 are supported (15 = NOT_AN_INTERRUPT) and only ADC channels 0 through 14 are supported (15 = No_ADC_Channel)
197+
// ExtInt (4 bits: 0-15, EExt_Interrupts) | ADC (4 bits: 0-15, EAnalogChannel)
198+
#if defined(PIN_DESCRIPTION_TABLE_SIMPLE)
199+
// Use SetExtIntADC in the ulExtIntADC column of the PinDescription table (when using PIN_DESCRIPTION_TABLE_SIMPLE only).
200+
#define SetExtIntADC( ExtInt, ADC ) ( (((ExtInt & 0x0F) << 4) | (ADC & 0x0F)) )
201+
#define GetExtInt( x ) ( ((g_APinDescription[x].ulExtIntADC) >> 4) & 0x0F )
202+
#define GetADC( x ) ( (g_APinDescription[x].ulExtIntADC) & 0x0F )
203+
#else
204+
#define GetExtInt( x ) g_APinDescription[x].ulExtInt
205+
#define GetADC( x ) g_APinDescription[x].ulADCChannelNumber
206+
#endif
207+
173208

174209
/* Copied from wiring_constants.h */
175210
#define INPUT (0x0)
@@ -178,8 +213,6 @@ typedef enum
178213
#define INPUT_PULLDOWN (0x3)
179214
typedef enum _EPioType
180215
{
181-
PIO_NOT_A_PIN=-1, /* Not under control of a peripheral. */
182-
183216
PIO_INPUT=INPUT, /* The pin is controlled by PORT and is an input. */
184217
PIO_OUTPUT=OUTPUT, /* The pin is controlled by PORT and is an output. */
185218
PIO_INPUT_PULLUP=INPUT_PULLUP, /* The pin is controlled by PORT and is an input with internal pull-up resistor enabled. */
@@ -212,8 +245,8 @@ typedef enum _EPioType
212245
PIO_CCL=24, /* The pin is controlled by the CCL (configurable custom logic) peripheral (I/O). */
213246

214247
PIO_MULTI, /* The pin can be configured to any type based on the attributes. */
215-
216248
PIO_STARTUP, /* Used as parameter to pinPeripheral() only to set startup state (enable INEN only) */
249+
PIO_NOT_A_PIN, /* Not under control of a peripheral. */
217250
} EPioType ;
218251

219252
/**
@@ -263,7 +296,6 @@ D51: EIC REF ADC AC PTC DAC SERCOM SERCOM_ALT TC TCC TCC/PDEC COM/Q
263296
*/
264297
typedef enum _EPioPeripheral
265298
{
266-
PER_PORT=-1, /* The pin is controlled by PORT. */
267299
PER_EXTINT=0, /* The pin is controlled by the associated signal of peripheral A. */
268300
PER_ANALOG=1, /* The pin is controlled by the associated signal of peripheral B. */
269301
PER_SERCOM=2, /* The pin is controlled by the associated signal of peripheral C. */
@@ -284,6 +316,7 @@ typedef enum _EPioPeripheral
284316
PER_AC_CLK=7, /* The pin is controlled by the associated signal of peripheral H. */
285317
PER_CCL=8, /* The pin is controlled by the associated signal of peripheral I. */
286318
#endif
319+
PER_PORT, /* The pin is controlled by PORT. */
287320
} EPioPeripheral ;
288321

289322
/**
@@ -319,9 +352,25 @@ typedef enum _EPioPeripheral
319352
#define PER_ATTR_ADC_MASK (1UL<<7)
320353

321354

322-
/* Types used for the table below
323-
* This struct MUST be 12 bytes long (elements are ordered to prevent unaligned access).
324-
*/
355+
/* PinDescription table */
356+
#if defined(PIN_DESCRIPTION_TABLE_SIMPLE)
357+
#if !defined(MATTAIRTECH_ARDUINO_SAMD_VARIANT_COMPLIANCE) || (MATTAIRTECH_ARDUINO_SAMD_VARIANT_COMPLIANCE < 10618)
358+
#error "The PinDescription table in the variant.cpp file of your board variant must be updated (MATTAIRTECH_ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10618) in order to use PIN_DESCRIPTION_TABLE_SIMPLE. See VARIANT_COMPLIANCE_CHANGELOG."
359+
#endif
360+
#if !(SAMD11)
361+
#error "PIN_DESCRIPTION_TABLE_SIMPLE is currently only supported by the D11 variants (although you can still add support yourself, see the variant.cpp of a D11 variant for an example)."
362+
#endif
363+
// This struct MUST be 4 bytes long (elements are ordered to prevent unaligned access).
364+
typedef struct _PinDescription
365+
{
366+
uint8_t ulPortPin ; // Must be 8 bits
367+
uint8_t ulPeripheralAttribute ; // Must be 8 bit bitfield
368+
uint8_t ulTCChannel ; // Must be 8 bits
369+
uint8_t ulExtIntADC ; // Must be 8 bits
370+
} PinDescription ;
371+
372+
#else
373+
// This struct MUST be 12 bytes long (elements are ordered to prevent unaligned access).
325374
typedef struct _PinDescription
326375
{
327376
uint8_t ulPort ; // Must be 8 bits
@@ -336,11 +385,12 @@ typedef struct _PinDescription
336385
uint8_t ulGCLKCCL ; // Must be 8 bits
337386
#else
338387
#error "The PinDescription table in the variant.cpp file of your board variant must be updated so that MATTAIRTECH_ARDUINO_SAMD_VARIANT_COMPLIANCE >= 10608. See VARIANT_COMPLIANCE_CHANGELOG."
339-
// uint16_t ulTCChannel ; // Must be 16 bits
340-
// uint8_t ulADCChannelNumber ; // Must be 8 bits
388+
// uint16_t ulTCChannel ; // Must be 16 bits
389+
// uint8_t ulADCChannelNumber ; // Must be 8 bits
341390
// uint8_t ulExtInt ; // Must be 8 bits
342391
#endif
343392
} PinDescription ;
393+
#endif
344394

345395
/* Pins table to be instantiated into variant.cpp */
346396
extern const PinDescription g_APinDescription[] ;

cores/arduino/pulse.c

+2-3
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,14 @@ uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
3030
// cache the port and bit of the pin in order to speed up the
3131
// pulse width measuring loop and achieve finer resolution. calling
3232
// digitalRead() instead yields much coarser resolution.
33-
PinDescription p = g_APinDescription[pin];
34-
uint32_t bit = 1 << p.ulPin;
33+
uint32_t bit = 1 << GetPin(pin);
3534
uint32_t stateMask = state ? bit : 0;
3635

3736
// convert the timeout from microseconds to a number of times through
3837
// the initial loop; it takes (roughly) 13 clock cycles per iteration.
3938
uint32_t maxloops = microsecondsToClockCycles(timeout) / 13;
4039

41-
uint32_t width = countPulseASM(&(PORT->Group[p.ulPort].IN.reg), bit, stateMask, maxloops);
40+
uint32_t width = countPulseASM(&(PORT->Group[GetPort(pin)].IN.reg), bit, stateMask, maxloops);
4241

4342
// convert the reading to microseconds. The loop has been determined
4443
// to be 13 clock cycles long and have about 16 clocks between the edge

cores/arduino/wiring_analog.c

+16-4
Original file line numberDiff line numberDiff line change
@@ -477,7 +477,7 @@ uint32_t analogRead( uint32_t pin )
477477
// pinPeripheral now handles disabling the DAC (if active)
478478
if ( pinPeripheral(pin, PIO_ANALOG_ADC) == RET_STATUS_OK )
479479
{
480-
ADC->INPUTCTRL.bit.MUXPOS = g_APinDescription[pin].ulADCChannelNumber; // Selection for the positive ADC input
480+
ADC->INPUTCTRL.bit.MUXPOS = GetADC(pin); // Selection for the positive ADC input
481481

482482
syncADC();
483483

@@ -506,8 +506,16 @@ uint32_t analogRead( uint32_t pin )
506506
// to digital output.
507507
void analogWrite(uint32_t pin, uint32_t value)
508508
{
509-
if ( pinPeripheral(pin, PIO_ANALOG_DAC) == RET_STATUS_OK )
509+
#if (SAMD21 || SAMD11 || SAMC21)
510+
if ( (GetPort(pin) == 0) && (GetPin(pin) == 2) )
511+
#elif (SAML21 || SAMD51)
512+
if ( (GetPort(pin) == 0) && (GetPin(pin) == 2 || GetPin(pin) == 5) )
513+
#endif
510514
{
515+
if (pinPeripheral(pin, PIO_ANALOG_DAC) != RET_STATUS_OK) {
516+
return;
517+
}
518+
511519
if (!DACinitialized) {
512520
initDAC();
513521
}
@@ -526,7 +534,7 @@ void analogWrite(uint32_t pin, uint32_t value)
526534
uint8_t DACNumber = 0x00;
527535
value = mapResolution(value, _writeResolution, 12);
528536

529-
if ( (g_APinDescription[pin].ulPort == 0) && (g_APinDescription[pin].ulPin == 5) ) {
537+
if ( (GetPort(pin) == 0) && (GetPin(pin) == 5) ) {
530538
DACNumber = 0x01;
531539
}
532540

@@ -550,7 +558,7 @@ void analogWrite(uint32_t pin, uint32_t value)
550558
#endif
551559
return;
552560
}
553-
else if ( pinPeripheral(pin, PIO_TIMER_PWM) == RET_STATUS_OK )
561+
else if ( g_APinDescription[pin].ulTCChannel != NOT_ON_TIMER )
554562
{
555563
Tc* TCx = 0 ;
556564
Tcc* TCCx = 0 ;
@@ -560,6 +568,10 @@ void analogWrite(uint32_t pin, uint32_t value)
560568
uint8_t timerChannel = GetTCChannelNumber( g_APinDescription[pin].ulTCChannel ) ;
561569
static bool timerEnabled[TCC_INST_NUM+TC_INST_NUM];
562570

571+
if (pinPeripheral(pin, PIO_TIMER_PWM) != RET_STATUS_OK) {
572+
return;
573+
}
574+
563575
if ( timerType == 1 ) {
564576
TCx = (Tc*) GetTC( g_APinDescription[pin].ulTCChannel ) ;
565577
#if (SAMD21 || SAMD11)

0 commit comments

Comments
 (0)