CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

How to use the NCO module- demo code
Goto page Previous  1, 2
 
Post new topic   Reply to topic    CCS Forum Index -> Code Library
View previous topic :: View next topic  
Author Message
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Thu Jul 16, 2015 1:12 am     Reply with quote

OK, then here we are without interrupts:
Code:
#include <10F322.h>
#use delay(internal=16000000)
#use FIXED_IO( A_outputs=PIN_A2,PIN_A0 )

#define LATA 0x07
#define NCO1ACCL 0x27
#define NCO1ACCH 0x28
#define NCO1ACCU 0x29
#define NCO1INCH 0x2B
#define NCO1INCL 0x2A
#define PIR1 0x0C
#BIT NCO1IF = PIR1.4

void main()
{

SETUP_ADC(ADC_OFF);
SETUP_NCO(NCO_ENABLED|NCO_OUTPUT|NCO_ACTIVE_LOW|NCO_PULSE_FREQ_MODE|NCO_PULSE_WIDTH_1|NCO_CLOCK_HFINOSC, 736);

while(TRUE){
if (NCO1IF){
//OUTPUT_TOGGLE(PIN_A0);
#asm
   MOVLW 0x01
   XORWF LATA, F
#endasm
if (input(PIN_A0)){
//   set_nco_inc_value(736);
#asm
   MOVLW 16
   MOVWF NCO1INCH
   MOVLW 105
   MOVWF NCO1INCL
#endasm
}
else{
//   set_nco_inc_value(471);
#asm
   MOVLW 1
   MOVWF NCO1INCH
   MOVLW 6
   MOVWF NCO1INCL
#endasm
}
// set_nco_accumulator(0);
#asm
   CLRF NCO1ACCL
   CLRF NCO1ACCH
   CLRF NCO1ACCU
#endasm
//clear_interrupt(INT_NCO1);
#asm
   BCF PIR1, 0x4
#endasm
}
}
}


The delay introduced by testing the NCO1IF and loading new numbers in NCO increment registers is around 4.3-4.4us measured on scope.
With the code above I expect 20us on and 255us off and I get 19.6-20.0us on and 254.0-254.4us off.
The jitter is 0.4us coming directly from internal RC oscillator.
But important is that the code is reduced to 6% RAM and 9% ROM, finally at the size comparable with XC8.

Then I tried to get rid of the ASM code and I found that only the loading of NCO increment registers is working right “set_nco_inc_value()”, so I replaced only that with ASM code and then the program worked fine. The delay introduced is around 5.1us. The code is 6% RAM and 10% ROM.
The precision/jitter is the same 0.4us.
The code below is expected to produce 20us on and 255us off. I measured 19.5-19.9us and 254.9-255.3us.
Code:

#include <10F322.h>
#use delay(internal=16000000)
#use FIXED_IO( A_outputs=PIN_A2,PIN_A0 )

#define LATA 0x07
#define NCO1ACCL 0x27
#define NCO1ACCH 0x28
#define NCO1ACCU 0x29
#define NCO1INCH 0x2B
#define NCO1INCL 0x2A
#define PIR1 0x0C
#BIT NCO1IF = PIR1.4


void main()
{

SETUP_ADC(ADC_OFF);
SETUP_NCO(NCO_ENABLED|NCO_OUTPUT|NCO_ACTIVE_LOW|NCO_PULSE_FREQ_MODE|NCO_PULSE_WIDTH_1|NCO_CLOCK_HFINOSC, 3277);

while(TRUE){
if (NCO1IF){
OUTPUT_TOGGLE(PIN_A0);

if (input(PIN_A0)){
#asm
   MOVLW 17
   MOVWF NCO1INCH
   MOVLW 46
   MOVWF NCO1INCL
#endasm
}
else{
#asm
   MOVLW 1
   MOVWF NCO1INCH
   MOVLW 6
   MOVWF NCO1INCL
#endasm

}
set_nco_accumulator(0);
NCO1IF=0;
}
}
}
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Thu Jul 16, 2015 6:09 am     Reply with quote

And next step was analyzing the long width for “on” and “off” with better precision.
For example when I try 10ms then the jitter error + the error delay generated by code ads itself. But the main error noticed comes from increment. We have a fixed space of 1048575 to fill with a fixed increment. At high delays, the increment value multiplied by needed times does not match exactly the accumulator of the NCO.
Therefore, instead of working with NCO overflow flag, no matter if is NCO interrupt or polling NCO overflow flag in a loop, I found better next solution:
- Increment only with 1 pulse the NCO accumulator.
- Check the value of the NCO accumulator in a loop.
The precision obtained is 20us jitter at 10ms width “on” or “off”.
Here is the XC8 working code:
Code:
#include <xc.h>
#define _XTAL_FREQ 16000000

__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF & WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);

void main(){

OSCCON=0b01110000;
TRISA=0b00001010;
LATA=0b00000000;
ANSELA=0b00000000;
ADCON=0b00100000;
OPTION_REG=0b00000000;
WPUA=0b00000000;
INTCON=0b00000000;
PIE1=0b00000000;
PIR1=0b00000000;

NCO1INCH = 0;
NCO1INCL = 1;

NCO1CLK = 0b0000010;
NCO1CON = 0b11100001;

while(1){
 if (LATA0==1 & NCO1ACC>=160000){
    LATA0=0;
    NCO1ACC=0;
    }
 if (LATA0==0 & NCO1ACC>=160000){
    LATA0=1;
    NCO1ACC=0;
    }
}
}

The CCS code I could not make it run. First of all I noticed in “10F322.h” file the function “_bif int16 get_nco_accumulator(void);”, but the NCO accumulator is 20 bits, so it suppose to be int32 function. I think is the same error as for “_bif void set_nco_accumulator(int16 value);” which I tried to use to reset the NCO accumulator.
The code does not work with the function “get_nco_accumulator()”

Here is the code that I tried, but still not functional:
Code:
#include <10F322.h>
#use delay(internal=16000000)
#use FIXED_IO( A_outputs=PIN_A2,PIN_A0 )

#define NCO1ACCL 0x27
#define NCO1ACCH 0x28
#define NCO1ACCU 0x29

void main()
{

SETUP_ADC(ADC_OFF);
SETUP_NCO(NCO_ENABLED|NCO_OUTPUT|NCO_ACTIVE_LOW|NCO_PULSE_FREQ_MODE|NCO_PULSE_WIDTH_1|NCO_CLOCK_HFINOSC, 1);

while(TRUE){
if (input(PIN_A0)){
   if ((NCO1ACCH>=15)&(NCO1ACCL>=160)){
      output_low(PIN_A0);
      #asm
         CLRF NCO1ACCL
         CLRF NCO1ACCH
         CLRF NCO1ACCU
      #endasm
   }
}
if (!input(PIN_A0)){
   if ((NCO1ACCH>=15)&(NCO1ACCL>=160)){
      output_high(PIN_A0);
      #asm
         CLRF NCO1ACCL
         CLRF NCO1ACCH
         CLRF NCO1ACCU
      #endasm
   }
}
}
}
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Thu Jul 16, 2015 6:34 am     Reply with quote

Sometimes, when I test I use the real chip, and other times simulators or debuggers.
As simulators I tried mostly MPLABX and Proteus.
PIC10 Simulator does not work with PIC10F322:
http://www.oshonsoft.com/pic10.html
The same with Real PIC Simulator:
http://digitalelectrosoft.com/pic-simulator

For the present tests I tried besides MPLABX, the Proteus 8.2 SP2 which has a small “bug”, or better say a missed update.

PIC10F322 has updated the datasheet regarding the NCOxCLK: NCOx INPUT CLOCK CONTROL REGISTER.
The new devices and the new datasheet 2011-2014, page 125 bottom, have:
https://drive.google.com/file/d/0BwXmKaSw75eKU2hQRGdRTUFBemc/view
bit 1-0 NxCKS<1:0>: NCOx Clock Source Select bits
11 = LC1OUT
10 = HFINTOSC (16 MHz)
01 = FOSC
00 = NCO1CLK pin

The old datasheet 2011, page 135 bottom, indicates a different order:
https://drive.google.com/file/d/0BwXmKaSw75eKaVNySl9FVHdKWVU/view
NxCKS<1:0>: NCOx Clock Source Select bits
11 = NCO1CLK
10 = LC1OUT
01 = FOSC
00 = HFINTOSC (16 MHz)

Proteus 8.2 SP2 works with the info from old datasheet 2011.

Any suggestions how to debug the not functional last CCS code above?
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Jul 16, 2015 8:08 am     Reply with quote

it looks to me like you did solve it with your post of
Thu Jul 16, 2015 1:12 am

Any info produced by Proteus - is of no help really.

But i would not be surprised to find that the CCS code for the NCO on
your 10F... part is sketchy. This is not so much CCS fault as the
fact that in the 20us/250us mode , jamming the control register pair as you do is not performed in a vacuum.

In the most successful version you coded here is what is happening:

The accumulator is already "counting up" for every i-cycle that occurs in your code stream. Your test for which value to load into the double buffer compare register presently checks for the LONGER time cycle first.

I think You should reverse the order and test for the ELSE case first .

When you zero the accumulator at the end of the test/load code you are "off the timing mark" by the time it has taken to do the tests.

Slightly less jitter will occur if you test for !input(pin) case FIRST ..

But all in all - a bigger problem is still there.

the NCO was designed i think to generate steady frequencies without the jamming you do on every cycle of the counter .

I think you might get better performance yet if you
clear the flag on every detection BUT if the recorded state of the INPUT control pin has not changed - then DO NOT re-jam the counter on every pass.

if the control pin has not changed - just clear the flag and exit.
Only set the alternative register value if the control pin has changed state .

That ought to further cut down on jitter.

Unless i am missing something about your schematic ( which you never posted) i can't suggest anything else.
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Fri Jul 17, 2015 4:58 am     Reply with quote

Thank you for the suggestions.
I do not think is a hardware jamming of the NCO as long as the XC8 code with 1 increment and the same poling of the accumulator works.
I find rather a problem of CCS when the code is compiled in assembly and when NCO functions are wrong declared in “10F322.h” as 16bits instead of 24bits, knowing that NCO accumulator is 20bits.
The INPUT control pin is in fact the same as OUTPUT control pin. I set it on or off.

I have no schematic. I use only a breadboard with PIC10F322, stabilized 5VDC and one DSO 350MHz.
To program I use ICD-U64 programmer inside the CCS IDE and PicKit 3 programmer with MPLABX.
It is just a test, not a real application.

I tested one more NCO function in XC8, which again is not working in CCS.
It is a microseconds delay function using NCO working in the range 20us-250us with a precision of +/-1us + oscillator jitter.
I increment the NCO slowly and I am looking at the NCO accumulator. It is more precisely than polling NCO overflow flag or using NCO interrupt, because NCO increment does not match always the NCO accumulator exactly.
I tried NCO1INCL also with 1, but the delay function cannot coop with such speeds and there is no signal generated. The NCO1INCL with 2 works, but is still too fast to get a good precision for the function in the range 20us-250us.
Code:
#include <xc.h>
#define _XTAL_FREQ 16000000

__CONFIG(FOSC_INTOSC & MCLRE_OFF & WDTE_OFF & LVP_OFF & CP_OFF & WRT_OFF & PWRTE_OFF & WRT_OFF & BOREN_ON & LPBOR_ON & BORV_LO);
void NCO_delay(unsigned short long dly);
void main(){

OSCCON=0b01110000;
TRISA=0b00001010;
LATA=0b00000000;
ANSELA=0b00000000;
ADCON=0b00100000;
OPTION_REG=0b00000000;
WPUA=0b00000000;
INTCON=0b00000000;
PIE1=0b00000000;
PIR1=0b00000000;

NCO1INCH = 0;
NCO1INCL = 3;

NCO1CLK = 0b00000010;
NCO1CON = 0b10000001;

while(1){
LATA0=0;
NCO_delay(11760);
LATA0=1;
NCO_delay(720);
}
}
//The number passed to the NCO_delay() function
//is calculated as (wanted delay in us-5)*48
// The 48 comes from 16MHz*NCO1INCL
//The "-5" is a compensation of the NCO_delay() function execution

void NCO_delay(unsigned short long dly){
    NCO1ACC=0;
    while(NCO1ACC<dly);
}


My intention was to test NCO and use it in 3 ways, based on the fact that its accumulator is 20 bits, is linear, has input clock 16MHz (62.5ns), so I said is a better precision:
- As replacement for Timer0 or Timer2 interrupt.
- As a precise signal generator for a limited number of signal periods.
- As a precise microseconds delay function.
I can do that now, but most of the tests are successful with XC8. For the time being I will not go further with CCS on this matter, but I will inform the CCS Technical support about NCO PIC10F322 found problems.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Jul 17, 2015 8:05 am     Reply with quote

Quote:
I tested one more NCO function in XC8, which again is not working in CCS.

Post your CCS compiler version. It's given at the top of the .LST file.
It's a 4-digit number like this: http://www.ccsinfo.com/devices.php?page=versioninfo
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Fri Jul 17, 2015 10:54 am     Reply with quote

CCS C complier version 5.048
Here is the LST file:
https://drive.google.com/file/d/0BwXmKaSw75eKMjc4SUoxd1prbmM/view?pli=1
viki2000



Joined: 08 May 2013
Posts: 233

View user's profile Send private message

PostPosted: Fri Jul 17, 2015 1:37 pm     Reply with quote

Here is the official answer just received from technical support:
Quote:
The function set_nco_accumulator() will accept a 32 bit variable and the get_nco_accumulator() function will return a 32 bit variable. It's just an error with the function prototype, I have correct the prototype which will be corrected in the next compiler release we do.

I also found an issue with the set_nco_inc_value() and set_nco_accumulator() functions writing to incorrect registers. I have updated the compiler and the fix will be available in the next compiler release.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> Code Library All times are GMT - 6 Hours
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group