Positron8 - NCO peripheral outputting a 10MHz square wave

Started by top204, Oct 31, 2024, 03:42 PM

Previous topic - Next topic

top204

A post I created on the forum concerning the NCO (Numerically Controlled Oscillator) peripheral, triggered my curiosity. So I wrote a program on a more common PIC device that has the NCO peripheral on-board. Namely the PIC16F18854 device, which is an enhanced 14-bit core type.

It also meant I could simulate the program to make sure I understood the peripheral enough to make it work for demonstrations. The code listing is below that will generate a 10MHz square wave waveform from pin PORTC.0, on a device running at only 32MHz using an external 8MHz crystal as its oscillator:

'
'   /\\\\\\\\\
'  /\\\///////\\\
'  \/\\\     \/\\\                                                 /\\\          /\\\
'   \/\\\\\\\\\\\/        /\\\\\     /\\\\\\\\\\     /\\\\\\\\   /\\\\\\\\\\\  /\\\\\\\\\\\  /\\\\\\\\\
'    \/\\\//////\\\      /\\\///\\\  \/\\\//////    /\\\/////\\\ \////\\\////  \////\\\////  \////////\\\
'     \/\\\    \//\\\    /\\\  \//\\\ \/\\\\\\\\\\  /\\\\\\\\\\\     \/\\\         \/\\\        /\\\\\\\\\\
'      \/\\\     \//\\\  \//\\\  /\\\  \////////\\\ \//\\///////      \/\\\ /\\     \/\\\ /\\   /\\\/////\\\
'       \/\\\      \//\\\  \///\\\\\/    /\\\\\\\\\\  \//\\\\\\\\\\    \//\\\\\      \//\\\\\   \//\\\\\\\\/\\
'        \///        \///     \/////     \//////////    \//////////      \/////        \/////     \////////\//
'                                  Let's find out together what makes a PIC Tick!
'
' Demonstration of the NCO (Numerically Controlled Oscillator) peripheral generating a 10MHz square wave waveform.
' Using a PIC16F18854 device running at 32MHz using an 8MHz crystal, and the output waveform is on pin PORTC.0.
'
' Written by Les Johnson for the Positron8 BASIC compiler.
' https://sites.google.com/view/rosetta-tech/home
'
    Device = 16F18854                               ' Tell the compiler what device to compile for
    Declare Xtal = 32                               ' Tell the compiler what frequency the device is operating at (in MHz)
    Declare Create_Coff = True                      ' Create a COF file for debugging
'
' Create NCO meta-macros
'
$define NCO_Enable() NCO1CONbits_N1EN = 1           ' Enable the NCO peripheral
$define NCO_Disable() NCO1CONbits_N1EN = 0          ' Disable the NCO peripheral
'
' Create any global variables here...
'

'---------------------------------------------------------------------------------------------
' The main program starts here
' Initialise the NCO peripheral to output a 10MHz waveform on pin PORTC.0
'
Main:
    Setup()                                         ' Setup the program and any peripherals
    Do
    '
    ' Main program code here
    '
    Loop

'---------------------------------------------------------------------------------------------
' Setup the program and any peripherals
' Input     : None
' Output    : None
' Notes     : None
'
Proc Setup()
    Osc_Init()                                      ' Initialise the oscillator for 32MHz operation
    PinOutput PORTC.0                               ' Make the NCO pin an output
    PPS_Unlock()                                    ' Unlock the PPS setup, just to be sure it will change
    RC0PPS = PPS_Fn_NCO                             ' Make pin PORTC.0 the output for the NCO peripheral
    NCO_Init()                                      ' Setup the NCO peripheral for 10MHz operation
EndProc

'---------------------------------------------------------------------------------------------
' Setup the NCO peripheral on a PIC16F18854 device
' Input     : None
' Output    : None
' Notes     : Setup for a 10MHz waveform when the device is operating at 32MHz
'
Proc NCO_Init()
    NCO1CON  = $00                                  ' NCO disabled. Polarity is active_lo. FDC mode
    NCO1CLK  = $00                                  ' Clock source is FOSC
    NCO1ACCU = $00
    NCO1ACCH = $00
    NCO1ACCL = $00
    NCO1INCU = $0A
    NCO1INCH = $00
    NCO1INCL = $00
    NCO_Enable()                                    ' Enable the NCO peripheral
EndProc

'---------------------------------------------------------------------------------------------
' Initialise the oscillator for 32MHz operation
' Input     : None
' Output    : None
' Notes     : For use with a PIC16F18854 device
'
Proc Osc_Init()
    OSCCON1 = %00100000                             ' External crystal with 4xPLL. NDIV is 1
    OSCCON3 = %00100000
    OSCEN   = %00100000
    OSCFRQ  = %00100110                             ' 32MHz
    OSCTUNE = %00100000
    DelayMS 100
EndProc

'---------------------------------------------------------------------------------------------
' Setup the config fuses for external 8MHz crystal with 4xPLL enabled on a PIC16F18854 device.
' Will operate the device at 32MHz.
'
    Config1 FEXTOSC_ECH,_                           ' External Oscillator above 8MHz
            RSTOSC_EXT4X,_                          ' EXTOSC with 4xPLL, with EXTOSC operating per FEXTOSC bits
            CLKOUTEN_OFF,_                          ' CLKOUT function is disabled
            CSWEN_ON,_                              ' Writing to NOSC and NDIV is allowed
            FCMEN_ON                                ' Fail-Safe Clock Monitor timer enabled

    Config2 MCLRE_ON,_                              ' MCLR pin is Master Clear function
            PWRTE_OFF,_                             ' Power-up Timer disabled
            LPBOREN_OFF,_                           ' Low-Power BOR disabled
            BOREN_ON,_                              ' Brown-out Reset Enabled. SBOREN bit is ignored
            BORV_LO,_                               ' Brown-out Reset Voltage (VBOR) set to 2.45V
            ZCD_OFF,_                               ' Zero-cross detect circuit is disabled at POR
            PPS1WAY_OFF,_                           ' The PPSLOCK bit can be repeatedly cleared and set
            STVREN_ON,_                             ' Stack Overflow or Underflow will cause a reset
            DEBUG_OFF                               ' Background Debugger disabled

    Config3 WDTCPS_WDTCPS_2,_                       ' WDT Period Divider ratio
            WDTE_OFF,_                              ' WDT Disabled. SWDTEN is ignored
            WDTCWS_WDTCWS_7,_                       ' WDT Window always open (100%)
            WDTCCS_SC                               ' WDT input clock Software Control

    Config4 WRT_OFF,_                               ' User NVM self-write protection off
            SCANE_AVAILABLE,_                       ' Scanner module is available for use
            LVP_OFF                                 ' High Voltage on MCLR/Vpp must be used for programming

    Config5 CP_OFF,_                                ' Program Memory code protection disabled
            CPD_OFF                                 ' Data EEPROM code protection disabled

The NCO peripheral seems to work well, and a screenshot of it working in a simulator is shown below, and a microchip technical note for the NCO operation is also attached below:

NCO_Screenshot.jpg