I am trying to replicate a white noise source project from September's Practical Electronics Magazine that used a Linear Shift Feedback register on a PIC12F675 to generate random white noise at one of the output pins.
The source code was provided, in .asm format. As I don't understand assembler, I'm struggling to convert the LSF function in BASIC (which I only partly understand anyway).
';generate random output (note: Using bit labelling 1-31 (rather than 0 to 30 for software), take 1 from Q value if counter labelling requiredrlfNOISE0,w'; move Q31 to ms bitmovwfSTORE'; store value for xoring with Q28'; place bit 31 to GPIO,0rlfSTORE,w'; get carry (bit 31)rlfGPIO,f'; carry to bit 0 GPIO'; get Q28swapfNOISE0,w'; Q28 to ms bit'; both store and w have required Q31 and Q28 in ms bitxorwfSTORE,f'; xor Q31 and Q28rlfSTORE,w'; move xored value to carry'; move shift register values along 1rlfNOISE3,f'; carry to ls byterlfNOISE2,f'; carry to next byterlfNOISE1,f'; carry to next byterlfNOISE0,f'; carry to ms byte
I am assuming that rlf is a rotate left command.
The first rlf seems to my eye to be rotating NOISE0 left, and storing the result in 'w'.
'w' then seems to be being copied to STORE.
STORE itself seems to be rotated left, with the value being stored in 'w'.
Then I get lost.
The output register GPIO appears to be being rotated left, with the result of it being sored in 'f'.
What would the equivalent of that be in GCB please? The port I was intending to use in my 12F1840 is PortA.2, could I achieve the same thing with:
rlfPORTA,f'; carry to bit 0 PORTA
The swapf command comment (Q28 to ms bit) implies that it is a bitwise command, again I don't see how that might be done. Similarly, the xorwf command implies that it is bitwise only. Are the locations of 'w' and 'f' bit values only?
Any guidance would be appreciated.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
The article simply deals with the 'electronics', with no mention of the code at all. I have the full Assembler:
;Noisesource;31bitshiftregisterrandomgeneratorXORQ31andQ28;QuotedfromXILINXapplicationXAPP052July7,1996(Version1.1);"Ann-bitLFSRcountercanhaveamaximumsequence;lengthof2n-1.Inthatcase,itgoesthroughallpossible;codepermutationsexceptone,whichwouldbealock-up;state.Amaximumlengthn-bitLFSRcounterconsistsofan;n-bitshiftregisterwithanXNORinthefeedbackpathfrom;thelastoutputQntothefirstinputD1.TheXNORmakes;thelock-upstatetheall-onesstate;anXORwouldmakeit;theall-zerosstate.FornormalXilinxapplications,all-ones;ismoreeasilyavoided,sinceìbydefaultîtheflip-flopswake;upintheall-zerosstate.Table3describestheoutputsthat;mustbeusedasinputsoftheXNOR.LFSRoutputsaretraditionally;labeled1throughn,with1beingthefirststageof;theshiftregister,andnbeingthelaststage.Thisisdifferent;fromtheconventional0to(n-1)notationforbinary;counters."ERRORLEVEL-302ERRORLEVEL-306listp=12F617;listdirectivetodefineprocessor#include<p12F617.inc>;processorspecificvariabledefinitions__CONFIG_CP_OFF&_BOR_OFF&_MCLRE_ON&_WDT_OFF&_PWRTE_ON&_INTRC_OSC_NOCLKOUT&_IOSCFS_8MHZ&_WRT_OFF;RAMNOISE0equH'20' ; ms byte of shift registerNOISE1equH'21' ; next byte of shift registerNOISE2equH'22' ; next byte of shift registerNOISE3equH'23' ; ls byte of shift registerSTOREequH'24' ; storage value;******************************************************************;startatmemory0org0;resetvectorMAIN;setoscillatorcalibrationbsfSTATUS,RP0;bank1movlw0x00;setoscillatortofactorycalibratedfrequencymovwfOSCTUNEbcfSTATUS,RP0;setinputs/outputsmovlwB'00000000'movwfGPIO;portslowmovlwB'00000111' ; comparators offmovwfCMCON0bsfSTATUS,RP0;selectmemorybank1movlwB'00000000' ; WPUmovwfWPUmovlwB'00000000' ; outputs/inputs set movwfTRISIO;portdatadirectionregistermovlwB'01000101' ; settings movwfOPTION_REGbcfSTATUS,RP0;selectmemorybank0;initialstates;preloadshiftregistersmovlwH'11'movwfNOISE0movlwH'8A'movwfNOISE1movlwH'9F'movwfNOISE2movlwH'01'movwfNOISE3RND;OutputatGPIO,0only;;generaterandomoutput(note:Usingbitlabelling1-31(ratherthan0to30forsoftware),take1fromQvalueifcounterlabellingrequiredrlfNOISE0,w;moveQ31tomsbitmovwfSTORE;storevalueforxoringwithQ28;placebit31toGPIO,0rlfSTORE,w;getcarry(bit31)rlfGPIO,f;carrytobit0GPIO;getQ28swapfNOISE0,w;Q28tomsbit;bothstoreandwhaverequiredQ31andQ28inmsbitxorwfSTORE,f;xorQ31andQ28rlfSTORE,w;movexoredvaluetocarry;moveshiftregistervaluesalong1rlfNOISE3,f;carrytolsbyterlfNOISE2,f;carrytonextbyterlfNOISE1,f;carrytonextbyterlfNOISE0,f;carrytomsbytegotoRND;total13clockcycles(6.5us)perhalffrequencygeneration;2tothepowerof31-1results=2,147,483,647;clockis2MHzso13cyclesis153.8451kHzgeneratingmaxfrequencyof76.923kHz;minimumfrequencyis76.923kHz/2,147,483,647=35.83uHz;sequencerepeatsafter13usx2,147,483,647=27,917,280sor7.75hoursend
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have something working but I can't be certain I have it close to the original, never mind right!
#Chip12F1840,2DimNOISE0AsByteDimNOISE1AsByteDimNOISE2AsByteDimNOISE3AsByteDimSTOREAsByteDimWFAsBitDimFFAsBitLetNOISE0=0x11LetNOISE1=0x8ALetNOISE2=0x9FLetNOISE3=0x01DoLetPortA.2=WFLetWF=Noise3.3XORNoise3.6'Bits 31 and 28LetFF=Noise3.0RotateNoise3LeftLetNoise3.7=WFLetWF=Noise2.0RotateNoise2LeftLetNoise2.7=FFLetFF=Noise1.0RotateNoise1LeftLetNoise1.7=WFLetWF=Noise0.0RotateNoise0LeftLetNoise0.7=FFLoop
Last edit: mkstevo 2019-10-03
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
; PE-Sep19-Noise.gcb; Noise source; 31 bit shift register random generator XOR Q31 and Q28
#chip12f675,8DimNoiseasLong' Create a 32bit shift registerNoise=Random' Randomise inital state (anything but zero)doC=Noise.27XORNoise.30' Test and set Carry flagRotateNoiseLeft' Rotate all 32 bitsGPIO.0=Noise.30' Output bit 31loop
It compiles and the ASM generated looks good but I have not yet built the hardware.
Give it a try on your device.
Cheers
Chris
EDIT: With a speaker attached it is generating White Noise :>)
Last edit: Chris Roper 2019-10-04
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have just updated the code having read the original article.
I see he has indexed from 1 not zero and the final stage is 7 bit not 8 bit.
As a result we need to XOR Noise.27 and Noise.30 wich in the article are referred to as Q28 and Q31.
I am not sure if there are any long term implications for 32 bits over 31 bits but the new code now fits his original algorithm.
Cheers
Chris
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Here is the complete program, should anyone be interested:
#Chip12F1840,2'Inspired by the Practical Electronics White Noise project, September 2019'White Noise source'Using a 31 bit shift register random generator XOR Q31 and Q28'Most of this work was done by Chris Roper'of the GCB forum for which I am most grateful.DimNoiseAsLong' Create a 32bit shift registerLetNoise=Random' Seed the LSFRDimLSAsBit'This allows us to the port on, or off. Without it the port goes'momentarily low in each cycle, even if it is intended to stay high'You end up with this:'____|‾|‾|‾|____|‾|‾|____'Instead of this:'____|‾‾‾‾‾|____|‾‾‾|____Do'This line causes an error:'Error: GCASM: Symbol 3.0 has not been defined'Let C = Noise.27 XOR Noise.30 ' Test and set Carry flag'Replaced with this If...ThenIfNoise.27<>Noise.30ThenLetC=1ElseLetC=0EndIfRotateNoiseLeft' Rotate all 32 bitsIfNoise.31<>LSThenLetLS=Noise.31LetPortA.2=LS' Output bit 31EndIfLoop
I found that the line:
LetC=Noise.28XORNoise.31' Test and set Carry flag
Caused an error when compiling for the 12F1840:
Error: GCASM: Symbol 3.0 has not been defined
I also found that direct XOR comparisons on Noise.28 and Noise.31 always equated to 0 (zero).
Using the If...Then statement cured that error.
Another anomaly was seen on the oscilloscope when observing the output. Directly setting the output port to the value of a variable seemed to cause it to momentarily dip to zero even if it was 'changing' from 1 (one) to 1 (one). This is why PortA.2 is only 'changed' when the value actually changes.
Last edit: mkstevo 2019-10-04
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
@Steve. What error? I just tried this code... Send me your code that fails, alone with the ASM.
Thank you.
#Chip12F1840, 2'Inspired by the Practical Electronics White Noise project, September 2019'White Noise source'Using a 31 bit shift register random generator XOR Q31 and Q28'Most of this work was done by Chris Roper'of the GCB forum for which I am most grateful.DimNoiseAsLong' Create a 32bit shift registerLetNoise=Random' Seed the LSFRDimLSAsBit'This allows us to the port on, or off. Without it the port goes'momentarily low in each cycle, even if it is intended to stay high'You end up with this:'____|‾|‾|‾|____|‾|‾|____'Instead of this:'____|‾‾‾‾‾|____|‾‾‾|____DoLetC=Noise.27XORNoise.30' Test and set Carry flagRotateNoiseLeft' Rotate all 32 bitsIfNoise.31<>LSThenLetLS=Noise.31LetPortA.2=LS' Output bit 31EndIfLoop
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
You are the only one getting that error, nether Even nor I can reproduce it.
here is my compiler output:
10:15:21G+Stoolstartedwithparameter'hex'->processingC:\GCB@Syn\G+Stools\makeHEX.batSource-File=C:\GCB@Syn\GreatCowBasic\Working\test.gcbTarget-File=C:\GCB@Syn\GreatCowBasic\Working\test.hexCompilerVersion(YYYY-MM-DD):0.98.<<>>2019-05-14(Windows32bit)ProgramMemory:108/4096 words (2.64%) RAM: 15/256bytes(5.86%)Chip:12F1840Duration:3.6Seconds.
What version are you running?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I was at work. I'll have to check the version, I had assumed it was a fairly recent version. I will check if I get this error at home.
My compiler here and at work will be one of the macOS versions which could be the reason you are not seeing the error? I'm certain mine here is the very latest, the one at work could be one version back from the latest, I can't be certain.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I did wonder if that would be an issue.
Your workaround is good but it introduces two XOR’s over one and additional branching code.
It does eliminate the glitch though at the cost of output frequency.
I don't know why you are seeing a compiler error, however.
I am unable to reproduce your error even on the 12F1840 device.
Your Code is looking good though and should be useful to others too.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
This version uses the above to solve the output Glitch and improve portability:
; PE-Sep19-Noise.gcb; Noise source; 31 bit shift register random generator XOR Q31 and Q28
#chip12f675,8
#defineNoisePinGPIO.0
#optionvolatileNoisePinDimNoiseasLong' Create a 32bit shift registerNoise=Random' Randomise inital state (anything but zero)doC=Noise.27XORNoise.30' Test and set Carry flagRotateNoiseLeft' Rotate all 32 bitsNoisePin=Noise.30' Output 31st bitloop
It now gives a main loop of 20 Instructions at 8Mhz, slightly more than the original, for a sampling rate of 100kHz, vs the original 153.846kHz, that is a frequency distribution of 50kHz which still covers the entire audio spectrum of 20Hz to 20kHz and the repeat sequence remains approximately 8 hours.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I'll give the "volatile" option a try when I'm next at the oscilloscope which may not be until next week now.
Any combination I tried using XOR always gave a result of 0 (zero) into the C (carry) register, filling the shift register with zeros. My <> comparison always worked? It could be being altered at a lower level by the serial LCD code I had which was outputting the 32 bits onto the LCD to see if it was working, which it wasn't. Perhaps as I passed "noise.30" and "noise.27" to the HSerPrint routine, they became corrupted, although they don't seem to have been when I use my If <> Then comparison. Odd.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I was correct, I am one version behind at work.
Great Cow BASIC (0.98.04 2018-10-20 (Darwin 64 bit))
I will update now.
Updated to:
Great Cow BASIC (0.98.06 2019-06-12 (Darwin 64 bit))
Program now compiles without errors at work.
I think I had updated previously, but had selected the 'All Users' install directory whilst my programs and scripts were located in my '~User' directory. I'll get that changed.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I am trying to replicate a white noise source project from September's Practical Electronics Magazine that used a Linear Shift Feedback register on a PIC12F675 to generate random white noise at one of the output pins.
The source code was provided, in .asm format. As I don't understand assembler, I'm struggling to convert the LSF function in BASIC (which I only partly understand anyway).
I am assuming that rlf is a rotate left command.
The first rlf seems to my eye to be rotating NOISE0 left, and storing the result in 'w'.
'w' then seems to be being copied to STORE.
STORE itself seems to be rotated left, with the value being stored in 'w'.
Then I get lost.
The output register GPIO appears to be being rotated left, with the result of it being sored in 'f'.
What would the equivalent of that be in GCB please? The port I was intending to use in my 12F1840 is PortA.2, could I achieve the same thing with:
The swapf command comment (Q28 to ms bit) implies that it is a bitwise command, again I don't see how that might be done. Similarly, the xorwf command implies that it is bitwise only. Are the locations of 'w' and 'f' bit values only?
Any guidance would be appreciated.
Post the article. Some genius will sort.
The article simply deals with the 'electronics', with no mention of the code at all. I have the full Assembler:
I have something working but I can't be certain I have it close to the original, never mind right!
Last edit: mkstevo 2019-10-03
This should do it:
It compiles and the ASM generated looks good but I have not yet built the hardware.
Give it a try on your device.
Cheers
Chris
EDIT: With a speaker attached it is generating White Noise :>)
Last edit: Chris Roper 2019-10-04
Oh wow!
That is so elegant and simple.
I hadn't realised you could rotate a Long variable.
Many thanks. Yours is far superior to what I was attempting to do.
Thanks.
I have just updated the code having read the original article.
I see he has indexed from 1 not zero and the final stage is 7 bit not 8 bit.
As a result we need to XOR Noise.27 and Noise.30 wich in the article are referred to as Q28 and Q31.
I am not sure if there are any long term implications for 32 bits over 31 bits but the new code now fits his original algorithm.
Cheers
Chris
And, it works on an 18f45k80.
Portable code rules!!
Here is the complete program, should anyone be interested:
I found that the line:
Caused an error when compiling for the 12F1840:
Error: GCASM: Symbol 3.0 has not been defined
I also found that direct XOR comparisons on Noise.28 and Noise.31 always equated to 0 (zero).
Using the If...Then statement cured that error.
Another anomaly was seen on the oscilloscope when observing the output. Directly setting the output port to the value of a variable seemed to cause it to momentarily dip to zero even if it was 'changing' from 1 (one) to 1 (one). This is why PortA.2 is only 'changed' when the value actually changes.
Last edit: mkstevo 2019-10-04
@Steve. What error? I just tried this code... Send me your code that fails, alone with the ASM.
Thank you.
The code failed to compile at all.
Let C = Noise.28 XOR Noise.31 ' Test and set Carry flag
Caused an error when compiling for the 12F1840:
Error: GCASM: Symbol 3.0 has not been defined
You are the only one getting that error, nether Even nor I can reproduce it.
here is my compiler output:
What version are you running?
I was at work. I'll have to check the version, I had assumed it was a fairly recent version. I will check if I get this error at home.
My compiler here and at work will be one of the macOS versions which could be the reason you are not seeing the error? I'm certain mine here is the very latest, the one at work could be one version back from the latest, I can't be certain.
I cannot reproduce the error. So, have a check.
The dip you were seeing is caused by this in the compiler output:
I did wonder if that would be an issue.
Your workaround is good but it introduces two XOR’s over one and additional branching code.
It does eliminate the glitch though at the cost of output frequency.
I don't know why you are seeing a compiler error, however.
I am unable to reproduce your error even on the 12F1840 device.
Your Code is looking good though and should be useful to others too.
I think you can stop the glitch. See if this works.
#option volatile bit
So, it would be
#option volatile GPIO.0
This version uses the above to solve the output Glitch and improve portability:
It now gives a main loop of 20 Instructions at 8Mhz, slightly more than the original, for a sampling rate of 100kHz, vs the original 153.846kHz, that is a frequency distribution of 50kHz which still covers the entire audio spectrum of 20Hz to 20kHz and the repeat sequence remains approximately 8 hours.
I'll give the "volatile" option a try when I'm next at the oscilloscope which may not be until next week now.
Any combination I tried using XOR always gave a result of 0 (zero) into the C (carry) register, filling the shift register with zeros. My <> comparison always worked? It could be being altered at a lower level by the serial LCD code I had which was outputting the 32 bits onto the LCD to see if it was working, which it wasn't. Perhaps as I passed "noise.30" and "noise.27" to the HSerPrint routine, they became corrupted, although they don't seem to have been when I use my If <> Then comparison. Odd.
The aded compiler directive:
has cured the apparent glitches at least as far as my super cheap Chinese USB 'scope shows. Thanks for that suggestion.
Here at home, the line:
compiles normally, and the XOR does not seem to be filling the shift register with zeros.
I have the compiler version:
Great Cow BASIC (0.98.05 2019-04-20 (Darwin 64 bit))
I will have to see what version I have at work next week.
Last edit: mkstevo 2019-10-06
Oh my. Please update Great Cow BASIC. We are many releases greater than that version.
My guess. Old version in use.
Perhaps just one release behind ... the current version is 0.98.06 (vs 0.98.05) unless I'm missing something?
I am the dim one. I read the version as 0.95.05!!!! Silly
I was correct, I am one version behind at work.
Great Cow BASIC (0.98.04 2018-10-20 (Darwin 64 bit))
I will update now.
Updated to:
Great Cow BASIC (0.98.06 2019-06-12 (Darwin 64 bit))
Program now compiles without errors at work.
I think I had updated previously, but had selected the 'All Users' install directory whilst my programs and scripts were located in my '~User' directory. I'll get that changed.