Waveform synthesis on the R4

Hi @bastenhoor,

Okay, here is the Arduino IDE version.

Tone fundament is selected by a voltage (i.e. pot) on A1 between 27.5Hz (piano note A0) and 4123.5Hz (note C8).

/*  Arduino UNO R4 example code - Sound Synthesis
 *  Using Timer 7 interrupt at c. 44.1kHz
 *  Super-Fast sine calculation of frequency and harmonics from ADC value 
 *  With fast non-blocking ADC analog-read and DAC analog-write operations
 *
 *  Susan Parker - 6th April 2025.
 *
 *    Realtime sine calc with Paul Stoffregen's 11th order Taylor Series Approximation
 *    https://www.pjrc.com/high-precision-sine-wave-synthesis-using-taylor-series/
 *    Note: I have condensed the Taylor Series code to a single set of inline asm calls
 *
 * This code is "AS IS" without warranty or liability. 
 * There may be glitches, etc. please let me know if you find any; thanks.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
*/


// ARM-developer - Accessing memory-mapped peripherals
// https://developer.arm.com/documentation/102618/0100

/* Start of Register Definitions - Use Code Folding to collapse these with V to > select (next to line numbers) */
// ==== Interrupt Control Unit ====

  /* Default Arduino Startup - see section 13.3.2 for Event Number info
  0 33 USBFS_USBI
  1 34 USBFS_USBR
  2 31 USBFS_D0FIFO
  3 32 USBFS_D1FIFO
  4 1E AGT0_AGTI
  ...
  */

  #define ICUBASE 0x40000000 // ICU Base - See 13.2.6 page 233
  // 32 bits - 
  #define IELSR 0x6300 // ICU Event Link Setting Register n
  #define ICU_IELSR00 ((volatile unsigned int *)(ICUBASE + IELSR))            //
  #define ICU_IELSR01 ((volatile unsigned int *)(ICUBASE + IELSR + ( 1 * 4))) // 
  #define ICU_IELSR02 ((volatile unsigned int *)(ICUBASE + IELSR + ( 2 * 4))) // 
  #define ICU_IELSR03 ((volatile unsigned int *)(ICUBASE + IELSR + ( 3 * 4))) // 
  #define ICU_IELSR04 ((volatile unsigned int *)(ICUBASE + IELSR + ( 4 * 4))) // 
  #define ICU_IELSR05 ((volatile unsigned int *)(ICUBASE + IELSR + ( 5 * 4))) // 
  #define ICU_IELSR06 ((volatile unsigned int *)(ICUBASE + IELSR + ( 6 * 4))) // 
  #define ICU_IELSR07 ((volatile unsigned int *)(ICUBASE + IELSR + ( 7 * 4))) // 
  #define ICU_IELSR08 ((volatile unsigned int *)(ICUBASE + IELSR + ( 8 * 4))) // 
  #define ICU_IELSR09 ((volatile unsigned int *)(ICUBASE + IELSR + ( 9 * 4))) // 
  #define ICU_IELSR10 ((volatile unsigned int *)(ICUBASE + IELSR + (10 * 4))) // 
  #define ICU_IELSR11 ((volatile unsigned int *)(ICUBASE + IELSR + (11 * 4))) // 
  #define ICU_IELSR12 ((volatile unsigned int *)(ICUBASE + IELSR + (12 * 4))) // 
  #define ICU_IELSR13 ((volatile unsigned int *)(ICUBASE + IELSR + (13 * 4))) // 
  #define ICU_IELSR14 ((volatile unsigned int *)(ICUBASE + IELSR + (14 * 4))) // 
  #define ICU_IELSR15 ((volatile unsigned int *)(ICUBASE + IELSR + (15 * 4))) // 
  #define ICU_IELSR16 ((volatile unsigned int *)(ICUBASE + IELSR + (16 * 4))) // 
  #define ICU_IELSR17 ((volatile unsigned int *)(ICUBASE + IELSR + (17 * 4))) // 
  #define ICU_IELSR18 ((volatile unsigned int *)(ICUBASE + IELSR + (18 * 4))) // 
  #define ICU_IELSR19 ((volatile unsigned int *)(ICUBASE + IELSR + (19 * 4))) // 
  #define ICU_IELSR20 ((volatile unsigned int *)(ICUBASE + IELSR + (20 * 4))) // 
  #define ICU_IELSR21 ((volatile unsigned int *)(ICUBASE + IELSR + (21 * 4))) // 
  #define ICU_IELSR22 ((volatile unsigned int *)(ICUBASE + IELSR + (22 * 4))) // 
  #define ICU_IELSR23 ((volatile unsigned int *)(ICUBASE + IELSR + (23 * 4))) // 
  #define ICU_IELSR24 ((volatile unsigned int *)(ICUBASE + IELSR + (24 * 4))) // 
  #define ICU_IELSR25 ((volatile unsigned int *)(ICUBASE + IELSR + (25 * 4))) // 
  #define ICU_IELSR26 ((volatile unsigned int *)(ICUBASE + IELSR + (26 * 4))) // 
  #define ICU_IELSR27 ((volatile unsigned int *)(ICUBASE + IELSR + (27 * 4))) // 
  #define ICU_IELSR28 ((volatile unsigned int *)(ICUBASE + IELSR + (28 * 4))) // 
  #define ICU_IELSR29 ((volatile unsigned int *)(ICUBASE + IELSR + (29 * 4))) // 
  #define ICU_IELSR30 ((volatile unsigned int *)(ICUBASE + IELSR + (30 * 4))) // 
  #define ICU_IELSR31 ((volatile unsigned int *)(ICUBASE + IELSR + (31 * 4))) // 

  // IRQ Event Numbers
  #define IRQ_NO_EVENT         0x00
  #define IRQ_PORT_IRQ0        0x01
  #define IRQ_PORT_IRQ1        0x02
  #define IRQ_PORT_IRQ2        0x03
  #define IRQ_PORT_IRQ3        0x04
  #define IRQ_PORT_IRQ4        0x05
  #define IRQ_PORT_IRQ5        0x06
  #define IRQ_PORT_IRQ6        0x07
  #define IRQ_PORT_IRQ7        0x08
  #define IRQ_PORT_IRQ8        0x09
  #define IRQ_PORT_IRQ9        0x0A
  #define IRQ_PORT_IRQ10       0x0B
  #define IRQ_PORT_IRQ11       0x0C
  #define IRQ_PORT_IRQ12       0x0D
  //      IRQ_PORT_UNUSED      0x0E
  #define IRQ_PORT_IRQ14       0x0F
  #define IRQ_PORT_IRQ15       0x10
  #define IRQ_DMAC0_INT        0x11
  #define IRQ_DMAC1_INT        0x12
  #define IRQ_DMAC2_INT        0x13
  #define IRQ_DMAC3_INT        0x14
  #define IRQ_DTC_COMPLETE     0x15
  //      IRQ_UNUSED           0x16
  #define IRQ_ICU_SNZCANCEL    0x17
  #define IRQ_FCU_FRDYI        0x18
  #define IRQ_LVD_LVD1         0x19
  #define IRQ_LVD_LVD2         0x1A
  #define IRQ_VBATT_LVD        0x1B
  #define IRQ_MOSC_STOP        0x1C
  #define IRQ_SYSTEM_SNZREQ    0x1D
  #define IRQ_AGT0_AGTI        0x1E
  #define IRQ_AGT0_AGTCMAI     0x1F
  #define IRQ_AGT0_AGTCMBI     0x20
  #define IRQ_AGT1_AGTI        0x21
  #define IRQ_AGT1_AGTCMAI     0x22
  #define IRQ_AGT1_AGTCMBI     0x23
  #define IRQ_IWDT_NMIUNDF     0x24
  #define IRQ_WDT_NMIUNDF      0x25
  #define IRQ_RTC_ALM          0x26
  #define IRQ_RTC_PRD          0x27
  #define IRQ_RTC_CUP          0x28
  #define IRQ_ADC140_ADI       0x29
  #define IRQ_ADC140_GBADI     0x2A
  #define IRQ_ADC140_CMPAI     0x2B
  #define IRQ_ADC140_CMPBI     0x2C
  #define IRQ_ADC140_WCMPM     0x2D
  #define IRQ_ADC140_WCMPUM    0x2E
  #define IRQ_ACMP_LP0         0x2F
  #define IRQ_ACMP_LP1         0x30
  #define IRQ_USBFS_D0FIFO     0x31
  #define IRQ_USBFS_D1FIFO     0x32
  #define IRQ_USBFS_USBI       0x33
  #define IRQ_USBFS_USBR       0x34
  #define IRQ_IIC0_RXI         0x35
  #define IRQ_IIC0_TXI         0x36
  #define IRQ_IIC0_TEI         0x37
  #define IRQ_IIC0_EEI         0x38
  #define IRQ_IIC0_WUI         0x39
  #define IRQ_IIC1_RXI         0x3A
  #define IRQ_IIC1_TXI         0x3B
  #define IRQ_IIC1_TEI         0x3C
  #define IRQ_IIC1_EEI         0x3D
  #define IRQ_SSIE0_SSITXI     0x3E
  #define IRQ_SSIE0_SSIRXI     0x3F
  //      IRQ_UNUSED           0x40
  #define IRQ_SSIE0_SSIF       0x41
  #define IRQ_CTSU_CTSUWR      0x42
  #define IRQ_CTSU_CTSURD      0x43
  #define IRQ_CTSU_CTSUFN      0x44
  #define IRQ_KEY_INTKR        0x45
  #define IRQ_DOC_DOPCI        0x46
  #define IRQ_CAC_FERRI        0x47
  #define IRQ_CAC_MENDI        0x48
  #define IRQ_CAC_OVFI         0x49
  #define IRQ_CAN0_ERS         0x4A
  #define IRQ_CAN0_RXF         0x4B
  #define IRQ_CAN0_TXF         0x4C
  #define IRQ_CAN0_RXM         0x4D
  #define IRQ_CAN0_TXM         0x4E
  #define IRQ_IOPORT_GROUP1    0x4F
  #define IRQ_IOPORT_GROUP2    0x50
  #define IRQ_IOPORT_GROUP3    0x51
  #define IRQ_IOPORT_GROUP4    0x52
  #define IRQ_ELC_SWEVT0       0x53
  #define IRQ_ELC_SWEVT1       0x54
  #define IRQ_POEG_GROUP0      0x55
  #define IRQ_POEG_GROUP1      0x56
  #define IRQ_GPT0_CCMPA       0x57
  #define IRQ_GPT0_CCMPB       0x58
  #define IRQ_GPT0_CMPC        0x59
  #define IRQ_GPT0_CMPD        0x5A
  #define IRQ_GPT0_CMPE        0x5B
  #define IRQ_GPT0_CMPF        0x5C
  #define IRQ_GPT0_OVF         0x5D
  #define IRQ_GPT0_UDF         0x5E
  #define IRQ_GPT1_CCMPA       0x5F
  #define IRQ_GPT1_CCMPB       0x60
  #define IRQ_GPT1_CMPC        0x61
  #define IRQ_GPT1_CMPD        0x62
  #define IRQ_GPT1_CMPE        0x63
  #define IRQ_GPT1_CMPF        0x64
  #define IRQ_GPT1_OVF         0x65
  #define IRQ_GPT1_UDF         0x66
  #define IRQ_GPT2_CCMPA       0x67
  #define IRQ_GPT2_CCMPB       0x68
  #define IRQ_GPT2_CMPC        0x69
  #define IRQ_GPT2_CMPD        0x6A
  #define IRQ_GPT2_CMPE        0x6B
  #define IRQ_GPT2_CMPF        0x6C
  #define IRQ_GPT2_OVF         0x6D
  #define IRQ_GPT2_UDF         0x6E
  #define IRQ_GPT3_CCMPA       0x6F
  #define IRQ_GPT3_CCMPB       0x70
  #define IRQ_GPT3_CMPC        0x71
  #define IRQ_GPT3_CMPD        0x72
  #define IRQ_GPT3_CMPE        0x73
  #define IRQ_GPT3_CMPF        0x74
  #define IRQ_GPT3_OVF         0x75
  #define IRQ_GPT3_UDF         0x76
  #define IRQ_GPT4_CCMPA       0x77
  #define IRQ_GPT4_CCMPB       0x78
  #define IRQ_GPT4_CMPC        0x79
  #define IRQ_GPT4_CMPD        0x7A
  #define IRQ_GPT4_CMPE        0x7B
  #define IRQ_GPT4_CMPF        0x7C
  #define IRQ_GPT4_OVF         0x7D
  #define IRQ_GPT4_UDF         0x7E
  #define IRQ_GPT5_CCMPA       0x7F
  #define IRQ_GPT5_CCMPB       0x80
  #define IRQ_GPT5_CMPC        0x81
  #define IRQ_GPT5_CMPD        0x82
  #define IRQ_GPT5_CMPE        0x83
  #define IRQ_GPT5_CMPF        0x84
  #define IRQ_GPT5_OVF         0x85
  #define IRQ_GPT5_UDF         0x86
  #define IRQ_GPT6_CCMPA       0x87
  #define IRQ_GPT6_CCMPB       0x88
  #define IRQ_GPT6_CMPC        0x89
  #define IRQ_GPT6_CMPD        0x8A
  #define IRQ_GPT6_CMPE        0x8B
  #define IRQ_GPT6_CMPF        0x8C
  #define IRQ_GPT6_OVF         0x8D
  #define IRQ_GPT6_UDF         0x8E
  #define IRQ_GPT7_CCMPA       0x8F
  #define IRQ_GPT7_CCMPB       0x90
  #define IRQ_GPT7_CMPC        0x91
  #define IRQ_GPT7_CMPD        0x92
  #define IRQ_GPT7_CMPE        0x93
  #define IRQ_GPT7_CMPF        0x94
  #define IRQ_GPT7_OVF         0x95
  #define IRQ_GPT7_UDF         0x96
  #define IRQ_GPT_UVWEDGE      0x97
  #define IRQ_SCI0_RXI         0x98
  #define IRQ_SCI0_TXI         0x99
  #define IRQ_SCI0_TEI         0x9A
  #define IRQ_SCI0_ERI         0x9B
  #define IRQ_SCI0_AM          0x9C
  #define IRQ_SCI0_RXI_OR_ERI  0x9D
  #define IRQ_SCI1_RXI         0x9E
  #define IRQ_SCI1_TXI         0x9F
  #define IRQ_SCI1_TEI         0xA0
  #define IRQ_SCI1_ERI         0xA1
  #define IRQ_SCI1_AM          0xA2
  #define IRQ_SCI2_RXI         0xA3
  #define IRQ_SCI2_TXI         0xA4
  #define IRQ_SCI2_TEI         0xA5
  #define IRQ_SCI2_ERI         0xA6
  #define IRQ_SCI2_AM          0xA7
  #define IRQ_SCI9_RXI         0xA8
  #define IRQ_SCI9_TXI         0xA9
  #define IRQ_SCI9_TEI         0xAA
  #define IRQ_SCI9_ERI         0xAB
  #define IRQ_SCI9_AM          0xAC
  #define IRQ_SPI0_SPRI        0xAD
  #define IRQ_SPI0_SPTI        0xAE
  #define IRQ_SPI0_SPII        0xAF
  #define IRQ_SPI0_SPEI        0xB0
  #define IRQ_SPI0_SPTEND      0xB1
  #define IRQ_SPI1_SPRI        0xB2
  #define IRQ_SPI1_SPTI        0xB3
  #define IRQ_SPI1_SPII        0xB4
  #define IRQ_SPI1_SPEI        0xB5
  #define IRQ_SPI1_SPTEND      0xB6


// ==== Low Power Mode Control ====
  // See datasheet section 10
  #define SYSTEM 0x40010000 // System Registers
  #define SYSTEM_SBYCR   ((volatile unsigned short *)(SYSTEM + 0xE00C))      // Standby Control Register
  #define SYSTEM_MSTPCRA ((volatile unsigned int   *)(SYSTEM + 0xE01C))      // Module Stop Control Register A

  #define MSTP 0x40040000 // Module Registers
  #define MSTP_MSTPCRB   ((volatile unsigned int   *)(MSTP + 0x7000))      // Module Stop Control Register B
  #define MSTPB2   2 // CAN0
  #define MSTPB8   8 // IIC1
  #define MSTPB9   9 // IIC0
  #define MSTPB18 18 // SPI1
  #define MSTPB19 19 // SPI0
  #define MSTPB22 22 // SCI9
  #define MSTPB29 29 // SCI2
  #define MSTPB30 30 // SCI1
  #define MSTPB31 31 // SCI0

  #define MSTP_MSTPCRC   ((volatile unsigned int   *)(MSTP + 0x7004))      // Module Stop Control Register C
  #define MSTP_MSTPCRD   ((volatile unsigned int   *)(MSTP + 0x7008))      // Module Stop Control Register D
  #define MSTPD2   2 // AGT1   - Asynchronous General Purpose Timer 1 Module
  #define MSTPD3   3 // AGT0   - Asynchronous General Purpose Timer 0 Module
  #define MSTPD5   5 // GPT320 and GPT321 General 32 bit PWM Timer Module
  #define MSTPD6   6 // GPT162 to GPT167 General 16 bit PWM Timer Module
  #define MSTPD14 14 // POEG   - Port Output Enable for GPT Module Stop
  #define MSTPD16 16 // ADC140 - 14-Bit A/D Converter Module
  #define MSTPD19 19 // DAC8   -  8-Bit D/A Converter Module
  #define MSTPD20 20 // DAC12  - 12-Bit D/A Converter Module
  #define MSTPD29 29 // ACMPLP - Low-Power Analog Comparator Module
  #define MSTPD31 31 // OPAMP  - Operational Amplifier Module

  // The Mode Control bits are read as 1, the write value should be 1.
  // Bit value 0: Cancel the module-stop state 
  // Bit value 1: Enter the module-stop state.

// ==== Asynchronous General Purpose Timer (AGT) ====
  #define AGTBASE 0x40084000 
  #define AGT0_AGTCR    ((volatile unsigned char  *)(AGTBASE + 0x008))  // AGT Control Register

// ==== ADC14 ====
  // 35.2 Register Descriptions
  #define ADCBASE 0x40050000 /* ADC Base */

  #define ADC140_ADCSR   ((volatile unsigned short *)(ADCBASE + 0xC000)) // A/D Control Register
  #define ADC140_ADANSA0 ((volatile unsigned short *)(ADCBASE + 0xC004)) // A/D Channel Select Register A0
  #define ADC140_ADANSA1 ((volatile unsigned short *)(ADCBASE + 0xC006)) // A/D Channel Select Register A1
  #define ADC140_ADADS0  ((volatile unsigned short *)(ADCBASE + 0xC008)) // A/D-Converted Value Addition/Average Channel Select Register 0
  #define ADC140_ADADS1  ((volatile unsigned short *)(ADCBASE + 0xC00A)) // A/D-Converted Value Addition/Average Channel Select Register 1
  #define ADC140_ADCER   ((volatile unsigned short *)(ADCBASE + 0xC00E)) // A/D Control Extended Register 
  #define ADC140_ADSTRGR ((volatile unsigned short *)(ADCBASE + 0xC010)) // A/D Conversion Start Trigger Select Register
  #define ADC140_ADEXICR ((volatile unsigned short *)(ADCBASE + 0xC012)) // A/D Conversion Extended Input Control Register
  #define ADC140_ADANSB0 ((volatile unsigned short *)(ADCBASE + 0xC014)) // A/D Channel Select Register B0
  #define ADC140_ADANSB1 ((volatile unsigned short *)(ADCBASE + 0xC016)) // A/D Channel Select Register B1
  #define ADC140_ADTSDR  ((volatile unsigned short *)(ADCBASE + 0xC01A)) // A/D conversion result of temperature sensor output
  #define ADC140_ADOCDR  ((volatile unsigned short *)(ADCBASE + 0xC01C)) // A/D result of internal reference voltage
  #define ADC140_ADRD    ((volatile unsigned short *)(ADCBASE + 0xC01E)) // A/D Self-Diagnosis Data Register

  #define ADC140_ADDR00 ((volatile unsigned short *)(ADCBASE + 0xC020))      // A1 (P000 AN00 AMP+)
  #define ADC140_ADDR01 ((volatile unsigned short *)(ADCBASE + 0xC020 +  2)) // A2 (P001 AN01 AMP-) 
  #define ADC140_ADDR02 ((volatile unsigned short *)(ADCBASE + 0xC020 +  4)) // A3 (P002 AN02 AMPO) 
  #define ADC140_ADDR05 ((volatile unsigned short *)(ADCBASE + 0xC020 + 10)) // Aref (P010 AN05 VrefH0)
  #define ADC140_ADDR09 ((volatile unsigned short *)(ADCBASE + 0xC020 + 18)) // A0 (P014 AN09 DAC)
  #define ADC140_ADDR21 ((volatile unsigned short *)(ADCBASE + 0xC040 + 10)) // A4 (P101 AN21 SDA) 
  #define ADC140_ADDR22 ((volatile unsigned short *)(ADCBASE + 0xC040 + 12)) // A5 (P100 AN20 SCL) 

  #define ADC140_ADHVREFCNT ((volatile unsigned char  *)(ADCBASE + 0xC08A)) // A/D High-Potential/Low-Potential Reference Voltage Control Register
  #define ADC140_ADADC      ((volatile unsigned char  *)(ADCBASE + 0xC00C)) // A/D-Converted Value Addition/Average Count Select Register

  #define ADC140_ADSSTR00 ((volatile unsigned char *)(ADCBASE + 0xC0E0))      // AN00 A/D Sampling State Register

// ==== 12-Bit D/A Converter ====
  #define DACBASE 0x40050000          // DAC Base - DAC output on A0 (P014 AN09 DAC)
  #define DAC12_DADR0    ((volatile unsigned short *)(DACBASE + 0xE000))      // D/A Data Register 0 
  #define DAC12_DACR     ((volatile unsigned char  *)(DACBASE + 0xE004))      // D/A Control Register
  #define DAC12_DADPR    ((volatile unsigned char  *)(DACBASE + 0xE005))      // DADR0 Format Select Register
  #define DAC12_DAADSCR  ((volatile unsigned char  *)(DACBASE + 0xE006))      // D/A A/D Synchronous Start Control Register
  #define DAC12_DAVREFCR ((volatile unsigned char  *)(DACBASE + 0xE007))      // D/A VREF Control Register


// ==== Ports ====
  // 19.2.5 Port mn Pin Function Select Register (PmnPFS/PmnPFS_HA/PmnPFS_BY) (m = 0 to 9; n = 00 to 15)
  #define PORTBASE 0x40040000 /* Port Base */

  #define P000PFS 0x0800  // Port 0 Pin Function Select Register
  #define PFS_P000PFS ((volatile unsigned int *)(PORTBASE + P000PFS))            // A1 / D15 - AN00 - AMP0+ - IRQ6
  #define PFS_P001PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 1 * 4))) // A2 / D16 - AN01 - AMP0- - IRQ7
  #define PFS_P002PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 2 * 4))) // A3 / D17 - AN03 - AMP0O - IRQ2
  #define PFS_P003PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 3 * 4))) // N/C - AN03
  #define PFS_P004PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 4 * 4))) // N/C - AN04 - IRQ3
  #define PFS_P005PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 5 * 4))) // N/A - AN11 - IRQ10
  #define PFS_P006PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 6 * 4))) // N/A - AN12
  #define PFS_P007PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 7 * 4))) // N/A - AN13
  #define PFS_P008PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 8 * 4))) // N/A - AN14
  // #define PFS_P009PFS ((volatile unsigned int *)(PORTBASE + P000PFS + ( 9 * 4))) // Does not exist
  #define PFS_P010PFS ((volatile unsigned int *)(PORTBASE + P000PFS + (10 * 4))) // N/A - AN05
  #define PFS_P011PFS ((volatile unsigned int *)(PORTBASE + P000PFS + (11 * 4))) // N/C - AN06 - IRQ15
  #define PFS_P012PFS ((volatile unsigned int *)(PORTBASE + P000PFS + (12 * 4))) // TxLED - AN07
  #define PFS_P013PFS ((volatile unsigned int *)(PORTBASE + P000PFS + (13 * 4))) // RxLED - AN08
  #define PFS_P014PFS ((volatile unsigned int *)(PORTBASE + P000PFS + (14 * 4))) // A0 / D14 - AN09 - DAC0
  #define PFS_P015PFS ((volatile unsigned int *)(PORTBASE + P000PFS + (15 * 4))) // N/C - AN10 - IRQ7

  #define P100PFS 0x0840  // Port 1 Pin Function Select Register
  #define PFS_P100PFS ((volatile unsigned int *)(PORTBASE + P100PFS))            // A5 / D19 - MISOA - SCL1 - IRQ2
  #define PFS_P101PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 1 * 4))) // A4 / D18 - MOSIA - SDA1 - IRQ1
  #define PFS_P102PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 2 * 4))) // D5 - RSPCKA
  #define PFS_P103PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 3 * 4))) // D4 - SSLA0
  #define PFS_P104PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 4 * 4))) // D3 - IRQ1
  #define PFS_P105PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 5 * 4))) // D2 - IRQ0
  #define PFS_P106PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 6 * 4))) // D6
  #define PFS_P107PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 7 * 4))) // D7
  #define PFS_P108PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 8 * 4))) // SWD p2 SWDIO
  #define PFS_P109PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 9 * 4))) // D11 / MOSI
  #define PFS_P110PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (10 * 4))) // D12 / MISO - IRQ3
  #define PFS_P111PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (11 * 4))) // D13 / SCLK - IRQ4
  #define PFS_P112PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (12 * 4))) // D10 / CS
  #define PFS_P113PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (13 * 4))) // N/C
  #define PFS_P114PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (14 * 4))) // N/A
  #define PFS_P115PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (15 * 4))) // N/A

  #define P200PFS 0x0880  // Port 2 Pin Function Select Register
  #define PFS_P200PFS ((volatile unsigned int *)(PORTBASE + P200PFS))           // NMI
  #define PFS_P201PFS ((volatile unsigned int *)(PORTBASE + P200PFS + (1 * 4))) // MD
  #define PFS_P202PFS ((volatile unsigned int *)(PORTBASE + P200PFS + (2 * 4))) // N/A
  #define PFS_P203PFS ((volatile unsigned int *)(PORTBASE + P200PFS + (3 * 4))) // N/A
  #define PFS_P204PFS ((volatile unsigned int *)(PORTBASE + P200PFS + (4 * 4))) // LOVE (Heart Pad on underside of board)
  #define PFS_P205PFS ((volatile unsigned int *)(PORTBASE + P200PFS + (5 * 4))) // N/C - IRQ1
  #define PFS_P206PFS ((volatile unsigned int *)(PORTBASE + P200PFS + (6 * 4))) // N/C - IRQ0
  // Pins P212, P213, P214, and P215 are Crystal functions, or N/C

  #define P300PFS 0x08C0  // Port 3 Pin Function Select Register
  #define PFS_P300PFS ((volatile unsigned int *)(PORTBASE + P300PFS))            // SWD p4 SWCLK
  #define PFS_P301PFS ((volatile unsigned int *)(PORTBASE + P300PFS + ( 1 * 4))) // D0 / RxD - IRQ6
  #define PFS_P302PFS ((volatile unsigned int *)(PORTBASE + P300PFS + ( 2 * 4))) // D1 / TxD - IRQ5
  #define PFS_P303PFS ((volatile unsigned int *)(PORTBASE + P300PFS + ( 3 * 4))) // D9
  #define PFS_P304PFS ((volatile unsigned int *)(PORTBASE + P300PFS + ( 4 * 4))) // D8  - IRQ9
  #define PFS_P305PFS ((volatile unsigned int *)(PORTBASE + P300PFS + ( 5 * 4))) // N/C - IRQ8
  #define PFS_P306PFS ((volatile unsigned int *)(PORTBASE + P300PFS + ( 6 * 4))) // N/C
  #define PFS_P307PFS ((volatile unsigned int *)(PORTBASE + P300PFS + ( 7 * 4))) // N/C

  #define P400PFS 0x0900  // Port 4 Pin Function Select Register
  #define PFS_P400PFS ((volatile unsigned int *)(PORTBASE + P100PFS))            // N/C - IRQ0
  #define PFS_P401PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 1 * 4))) // N/C - IRQ5
  #define PFS_P402PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 2 * 4))) // N/C - IRQ4
  #define PFS_P403PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 3 * 4))) // N/A
  #define PFS_P404PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 4 * 4))) // N/A
  #define PFS_P405PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 5 * 4))) // N/A
  #define PFS_P406PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 6 * 4))) // N/A
  #define PFS_P407PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 7 * 4))) // ADTRG0 - R7, R8, and R9 divider.
  #define PFS_P408PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 8 * 4))) // N/C - IRQ7
  #define PFS_P409PFS ((volatile unsigned int *)(PORTBASE + P100PFS + ( 9 * 4))) // N/C - IRQ6
  #define PFS_P410PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (10 * 4))) // N/C - IRQ5
  #define PFS_P411PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (11 * 4))) // N/C - IRQ4
  #define PFS_P412PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (12 * 4))) // N/A
  #define PFS_P413PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (13 * 4))) // N/A
  #define PFS_P414PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (14 * 4))) // N/A - IRQ9
  #define PFS_P415PFS ((volatile unsigned int *)(PORTBASE + P100PFS + (15 * 4))) // N/A - IRQ8

  #define P500PFS 0x0940  // Port 5 Pin Function Select Register
  #define PFS_P500PFS ((volatile unsigned int *)(PORTBASE + P500PFS))           // AN016 in R10/R26 divider
  #define PFS_P501PFS ((volatile unsigned int *)(PORTBASE + P500PFS + (1 * 4))) // SWD p8 TxD - IRQ11
  #define PFS_P502PFS ((volatile unsigned int *)(PORTBASE + P500PFS + (2 * 4))) // SWD p7 RxD - IRQ12
  #define PFS_P503PFS ((volatile unsigned int *)(PORTBASE + P500PFS + (3 * 4))) // N/A
  #define PFS_P504PFS ((volatile unsigned int *)(PORTBASE + P500PFS + (4 * 4))) // N/A
  #define PFS_P505PFS ((volatile unsigned int *)(PORTBASE + P500PFS + (5 * 4))) // N/A - IRQ14

  #define PFS_PODR   0  // Pin Output Data     - 0: Low output; 1: High output
  #define PFS_PIDR   1  // Pin Input State     - Read 0: Low level; 1: High level
  #define PFS_PDR    2  // Pin Direction       - 0: Input (input pin); 1: Output (output pin)
  #define PFS_PCR    4  // Pull-up Control     - 1: Enable internal pull-up 
  #define PFS_NCODR  6  // N-Channel Open Drain Control - 1: NMOS open-drain output.
  #define PFS_DSCR  10  // Port Drive Capability - 1: Middle drive; Default 0: Low drive
  #define PFS_EOR   12  // Event on Rising     - 1: Detect rising edge  - Set EOR and EOF both to 1
  #define PFS_EOF   13  // Event on Falling    - 1: Detect falling edge - ... for Detect both edges
  #define PFS_ISEL  14  // IRQ Input Enable    - 1: Used as an IRQn input pin.
  #define PFS_ASEL  15  // Analog Input Enable - 1: Used as an analog pin.
  #define PFS_PMR   16  // Pin Mode Control    - 1: Used as an I/O port for peripheral functions
  #define PFS_PSEL_4_0 24 // Peripheral Function Select

  // 16 bit register access
  #define PFS_P100PFS_HA ((volatile unsigned short *)(PORTBASE + 0x0842))
  #define PFS_P115PFS_HA ((volatile unsigned short *)(PORTBASE + 0x0842 + (15 * 2))) 
  #define PFS_P200PFS_HA ((volatile unsigned short *)(PORTBASE + 0x0882))
  #define PFS_P206PFS_HA ((volatile unsigned short *)(PORTBASE + 0x0882 + (06 * 2))) //

  // 8 bits - Used for fast pin set/clear operations of register lower byte
  #define PFS_P000PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803))            // A1
  #define PFS_P001PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 1 * 4))) // A2
  #define PFS_P002PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 2 * 4))) // A3
  #define PFS_P003PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 3 * 4))) // N/C
  #define PFS_P004PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 4 * 4))) // N/C
  #define PFS_P005PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 5 * 4))) // N/A
  #define PFS_P006PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 6 * 4))) // N/A
  #define PFS_P007PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 7 * 4))) // N/A
  #define PFS_P008PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 8 * 4))) // N/A
  // #define PFS_P009PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + ( 9 * 4))) //
  #define PFS_P010PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + (10 * 4))) // N/A
  #define PFS_P011PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + (11 * 4))) // N/C - P58 - VREFL0 << WTF!!!
  #define PFS_P012PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + (12 * 4))) // TxLED - VREFH
  #define PFS_P013PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + (13 * 4))) // RxLED - VREFL
  #define PFS_P014PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + (14 * 4))) // A0 - DAC0
  #define PFS_P015PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0803 + (15 * 4))) // N/C

  #define PFS_P100PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843))            // A5
  #define PFS_P101PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 1 * 4))) // A4
  #define PFS_P102PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 2 * 4))) // D5
  #define PFS_P103PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 3 * 4))) // D4
  #define PFS_P104PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 4 * 4))) // D3
  #define PFS_P105PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 5 * 4))) // D2
  #define PFS_P106PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 6 * 4))) // D6
  #define PFS_P107PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 7 * 4))) // D7
  #define PFS_P108PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 8 * 4))) // SWDIO
  #define PFS_P109PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + ( 9 * 4))) // D11 / MOSI
  #define PFS_P110PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + (10 * 4))) // D12 / MISO
  #define PFS_P111PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + (11 * 4))) // D13 / SCLK
  #define PFS_P112PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + (12 * 4))) // D10 / CS
  #define PFS_P113PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + (13 * 4))) // N/C
  #define PFS_P114PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + (14 * 4))) // N/A
  #define PFS_P115PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0843 + (15 * 4))) // N/A

  #define PFS_P200PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0883))            // NMI input
  #define PFS_P201PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0883 + (01 * 4))) // MD
  #define PFS_P202PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0883 + (02 * 4))) // N/A
  #define PFS_P203PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0883 + (03 * 4))) // N/A
  #define PFS_P204PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0883 + (04 * 4))) // LOVE (Heart Pad on underside of board)
  #define PFS_P205PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0883 + (05 * 4))) // N/C
  #define PFS_P206PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x0883 + (06 * 4))) // N/C

  #define PFS_P212PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08B3))            // EXTAL
  #define PFS_P213PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08B3 + (01 * 4))) // XTAL
  #define PFS_P214PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08B3 + (02 * 4))) // N/C XCOUT (P214 IN)
  #define PFS_P215PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08B3 + (03 * 4))) // N/C XCIN  (P215 IN)

  #define PFS_P300PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3))            // SWCLK (P300)
  #define PFS_P301PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3 + (01 * 4))) // D0 / RxD (P301)
  #define PFS_P302PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3 + (02 * 4))) // D1 / TxD (P302)
  #define PFS_P303PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3 + (03 * 4))) // D9
  #define PFS_P304PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3 + (04 * 4))) // D8
  #define PFS_P305PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3 + (05 * 4))) // N/C
  #define PFS_P306PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3 + (06 * 4))) // N/C
  #define PFS_P307PFS_BY ((volatile unsigned char  *)(PORTBASE + 0x08C3 + (07 * 4))) // N/C


// ==== General PWM Timer (GPT) - Timers 0 to 7 ====
  #define GPTBASE 0x40070000 /* PWM Base */

  #define GTWP 0x8000  // General PWM Timer Write-Protection Register
  #define GPT320_GTWP ((volatile unsigned int *)(GPTBASE + GTWP))           
  #define GPT321_GTWP ((volatile unsigned int *)(GPTBASE + GTWP + 0x0100))
  #define GPT162_GTWP ((volatile unsigned int *)(GPTBASE + GTWP + 0x0200))
  #define GPT163_GTWP ((volatile unsigned int *)(GPTBASE + GTWP + 0x0300))
  #define GPT164_GTWP ((volatile unsigned int *)(GPTBASE + GTWP + 0x0400))
  #define GPT165_GTWP ((volatile unsigned int *)(GPTBASE + GTWP + 0x0500))
  #define GPT166_GTWP ((volatile unsigned int *)(GPTBASE + GTWP + 0x0600))
  #define GPT167_GTWP ((volatile unsigned int *)(GPTBASE + GTWP + 0x0700))

  #define GTSTR 0x8004  // General PWM Timer Software Start Register
  #define GPT320_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR))           
  #define GPT321_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR + 0x0100))
  #define GPT162_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR + 0x0200))
  #define GPT163_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR + 0x0300))
  #define GPT164_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR + 0x0400))
  #define GPT165_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR + 0x0500))
  #define GPT166_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR + 0x0600))
  #define GPT167_GTSTR ((volatile unsigned int *)(GPTBASE + GTSTR + 0x0700))

  #define GTSTP 0x8008  // General PWM Timer Software Stop Register
  #define GPT320_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP))           
  #define GPT321_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP + 0x0100))
  #define GPT162_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP + 0x0200))
  #define GPT163_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP + 0x0300))
  #define GPT164_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP + 0x0400))
  #define GPT165_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP + 0x0500))
  #define GPT166_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP + 0x0600))
  #define GPT167_GTSTP ((volatile unsigned int *)(GPTBASE + GTSTP + 0x0700))

  #define GTCLR 0x800C  // General PWM Timer Software Clear Register
  #define GPT320_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR))           
  #define GPT321_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR + 0x0100))
  #define GPT162_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR + 0x0200))
  #define GPT163_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR + 0x0300))
  #define GPT164_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR + 0x0400))
  #define GPT165_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR + 0x0500))
  #define GPT166_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR + 0x0600))
  #define GPT167_GTCLR ((volatile unsigned int *)(GPTBASE + GTCLR + 0x0700))

  #define GTSSR 0x8010  // General PWM Timer Start Source Select Register
  #define GPT320_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR))           
  #define GPT321_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR + 0x0100))
  #define GPT162_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR + 0x0200))
  #define GPT163_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR + 0x0300))
  #define GPT164_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR + 0x0400))
  #define GPT165_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR + 0x0500))
  #define GPT166_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR + 0x0600))
  #define GPT167_GTSSR ((volatile unsigned int *)(GPTBASE + GTSSR + 0x0700))

  #define GTPSR 0x8014  // General PWM Timer Stop Source Select Register
  #define GPT320_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR))           
  #define GPT321_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR + 0x0100))
  #define GPT162_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR + 0x0200))
  #define GPT163_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR + 0x0300))
  #define GPT164_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR + 0x0400))
  #define GPT165_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR + 0x0500))
  #define GPT166_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR + 0x0600))
  #define GPT167_GTPSR ((volatile unsigned int *)(GPTBASE + GTPSR + 0x0700))

  #define GTCSR 0x8018  // General PWM Timer Clear Source Select Register
  #define GPT320_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR))           
  #define GPT321_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR + 0x0100))
  #define GPT162_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR + 0x0200))
  #define GPT163_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR + 0x0300))
  #define GPT164_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR + 0x0400))
  #define GPT165_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR + 0x0500))
  #define GPT166_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR + 0x0600))
  #define GPT167_GTCSR ((volatile unsigned int *)(GPTBASE + GTCSR + 0x0700))

  #define GTUPSR 0x801C  // General PWM Timer Up Count Source Select Register
  #define GPT320_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR))           
  #define GPT321_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR + 0x0100))
  #define GPT162_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR + 0x0200))
  #define GPT163_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR + 0x0300))
  #define GPT164_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR + 0x0400))
  #define GPT165_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR + 0x0500))
  #define GPT166_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR + 0x0600))
  #define GPT167_GTUPSR ((volatile unsigned int *)(GPTBASE + GTUPSR + 0x0700))

  #define GTDNSR 0x8020  // General PWM Timer Down Count Source Select Register
  #define GPT320_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR))           
  #define GPT321_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR + 0x0100))
  #define GPT162_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR + 0x0200))
  #define GPT163_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR + 0x0300))
  #define GPT164_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR + 0x0400))
  #define GPT165_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR + 0x0500))
  #define GPT166_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR + 0x0600))
  #define GPT167_GTDNSR ((volatile unsigned int *)(GPTBASE + GTDNSR + 0x0700))

  #define GTICASR 0x8024 // General PWM Timer Input Capture Source Select Register A 
  #define GTICBSR 0x8028 // General PWM Timer Input Capture Source Select Register B 

  #define GTCR 0x802C // General PWM Timer Control Register
  #define GPT320_GTCR ((volatile unsigned int *)(GPTBASE + GTCR))           
  #define GPT321_GTCR ((volatile unsigned int *)(GPTBASE + GTCR + 0x0100))
  #define GPT162_GTCR ((volatile unsigned int *)(GPTBASE + GTCR + 0x0200))
  #define GPT163_GTCR ((volatile unsigned int *)(GPTBASE + GTCR + 0x0300))
  #define GPT164_GTCR ((volatile unsigned int *)(GPTBASE + GTCR + 0x0400))
  #define GPT165_GTCR ((volatile unsigned int *)(GPTBASE + GTCR + 0x0500))
  #define GPT166_GTCR ((volatile unsigned int *)(GPTBASE + GTCR + 0x0600))
  #define GPT167_GTCR ((volatile unsigned int *)(GPTBASE + GTCR + 0x0700))

  #define GTUDDTYC 0x8030 // General PWM Timer Count Direction and Duty Setting Register
  #define GPT320_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC))           
  #define GPT321_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC + 0x0100))
  #define GPT162_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC + 0x0200))
  #define GPT163_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC + 0x0300))
  #define GPT164_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC + 0x0400))
  #define GPT165_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC + 0x0500))
  #define GPT166_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC + 0x0600))
  #define GPT167_GTUDDTYC ((volatile unsigned int *)(GPTBASE + GTUDDTYC + 0x0700))

  #define GTIOR 0x8034 // General PWM Timer I/O Control Register
  #define GPT320_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR))           
  #define GPT321_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR + 0x0100))
  #define GPT162_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR + 0x0200))
  #define GPT163_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR + 0x0300))
  #define GPT164_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR + 0x0400))
  #define GPT165_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR + 0x0500))
  #define GPT166_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR + 0x0600))
  #define GPT167_GTIOR ((volatile unsigned int *)(GPTBASE + GTIOR + 0x0700))

  #define GTST 0x803C // General PWM Timer Status Register
  #define GPT320_GTST ((volatile unsigned int *)(GPTBASE + GTST))           
  #define GPT321_GTST ((volatile unsigned int *)(GPTBASE + GTST + 0x0100))
  #define GPT162_GTST ((volatile unsigned int *)(GPTBASE + GTST + 0x0200))
  #define GPT163_GTST ((volatile unsigned int *)(GPTBASE + GTST + 0x0300))
  #define GPT164_GTST ((volatile unsigned int *)(GPTBASE + GTST + 0x0400))
  #define GPT165_GTST ((volatile unsigned int *)(GPTBASE + GTST + 0x0500))
  #define GPT166_GTST ((volatile unsigned int *)(GPTBASE + GTST + 0x0600))
  #define GPT167_GTST ((volatile unsigned int *)(GPTBASE + GTST + 0x0700))

  #define GTBER 0x8040 // General PWM Timer Buffer Enable Register
  #define GPT320_GTBER ((volatile unsigned int *)(GPTBASE + GTBER))           
  #define GPT321_GTBER ((volatile unsigned int *)(GPTBASE + GTBER + 0x0100))
  #define GPT162_GTBER ((volatile unsigned int *)(GPTBASE + GTBER + 0x0200))
  #define GPT163_GTBER ((volatile unsigned int *)(GPTBASE + GTBER + 0x0300))
  #define GPT164_GTBER ((volatile unsigned int *)(GPTBASE + GTBER + 0x0400))
  #define GPT165_GTBER ((volatile unsigned int *)(GPTBASE + GTBER + 0x0500))
  #define GPT166_GTBER ((volatile unsigned int *)(GPTBASE + GTBER + 0x0600))
  #define GPT167_GTBER ((volatile unsigned int *)(GPTBASE + GTBER + 0x0700))

  // Note: GTCNT can only be written to after the counting stops
  #define GTCNT 0x8048 // General PWM Timer Counter
  #define GPT320_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT))           
  #define GPT321_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT + 0x0100))
  #define GPT162_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT + 0x0200))
  #define GPT163_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT + 0x0300))
  #define GPT164_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT + 0x0400))
  #define GPT165_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT + 0x0500))
  #define GPT166_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT + 0x0600))
  #define GPT167_GTCNT ((volatile unsigned int *)(GPTBASE + GTCNT + 0x0700))

  #define GTCCRA 0x804C // General PWM Timer Compare Capture Register A
  #define GPT320_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA))           
  #define GPT321_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA + 0x0100))
  #define GPT162_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA + 0x0200))
  #define GPT163_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA + 0x0300))
  #define GPT164_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA + 0x0400))
  #define GPT165_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA + 0x0500))
  #define GPT166_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA + 0x0600))
  #define GPT167_GTCCRA ((volatile unsigned int *)(GPTBASE + GTCCRA + 0x0700))

  #define GTCCRB 0x8050 // General PWM Timer Compare Capture Register B
  #define GPT320_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB))           
  #define GPT321_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB + 0x0100))
  #define GPT162_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB + 0x0200))
  #define GPT163_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB + 0x0300))
  #define GPT164_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB + 0x0400))
  #define GPT165_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB + 0x0500))
  #define GPT166_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB + 0x0600))
  #define GPT167_GTCCRB ((volatile unsigned int *)(GPTBASE + GTCCRB + 0x0700))

  #define GTCCRC 0x8054 // General PWM Timer Compare Capture Register C
  #define GPT320_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC))           
  #define GPT321_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC + 0x0100))
  #define GPT162_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC + 0x0200))
  #define GPT163_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC + 0x0300))
  #define GPT164_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC + 0x0400))
  #define GPT165_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC + 0x0500))
  #define GPT166_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC + 0x0600))
  #define GPT167_GTCCRC ((volatile unsigned int *)(GPTBASE + GTCCRC + 0x0700))

  //#define GTCCRD 0x805C // General PWM Timer Compare Capture Register D  - See page 425 22.2.19
  #define GTCCRD 0x8058 // General PWM Timer Compare Capture Register D
  #define GPT320_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD))           
  #define GPT321_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD + 0x0100))
  #define GPT162_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD + 0x0200))
  #define GPT163_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD + 0x0300))
  #define GPT164_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD + 0x0400))
  #define GPT165_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD + 0x0500))
  #define GPT166_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD + 0x0600))
  #define GPT167_GTCCRD ((volatile unsigned int *)(GPTBASE + GTCCRD + 0x0700))

  //#define GTCCRE 0x8058 // General PWM Timer Compare Capture Register E  - As above...
  #define GTCCRE 0x805C // General PWM Timer Compare Capture Register E
  #define GPT320_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE))           
  #define GPT321_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE + 0x0100))
  #define GPT162_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE + 0x0200))
  #define GPT163_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE + 0x0300))
  #define GPT164_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE + 0x0400))
  #define GPT165_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE + 0x0500))
  #define GPT166_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE + 0x0600))
  #define GPT167_GTCCRE ((volatile unsigned int *)(GPTBASE + GTCCRE + 0x0700))

  #define GTCCRF 0x8060 // General PWM Timer Compare Capture Register F
  #define GPT320_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF))           
  #define GPT321_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF + 0x0100))
  #define GPT162_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF + 0x0200))
  #define GPT163_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF + 0x0300))
  #define GPT164_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF + 0x0400))
  #define GPT165_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF + 0x0500))
  #define GPT166_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF + 0x0600))
  #define GPT167_GTCCRF ((volatile unsigned int *)(GPTBASE + GTCCRF + 0x0700))

  #define GTPR 0x8064 // General PWM Timer Cycle Setting Register
  #define GPT320_GTPR ((volatile unsigned int *)(GPTBASE + GTPR))           
  #define GPT321_GTPR ((volatile unsigned int *)(GPTBASE + GTPR + 0x0100))
  #define GPT162_GTPR ((volatile unsigned int *)(GPTBASE + GTPR + 0x0200))
  #define GPT163_GTPR ((volatile unsigned int *)(GPTBASE + GTPR + 0x0300))
  #define GPT164_GTPR ((volatile unsigned int *)(GPTBASE + GTPR + 0x0400))
  #define GPT165_GTPR ((volatile unsigned int *)(GPTBASE + GTPR + 0x0500))
  #define GPT166_GTPR ((volatile unsigned int *)(GPTBASE + GTPR + 0x0600))
  #define GPT167_GTPR ((volatile unsigned int *)(GPTBASE + GTPR + 0x0700))

  #define GTPBR 0x8068 // General PWM Timer Cycle Setting Buffer Register
  #define GPT320_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR))           
  #define GPT321_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR + 0x0100))
  #define GPT162_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR + 0x0200))
  #define GPT163_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR + 0x0300))
  #define GPT164_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR + 0x0400))
  #define GPT165_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR + 0x0500))
  #define GPT166_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR + 0x0600))
  #define GPT167_GTPBR ((volatile unsigned int *)(GPTBASE + GTPBR + 0x0700))

// ==== NVIC Interrupt Controller ====
  #define NVICBASE 0xE0000000 // NVIC Interrupt Controller

  // asm volatile("dsb"); // <<<< use a DSB instruction to ensure bus-synchronisition for NVIC write operations

  #define NVIC_ICTR    ((volatile unsigned int  *)(NVICBASE + 0xE004))              // Interrupt Controller Type Register
  // Total number of interrupt lines in groups of 32: [3:0]	INTLINESNUM
  // b0000 = 0...32   << RA4M1 returns 0 - Has only 32 Interrupts - See Table 13.3 Interrupt vector table p.237
  // b0001 = 33...64
  // b0010 = 65...96
  // b0011 = 97...128
  // b0100 = 129...160
  // b0101 = 161...192
  // b0110 = 193...224
  // b0111 = 225...256


  // NVIC IRQ registers - Generic ARM Cortex-M4F; not all are necessiraly present in the RA4M1
  // x = 0..7 for each register type, with 32 bits per register, to support up to 240 IRQs
  // * Each bit controls one interrupt, identified by its IRQ# (0..239)
  // * Register# x = IRQ# DIV 32
  // * Bit n in the register = IRQ# MOD 32

  #define NVICISER 0xE100     // Interrupt Set-Enable Registers
  #define NVIC_ISER0  ((volatile unsigned int  *)(NVICBASE + NVICISER +(0 * 4)))     // Register 0
  #define NVIC_ISER1  ((volatile unsigned int  *)(NVICBASE + NVICISER +(1 * 4)))     // Register 1
  #define NVIC_ISER2  ((volatile unsigned int  *)(NVICBASE + NVICISER +(2 * 4)))     // Register 2
  #define NVIC_ISER3  ((volatile unsigned int  *)(NVICBASE + NVICISER +(3 * 4)))     // Register 3
  #define NVIC_ISER4  ((volatile unsigned int  *)(NVICBASE + NVICISER +(4 * 4)))     // Register 4
  #define NVIC_ISER5  ((volatile unsigned int  *)(NVICBASE + NVICISER +(5 * 4)))     // Register 5
  #define NVIC_ISER6  ((volatile unsigned int  *)(NVICBASE + NVICISER +(6 * 4)))     // Register 6
  #define NVIC_ISER7  ((volatile unsigned int  *)(NVICBASE + NVICISER +(7 * 4)))     // Register 7
  #define NVICICER 0xE180     // Interrupt Clear-Enable Registers
  #define NVIC_ICER0  ((volatile unsigned int  *)(NVICBASE + NVICICER +(0 * 4)))     // Register 0
  #define NVIC_ICER1  ((volatile unsigned int  *)(NVICBASE + NVICICER +(1 * 4)))     // Register 1
  #define NVIC_ICER2  ((volatile unsigned int  *)(NVICBASE + NVICICER +(2 * 4)))     // Register 2
  #define NVIC_ICER3  ((volatile unsigned int  *)(NVICBASE + NVICICER +(3 * 4)))     // Register 3
  #define NVIC_ICER4  ((volatile unsigned int  *)(NVICBASE + NVICICER +(4 * 4)))     // Register 4
  #define NVIC_ICER5  ((volatile unsigned int  *)(NVICBASE + NVICICER +(5 * 4)))     // Register 5
  #define NVIC_ICER6  ((volatile unsigned int  *)(NVICBASE + NVICICER +(6 * 4)))     // Register 6
  #define NVIC_ICER7  ((volatile unsigned int  *)(NVICBASE + NVICICER +(7 * 4)))     // Register 7

  #define NVICISPR 0xE200     // Interrupt Set-Pending Registers
  #define NVIC_ISPR0  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(0 * 4)))     // Register 0
  #define NVIC_ISPR1  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(1 * 4)))     // Register 1
  #define NVIC_ISPR2  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(2 * 4)))     // Register 2
  #define NVIC_ISPR3  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(3 * 4)))     // Register 3
  #define NVIC_ISPR4  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(4 * 4)))     // Register 4
  #define NVIC_ISPR5  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(5 * 4)))     // Register 5
  #define NVIC_ISPR6  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(6 * 4)))     // Register 6
  #define NVIC_ISPR7  ((volatile unsigned int  *)(NVICBASE + NVICISPR +(7 * 4)))     // Register 7
  #define NVICICPR 0xE280     // Interrupt Clear-Pending Registers
  #define NVIC_ICPR0  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(0 * 4)))     // Register 0
  #define NVIC_ICPR1  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(1 * 4)))     // Register 1
  #define NVIC_ICPR2  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(2 * 4)))     // Register 2
  #define NVIC_ICPR3  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(3 * 4)))     // Register 3
  #define NVIC_ICPR4  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(4 * 4)))     // Register 4
  #define NVIC_ICPR5  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(5 * 4)))     // Register 5
  #define NVIC_ICPR6  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(6 * 4)))     // Register 6
  #define NVIC_ICPR7  ((volatile unsigned int  *)(NVICBASE + NVICICPR +(7 * 4)))     // Register 7

  #define NVICIABR 0xE300     // Interrupt Active Bit Register - Read Only: Read 1 if interrupt in active state
  #define NVIC_IABR0  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(0 * 4)))     // Register 0
  #define NVIC_IABR1  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(1 * 4)))     // Register 1
  #define NVIC_IABR2  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(2 * 4)))     // Register 2
  #define NVIC_IABR3  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(3 * 4)))     // Register 3
  #define NVIC_IABR4  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(4 * 4)))     // Register 4
  #define NVIC_IABR5  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(5 * 4)))     // Register 5
  #define NVIC_IABR6  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(6 * 4)))     // Register 6
  #define NVIC_IABR7  ((volatile unsigned int  *)(NVICBASE + NVICIABR +(7 * 4)))     // Register 7

  // NVIC_IPRx (x=0..59) – Interrupt Priority Registers
  // * Supports up to 240 interrupts: 0..239 (32 in RA4M1)
  // *  8-bit priority field for each interrupts (4-bit field for RA4M1)
  // *  4 priority values per register (MSB aligned bits of each byte for prioity i.e. 0x10 thru 0xF0)
  // *  0 = highest priority, F = lowest priority (USBs are all at 0xC0, mS Timer on AGT is 0xE0)
  // *  Register# x = IRQ# DIV 4
  // *  Byte offset within the register = IRQ# MOD 4
  // *  Ex. IRQ85:
  // *  85/4 = 21 with remainder 1 (register 21, byte offset 1): Write priority<<8 to NVIC_IPR2
  // *  85/32 = 2 with remainder 21: write 1<<21 to NVIC_SER2


  #define NVICIPR  0xE400     // Interrupt Priority Register
  #define NVIC_IPR00  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(0 * 4)))     // Register 0: NVIC_IPR0 TO 3
  #define NVIC_IPR04  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(1 * 4)))     // Register 1
  #define NVIC_IPR08  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(2 * 4)))     // Register 2
  #define NVIC_IPR12  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(3 * 4)))     // Register 3
  #define NVIC_IPR16  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(4 * 4)))     // Register 4
  #define NVIC_IPR20  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(5 * 4)))     // Register 5
  #define NVIC_IPR24  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(6 * 4)))     // Register 6
  #define NVIC_IPR28  ((volatile unsigned int  *)(NVICBASE + NVICIPR +(7 * 4)))     // Register 7

  // Also byte accessible:
  #define NVIC_IPR00_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  0 ))     // For direct byte access
  #define NVIC_IPR01_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  1 ))     // For direct byte access
  #define NVIC_IPR02_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  2 ))     // For direct byte access
  #define NVIC_IPR03_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  3 ))     // For direct byte access
  #define NVIC_IPR04_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  4 ))     // For direct byte access
  #define NVIC_IPR05_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  5 ))     // For direct byte access
  #define NVIC_IPR06_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  6 ))     // For direct byte access
  #define NVIC_IPR07_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  7 ))     // For direct byte access
  #define NVIC_IPR08_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  8 ))     // For direct byte access
  #define NVIC_IPR09_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR +  9 ))     // For direct byte access
  #define NVIC_IPR10_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 10 ))     // For direct byte access
  #define NVIC_IPR11_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 11 ))     // For direct byte access
  #define NVIC_IPR12_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 12 ))     // For direct byte access
  #define NVIC_IPR13_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 13 ))     // For direct byte access
  #define NVIC_IPR14_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 14 ))     // For direct byte access
  #define NVIC_IPR15_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 15 ))     // For direct byte access
  #define NVIC_IPR16_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 16 ))     // For direct byte access
  #define NVIC_IPR17_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 17 ))     // For direct byte access
  #define NVIC_IPR18_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 18 ))     // For direct byte access
  #define NVIC_IPR19_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 19 ))     // For direct byte access
  #define NVIC_IPR20_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 20 ))     // For direct byte access
  #define NVIC_IPR21_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 21 ))     // For direct byte access
  #define NVIC_IPR22_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 22 ))     // For direct byte access
  #define NVIC_IPR23_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 23 ))     // For direct byte access
  #define NVIC_IPR24_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 24 ))     // For direct byte access
  #define NVIC_IPR25_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 25 ))     // For direct byte access
  #define NVIC_IPR26_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 26 ))     // For direct byte access
  #define NVIC_IPR27_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 27 ))     // For direct byte access
  #define NVIC_IPR28_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 28 ))     // For direct byte access
  #define NVIC_IPR29_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 29 ))     // For direct byte access
  #define NVIC_IPR30_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 30 ))     // For direct byte access
  #define NVIC_IPR31_BY  ((volatile unsigned char  *)(NVICBASE + NVICIPR + 31 ))     // For direct byte access

/* End of Register Definitions */

// === Local Defines

#define SERIAL_DIAGS

// #define ADC_EXT_AREF         // Use external ADC Aref source
// #define ADC_AVARAGE          // Enable 4x averaging i.e. four sucessive conversions
#define ADSSTR00               // Enable Sampling State Register change from default
#define ADSSTR00_VAL 0x08      // A/D Sampling State Register 0 - Default is 0x0D

#define GPT7A_OUTPUT   // Frequency Monitor on D8

#define AUDIO_FRAME_RATE   44118    //  44117.65  // Actual update rate

#define COMPLEX_SINE
#define INHARMONICITY  // Live harmonic/tone frequency offsets
// #define SINE_24_BITS   // Full 25 bit resolution - not needed for 16 bit CD quality output

#define AUDIO_MAX_AMPLITUDE 0x6FFF0000
#define AUDIO_MAX_GLOBAL    0x7FFF0000

#define SINE_GEN_SLOTS     10

#define AUDIO_NOTE_HZ    (float)440.00  // Example tone
#define AUDIO_NOTE_PHASE (float)0.00

#define AUDIO_AMP_0      (float) 1.00
#define AUDIO_AMP_1      (float) 1.00
#define AUDIO_AMP_2      (float) 0.07
#define AUDIO_AMP_3      (float)-0.40
#define AUDIO_AMP_4      (float)-0.07
#define AUDIO_AMP_5      (float) 0.10
#define AUDIO_AMP_6      (float) 0.05
#define AUDIO_AMP_7		   (float)-0.15
#define AUDIO_AMP_8      (float)-0.05
#define AUDIO_AMP_9		   (float) 0.25
#define AUDIO_AMP_10     (float) 0.00
#define AUDIO_AMP_11	   (float) 0.00
#define AUDIO_AMP_12     (float) 0.00

#define AUDIO_ZERO     0
#define AUDIO_FIRST    1
#define AUDIO_SECOND   2
#define AUDIO_THIRD    3
#define AUDIO_FORTH    4
#define AUDIO_FIFTH    5
#define AUDIO_SIXTH    6
#define AUDIO_SEVENTH  7
#define AUDIO_EIGHTH   8
#define AUDIO_NINTH    9
#define AUDIO_TENTH    10
#define AUDIO_ELEVENTH 11
#define AUDIO_TWELFTH  12

// Multiplier for inharmonicity of harmonics
#define AUDIO_INHAM_1    (float)1.00   // 440/440	Note Funderment and Second harmonics match their tones
#define AUDIO_INHAM_2    (float)1.00   // 880/880
#define AUDIO_INHAM_3    (float)1.008  // 1330/1320
#define AUDIO_INHAM_4    (float)1.011  // 1780/1760
#define AUDIO_INHAM_5    (float)1.014  // 2230/2200
#define AUDIO_INHAM_6    (float)1.015  // 2680/2640
#define AUDIO_INHAM_7    (float)1.019  // 3140/3080
#define AUDIO_INHAM_8    (float)1.026  // 3610/3520
#define AUDIO_INHAM_9    (float)1.033  // 4090/3960
#define AUDIO_INHAM_10	 (float)1.039  // 4570/4400
#define AUDIO_INHAM_11	 (float)1.045  // 5060/4840
#define AUDIO_INHAM_12	 (float)1.055  // 5570/5280


static uint32_t sine_freq_table[SINE_GEN_SLOTS];

static float sine_amp_table[SINE_GEN_SLOTS] =
  {
  AUDIO_AMP_0, AUDIO_AMP_1,
  AUDIO_AMP_2, AUDIO_AMP_3,
  AUDIO_AMP_4, AUDIO_AMP_5,
  AUDIO_AMP_6, AUDIO_AMP_7,
  AUDIO_AMP_8, AUDIO_AMP_9
  };

static uint32_t sine_hdelta_table[SINE_GEN_SLOTS]; // Table to hold harmonic delta adding

static int32_t sine_output_table[SINE_GEN_SLOTS];


// ==== Other Global Variables ====

static bool wake_from_int_flag = false;   // Start with WFI true

static uint16_t adc_val_A1;
static uint16_t adc_val_A2;

#ifdef SERIAL_DIAGS
float ext_analog_frequency;
uint32_t ext_freq_time_delta;
int32_t ext_out_sine;
#endif



void setup()
  {
  attachInterrupt(13, timer7interrupt, FALLING);        // This IRQ will be asigned to Slot 05 IELSR05 as 0x001 PORT_IRQ0 - Table 13.4
  *ICU_IELSR05 = IRQ_GPT7_OVF;                          // Assign Slot 05 IELSR05 for GPT7_OVF
  *PFS_P111PFS = 0x00000000;                            // Clear D13 ISEL pin assigned Interrupt Enable
	asm volatile("dsb");                                  // Data bus Synchronization instruction
  *NVIC_IPR05_BY = 0x40;                                // Bounce ICU_IELSR05 irq priority up from 0xC0 to 0x40

  Serial.begin(115200);
//  while (!Serial){};

  setup_adc();
  setup_dac();

  *ADC140_ADCSR   |= (0x01 << 15);   // Start an ADC conversion
  delayMicroseconds(10);
  *AGT0_AGTCR = 0;                     // disable Millis counter, delay etc. don't want this Interrupt messing up output stability

// Setup fast IRQ timers ABSOLUTLY last!!!  
  setup_timer_7();
  }


void loop()
  {
  *PFS_P204PFS_BY = 0x04;         // LOVE Heart-Pad - Low (Changed from D11/SCK as going to use SPI for Dual 16bit External DAC)
  if(wake_from_int_flag == true)
    asm volatile("wfi");          // Stop here and wait for an interrupt
  *PFS_P204PFS_BY = 0x05;         // LOVE Heart-Pad - High

  if(Serial.available() > 0)
    {
    char input_char = Serial.read();  // get one byte from serial buffer
    Serial.println(input_char);
    switch(input_char)
      {
      case 's':
        {
        Serial.println("Enable Wake from Interrupt");
        wake_from_int_flag = true; 
        break;
        }
      case 'r':
        {
        Serial.println("Disable Wake from Interrupt");
        wake_from_int_flag = false;       // Disable WFI, otherwsie double tap on Reset-Button needed
        break;
        }
  #ifdef SERIAL_DIAGS
      case 'f':
        {
        Serial.println(ext_analog_frequency);
        break;
        }
      case 't':
        {
        Serial.println(ext_freq_time_delta);
        break;
        }
      case 'y':
        {
        Serial.println(ext_out_sine);
        break;
        }
  #endif
      case '?':
        {
        serial_commands();
        break;
        }
      default:
        break;
      }
    }

  }

void serial_commands(void)
  {
  Serial.println("\nGPT Timer Setup");
  Serial.println("s = Enable Wake from Interrupt");
  Serial.println("r = Disable Wake from Interrupt");
  #ifdef SERIAL_DIAGS
  Serial.println("f = DDS Frequency");
  Serial.println("t = DDS Delta");
  #endif
  Serial.println("? = This Help List");
  }


void timer7interrupt(void)
  {
  //  static uint16_t localValA0 = 0;  // Board input ADC A0 used for DAC output
  static uint16_t localValA1 = 0;  // Board input ADC A1
  static uint16_t localValA2 = 0;  // Board input ADC A2
  static uint16_t localCount = 0;
  static uint8_t test = 0;

   int32_t out, a , b;
  static int32_t sine_amp_local = 0x7FFFFFFF;
  uint32_t freq_time_delta = 0;  //  
  uint32_t freq_time_delta_2 = 0;  //  
   int16_t result_sine;

  static int32_t out_sine, out_cosine; 
  static int32_t acc_sine, acc_cosine;
   int32_t result_taylor_sine;
   int32_t result_taylor_cosine;

  float sine_freq_local = AUDIO_NOTE_HZ;

  static  int32_t sine_amp_global = AUDIO_MAX_GLOBAL;
  static uint32_t freq_time_cosine;
  static uint32_t freq_time_accumulate = 0;
  static uint32_t freq_time_1st_acc    = 0;
  static uint32_t freq_time_2nd_acc    = 0;
  static uint32_t freq_time_3rd_acc    = 0;
  static uint32_t freq_time_4th_acc    = 0;
  static uint32_t freq_time_5th_acc    = 0;
  static uint32_t freq_time_6th_acc    = 0;
  static uint32_t freq_time_7th_acc    = 0;
  static uint32_t freq_time_8th_acc    = 0;
  static uint32_t freq_time_9th_acc    = 0;
  static uint32_t freq_gen_sine = 0;

  float freq_time_delta_1hz = (4294967295 / AUDIO_FRAME_RATE);  // 97352 for 44.1kHz

  // The lowest note on a standard 88-key piano, A0, is 27.5 Hz
  // The highest note on a piano, C8, is 4186 Hz

  int32_t angle, sum, p1, p2, p3, p5, p7, p9, p11, term; 
  uint32_t ph;
  uint16_t analog_read_value;
  uint16_t analog_write_value;

  *PFS_P107PFS_BY = 0x05;         // D7 start of Timer Interrupt



// ==== ADC ====

  analog_read_value = *ADC140_ADDR00;    // adcValue = analogRead(analogPin); // Internal 16bit register read = c. 123nS 
  *ADC140_ADCSR |= (0x01 << 15);  // Next ADC conversion = write to register c. 300nS

// ==== Sine Gen ====

  float analog_frequency = ((float)analog_read_value / 15.75574) + 25.5;  // ADC = 0 to 65535 (with 2 LSBs low)
  freq_time_delta = (uint32_t)(freq_time_delta_1hz * analog_frequency);  // 
  freq_time_delta_2 = (uint32_t)(freq_time_delta_1hz * 20.00);  // 

  #ifdef SERIAL_DIAGS
  ext_analog_frequency = analog_frequency;
  ext_freq_time_delta  = freq_time_delta;
  ext_out_sine = out_sine;
  #endif

  sine_hdelta_table[0] = freq_time_delta_2;
  sine_hdelta_table[1] = freq_time_delta;
  sine_hdelta_table[2] = (uint32_t)((( (float)freq_time_delta) * 2) * AUDIO_INHAM_2);
  sine_hdelta_table[3] = (uint32_t)((( (float)freq_time_delta) * 3) * AUDIO_INHAM_3);
  sine_hdelta_table[4] = (uint32_t)((( (float)freq_time_delta) * 4) * AUDIO_INHAM_4);
  sine_hdelta_table[5] = (uint32_t)((( (float)freq_time_delta) * 5) * AUDIO_INHAM_5);
  sine_hdelta_table[6] = (uint32_t)((( (float)freq_time_delta) * 6) * AUDIO_INHAM_6);
  sine_hdelta_table[7] = (uint32_t)((( (float)freq_time_delta) * 7) * AUDIO_INHAM_7);
  sine_hdelta_table[8] = (uint32_t)((( (float)freq_time_delta) * 8) * AUDIO_INHAM_8);
  sine_hdelta_table[9] = (uint32_t)((( (float)freq_time_delta) * 9) * AUDIO_INHAM_9);


// Sine Calc(s) 
  *PFS_P103PFS_BY = 0x05;      // D4 Set to time Sine calc(s) 

#ifdef INHARMONICITY
	  sine_freq_table[0] = freq_time_accumulate += freq_time_delta_2;
	  sine_freq_table[1] = freq_time_1st_acc += sine_hdelta_table[1];
	  sine_freq_table[2] = freq_time_2nd_acc += sine_hdelta_table[2];
	  sine_freq_table[3] = freq_time_3rd_acc += sine_hdelta_table[3];
	  sine_freq_table[4] = freq_time_4th_acc += sine_hdelta_table[4];
	  sine_freq_table[5] = freq_time_5th_acc += sine_hdelta_table[5];
	  sine_freq_table[6] = freq_time_6th_acc += sine_hdelta_table[6];
	  sine_freq_table[7] = freq_time_7th_acc += sine_hdelta_table[7];
	  sine_freq_table[8] = freq_time_8th_acc += sine_hdelta_table[8];
	  sine_freq_table[9] = freq_time_9th_acc += sine_hdelta_table[9];
#else
	  sine_freq_table[0] = freq_time_accumulate += freq_time_delta_2;
	  sine_freq_table[1] = freq_time_1st_acc +=  freq_time_delta;
	  sine_freq_table[2] = freq_time_2nd_acc += (freq_time_delta * 2);
	  sine_freq_table[3] = freq_time_3rd_acc += (freq_time_delta * 3);
	  sine_freq_table[4] = freq_time_4th_acc += (freq_time_delta * 4);
	  sine_freq_table[5] = freq_time_5th_acc += (freq_time_delta * 5);
	  sine_freq_table[6] = freq_time_6th_acc += (freq_time_delta * 6);
	  sine_freq_table[7] = freq_time_7th_acc += (freq_time_delta * 7);
	  sine_freq_table[8] = freq_time_8th_acc += (freq_time_delta * 8);
	  sine_freq_table[9] = freq_time_9th_acc += (freq_time_delta * 9);
#endif


	uint8_t sine_gen_count;

	for(sine_gen_count = 0; sine_gen_count < SINE_GEN_SLOTS; sine_gen_count++)
	  {
		freq_gen_sine = sine_freq_table[sine_gen_count];

	  if (freq_gen_sine >= 0xC0000000u || freq_gen_sine < 0x40000000u)
		{
		angle = (int32_t)freq_gen_sine; // valid from -90 to +90 degrees
		}
	  else
		{
		angle = (int32_t)(0x7FFFFFFFu - freq_gen_sine);
		}
		term = angle << 1;
		__asm__ ("smmulr %0, %1, %2" : "=r" (p1) : "r" (term), "r" (1686629713));
		__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p1), "r" (p1));
		p2 = term << 3;
		__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p2), "r" (p1));
		p3 = term << 3;
		term = p1 << 1;
		__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (term), "r" (p3), "r" (1431655765));
		__asm__ ("smmulr %0, %1, %2" : "=r" (term) : "r" (p3), "r" (p2));
		p5 = term << 1;
		__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p5), "r" (286331153));
		__asm__ ("smmulr %0, %1, %2" : "=r" (p7) : "r" (p5), "r" (p2));
		__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p7), "r" (54539267));
#ifdef SINE_24_BITS
		__asm__ ("smmulr %0, %1, %2" : "=r" (p9) : "r" (p7), "r" (p2));
		__asm__ ("smmlar %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p9), "r" (6059919));
		__asm__ ("smmulr %0, %1, %2" : "=r" (p11) : "r" (p9), "r" (p2));
		__asm__ ("smmlsr %0, %2, %3, %1" : "=r" (sum) : "r" (sum), "r" (p11), "r" (440721));
#endif
		result_taylor_sine = sum << 1;

		sine_amp_local = (int)((float)AUDIO_MAX_AMPLITUDE * sine_amp_table[sine_gen_count]);
		__asm__ ("smmulr %0, %1, %2" : "=r" (out_sine) : "r" (result_taylor_sine), "r" (sine_amp_local));
		sine_output_table[sine_gen_count] = out_sine;
	  }

	acc_sine = sine_output_table[1] + sine_output_table[2] + sine_output_table[3] + sine_output_table[4] + sine_output_table[5] + sine_output_table[6] + sine_output_table[7] + sine_output_table[8] + sine_output_table[9];
	acc_cosine = sine_output_table[0];

  __asm__ ("smmulr %0, %1, %2" : "=r" (out_sine) : "r" (acc_sine), "r" (sine_amp_global));
	__asm__ ("smmulr %0, %1, %2" : "=r" (out_cosine) : "r" (acc_cosine), "r" (sine_amp_global));

  *PFS_P103PFS_BY = 0x04;      // D4 Clear - end of Sine

// Output DAC value - DAC is not buffered

  result_sine = (int16_t)(out_sine >> 15);   // 
  *DAC12_DADR0 = result_sine + 32767;

  *GPT167_GTCCRC = (uint32_t)(analog_frequency * 0.25);

  *PFS_P107PFS_BY = 0x04;         // D7 end of Timer Interrupt
  }

// ADC //
void setup_adc(void)
  {
  *MSTP_MSTPCRD &= (0xFFFFFFFF - (0x01 << MSTPD16));  // Enable ADC140 module
  #ifdef ADC_EXT_AREF
  *ADC140_ADHVREFCNT = 0x01;         // Set External Aref = analogReference(AR_EXTERNAL);      
  #endif
  #ifdef ADC_RIGHT_JUST
  *ADC140_ADCER = 0x06;              // 14 bit mode, right justified
  #else
  *ADC140_ADCER = 0x8006;            // 14 bit mode, left-justified
  //  *ADC140_ADCER = 0x8000;            // 12 bit mode, left-justified
  #endif
  *ADC140_ADANSA0 |= (0x01 << 0);    // Selected ANSA00 = A1 as DAC is on A0
  #ifdef ADC_AVARAGE
  *ADC140_ADADC    = 0x83;           // Average mode - 4x and b7 to enable averaging
  *ADC140_ADADS0  |= (0x01 << 0);    // Enable Averaging for ANSA00 channel
  #endif
  #ifdef ADSSTR00
  *ADC140_ADSSTR00 = ADSSTR00_VAL;   // A/D Sampling State Register 0 - Default is 0x0D
  #endif
  }

void setup_dac(void)       // Note make sure ADC is stopped before setup DAC
  {
  *MSTP_MSTPCRD &= (0xFFFFFFFF - (0x01 << MSTPD20));  // Enable DAC12 module
  #ifdef DAC_RIGHT_JUST
  *DAC12_DADPR    = 0x00;        // DADR0 Format Select Register - Set right-justified format
  #else
  *DAC12_DADPR    = 0x80;        // DADR0 Format Select Register - Set left-justified format i.e. 16 bit format, 4 LSBs not used
  #endif
  //  *DAC12_DAADSCR  = 0x80;        // D/A A/D Synchronous Start Control Register - Enable
  *DAC12_DAADSCR  = 0x00;        // D/A A/D Synchronous Start Control Register - Default
  // 36.3.2 Notes on Using the Internal Reference Voltage as the Reference Voltage
  *DAC12_DAVREFCR = 0x00;        // D/A VREF Control Register - Write 0x00 first - see 36.2.5
  *DAC12_DADR0    = 0x0000;      // D/A Data Register 0 
   delayMicroseconds(10);        
  *DAC12_DAVREFCR = 0x01;        // D/A VREF Control Register - Select AVCC0/AVSS0 for Vref
  //  *DAC12_DAVREFCR = 0x03;        // D/A VREF Control Register - Select Internal reference voltage/AVSS0
  //  *DAC12_DAVREFCR = 0x06;        // D/A VREF Control Register - Select External Vref; set VREFH&L pins used for LEDs
  *DAC12_DACR     = 0x5F;        // D/A Control Register - 
   delayMicroseconds(5);         // 
  #ifdef DAC_RIGHT_JUST
  *DAC12_DADR0    = 0x0800;      // Set D/A Data Register to Midrange "Zero" Value 
  #else
  *DAC12_DADR0    = 0x8000;      // Set D/A Data Register to Midrange "Zero" Value 
  #endif
  *PFS_P014PFS   = 0x00000000;   // Make sure all cleared
  *PFS_P014PFS  |= (0x1 << 15);  // Port Mode Control - Used as an analog pin
  }

// ==== GPT - General Purpose Timers ==== //

void setup_timer_7(void)
  {
  *MSTP_MSTPCRD &= (0xFFFFFFFF - (0x01 << MSTPD6));  // Enable GTP16 timer module
                //   76543210
  *GPT167_GTSTP  = 0b10000000; // Stop Timer 7  - Doesn't matter which timer is addressed

  // Timer 7 - Sawtooth Mode 
  *GPT167_GTSSR = 0x80000000; // b31 CSTRT Software Source Counter Start Enable
  *GPT167_GTPSR = 0x80000000; // b31 CSTOP Software Source Counter Stop Enable
  *GPT167_GTCSR = 0x80000000; // b31 CCLR  Software Source Counter Clear Enable

  #define TIMER_COUNT  0x043F     // 1087 Decimal, for 1088 counts (44.10kHz exact is 1088.4354)
  #define TIMER_HALF_COUNT TIMER_COUNT / 2    // Set for 50% PWM

  *GPT167_GTUDDTYC = 0x1;
  *GPT167_GTCNT  = 0x0000;     // Set Counter value
  *GPT167_GTCCRA = TIMER_HALF_COUNT;
  *GPT167_GTCCRB = TIMER_HALF_COUNT;
  *GPT167_GTCCRC = TIMER_HALF_COUNT;
  *GPT167_GTCCRD = TIMER_HALF_COUNT;
  *GPT167_GTPR   = TIMER_COUNT;
  *GPT167_GTPBR  = TIMER_COUNT;
  *GPT167_GTBER  = 0x00150000; // PR, CCRB, and CCRA set to single buffer operation 

  // b26-b24 - b26 to b24 TPCS[2:0] Timer Prescaler Select
  //  0 0 0: PCLKD/1 
  //  0 0 1: PCLKD/4
  //  0 1 0: PCLKD/16
  //  0 1 1: PCLKD/64
  //  1 0 0: PCLKD/256
  //  1 0 1: PCLKD/1024.
  *GPT167_GTCR   = 0x0;           // Set Sawtooth mode, PreScale to PCLKD/1 = 1465Hz with Counter set to 0x7FFF
  #ifdef PRE_SCALE_DIV64
  *GPT167_GTCR   = 0b011 << 24;   // Set PreScale to PCLKD/64 = 22.89Hz with Counter set to 0x7FFF
  #endif

  // RA4M1 Data-Sheet - 22.2.14 General PWM Timer I/O Control Register (GTIOR)
  //                  - Table 22.5 Settings of GTIOA[4:0] and GTIOB[4:0] bits
  *GPT167_GTIOR  = 0x00000000;        // Clear I/O Control Register

  #ifdef GPT7A_OUTPUT   // Frequency Monitor on D8
  //  *GPT167_GTIOR |=  0b01001;          // GTIOA[4:0] = 01001b - Initial output is low; Low Output at GTCCRA compare match; HIGH at end
  *GPT167_GTIOR |=  0b00110;          // GTIOA[4:0] = 01001b - Initial output is low; High Output at GTCCRA compare match; LOW at end
  *GPT167_GTIOR |= 0x00000100;        // Set OAE bit 
  *PFS_P304PFS   = (0b00011 << 24);   // Select PSEL[4:0] for GTIOC7A - See Table 19.10
  *PFS_P304PFS  |= (0x1 << 16);       // Port Mode Control - Used as an I/O port for peripheral function
  #endif
  #ifdef GPT7B_OUTPUT   // 
  //  *GPT167_GTIOR |= (0b01001 << 16);   // GTIOB[4:0] = 01001b - Initial output is low; Low Output at GTCCRB compare match; HIGH at end
  *GPT167_GTIOR |= (0b00110 << 16);   // GTIOB[4:0] = 01001b - Initial output is low; High Output at GTCCRB compare match; LOW at end
  *GPT167_GTIOR |= 0x01000000;        // Set OBE bit
  *PFS_P303PFS   = (0b00011 << 24);   // Select PSEL[4:0] for GTIOC7B - See Table 19.10
  *PFS_P303PFS  |= (0x1 << 16);       // Port Mode Control - Used as an I/O port for peripheral function
  #endif

  *GPT167_GTSTR  = 0b10000000;  // Start Timer 7 - Doesn't matter which timer is addressed
  *GPT167_GTCR   |= 0x1;        // Start Timer 7 with a PreScale of zero
  //  *GPT167_GTCLR  = 0b10000000;  // Clear Timer 7 - use to clear multipl times to align counts, not needed for single timer
  }


3 Likes

Wow! Thanks. FYI: I got a bit distracted... The EK-RA4M1 is delivered but still in the package. I've been busy with a true brick wall limiter (without (zener-)diodes that have a curve). And testing stable and accurate voltage references. I had it going on breadboard, but I think I've made a mistake in making it a schematic and PCB, because it is not working. I will upload your code tomorrow and then also get back to the hardware stuff. When done and fully tested I will show you the progress and perhaps send you a copy to test. For now... HIHAA!! :wink:

1 Like

@bastenhoor - no worries - we are all busy!

ONE important NOTE, please remember with the Minima to double-press the reset button to put the board into bootloader-mode each time - BEFORE doing a Code Flash update.

The IDE / programming-mode really doesn't like the fast 44.1 kHz timer interrupt running... :frowning:

Susan!!! It is really (and I mean REALLY) wonderful! I've been playing around with it and it's amazing! Thanks a million!

1 Like

I see you implemented untill the 9th harmonic. I updated the code to also include the last 3. the (#define) AUDIO_AMP_XX all have a value, and I notice that they get smaller, is this why the last harmonics are not implemented? How did you come up with these values and do you recommend values for the last harmonics?
It runs fine by the way with 24_BIT and all the harmonics!

1 Like

Pleased that you like it! :slight_smile:

Using the standard version (i.e. non inharmonic) I built the waveform up the hard way, trying different values to get the shape I wanted - in this case vaguely guitar like - recompiling each time. Then enable the inharmonicity.

Higher harmonics in general are lower than the fundament, with some exceptions, since the loudest frequency is the one we hear as the base tone.

The code as it stands is very much an example of the core DDS synthesis code method for calculating sines on the fly. I didn't implement above the 9th (10 sine sets in all) as I wanted to leave time in the interrupt for other things like envelopes and pitch modulation (with the AUDIO_ZERO slot).

And it is also prudent for the processor to have time outside the interrupt to run other stuff like the USB interface.

Next off I could add my serial command line interpreter and have all the parameters settable - probably write a bit of python for that - so everything can be changed dynamically.

There seems no issue with overclocking the RA4M1 if one wants a bit more calculating time.

I did make an application using OSC and Processing on an iPad where you could put in the rise and fall of each harmonic and show the resulting waveform.

It is from Chapter 14 of my book ( Arduino audio projects ) entitled "Spoonduino" This is what the display looked like:-

3 Likes