It is a Sine Generator using DDS. The wave is generated using the second core. To achieve higher resolution in combination with higher frequency it adds 2 pwm signals with 6bits each. Both channels from pin15 (1.5k) and pin15 (100k) are connected to a 4.7nF filter capacitor.
See: http://www.openmusiclabs.com/learning/d ... index.html
setF(Frequency) sets the frequency. Zero to stop the second core.
Be aware that you have to edit the register address, if you want to use different pins!
EDIT: It turns out, that activity on core0 does influence frequency accuracy of this code running in core1. Frequency of 1kHz sinks to 974Hz. See next post for an improved version.
Enjoy!
Christof
Code: Select all
# DDS Sine Generator in second core by CWE
# Example using Double PWM
# http://www.openmusiclabs.com/learning/digital/pwm-dac/dual-pwm-circuits/index.html 100k and 1.5k + 4.7nF
import time, _thread, sys
from machine import Pin, PWM
import math
import uarray
# Construct PWM object, with LED on Pin(25).
pwmA = PWM(Pin(15, Pin.OUT)) # upper 6 bits
pwmB = PWM(Pin(14, Pin.OUT)) # low 6 bits
# Set the PWM frequency.
pwmFreq= int(125_000_000/64) # 6 bit
pwmA.freq(pwmFreq)
pwmB.freq(pwmFreq)
pwmA.duty_u16(31<<10)
pwmB.duty_u16(31<<10)
sineBufLen= 6249 #1kHz: 6249
sineBuf=uarray.array("H",range(0,sineBufLen))
for x in range(0,sineBufLen):
xr= x/sineBufLen*2*math.pi
sineBuf[x]= 2047+int(2047*math.sin(xr)) # 12 bit resolution
#print(sineBuf[x])
pwmA.duty_u16(0<<10)
pwmB.duty_u16(0<<10)
ddsCtrl = uarray.array('i',[
0x40050000 + 0x98, # 0 cc7
sineBufLen, # 4
1, # 8
int((1<<16)*1.0) # 12 1=run, step in half
])
@micropython.asm_thumb
def dds(r0, r1): # Buffer, ctrl-array
mov(r2,r0) # Buffer Start Address
ldr(r5, [r1,4]) # buffer length
ldr(r4, [r1,0]) # pwm counter compare register
ldr(r7, [r1,12]) # step index fine
mov(r3,0) # Buffer Index fine
label(nextVal)
lsr(r0,r3,16) # index coarse
lsl(r0,r0,1) # index coarse half words
add(r0,r0,r2)
ldrh(r0,[r0,0]) # read buffer regPoke(0x40050000 + 0x98, ((a>>6)<<16) + (a&63))
lsl(r6,r0,26) # get the lowest 6 bit
lsr(r0,r0,6) # shift bits right (upper)
lsl(r0,r0,16)
lsr(r6,r6,26) # lower 6 bits
add(r0,r0,r6)
str(r0,[r4,0])
#b(retu)
add(r3,r3,r7) # next buffer index fine
lsr(r0,r3,16)
cmp(r5,r0) # end not yet reached
bhi(nextVal)
lsl(r0,r5,16)
sub(r3,r3,r0)
mov(r0,r3)
ldr(r7, [r1,12]) # reload step index repeat?
cmp(r7,0)
bne(nextVal)
label(retu)
@micropython.asm_thumb
def regPeek(r0): # Address
mov(r1,r0)
ldr(r0,[r1,0])
@micropython.asm_thumb
def regPoke(r0, r1): # Address, Data
str(r1,[r0,0])
mov(r0,r1)
def regSet(adress, mask):
regPoke(adress, regPeek(adress) | mask)
def setF(f):
ddsCtrl[3]=int(f/1000*(1<<16))
#sineBuf[0]=1<<6
#print(dds(sineBuf, ddsCtrl))
_thread.start_new_thread(dds, (sineBuf, ddsCtrl))
try:
while True:
f=10
while f<25_000:
setF(f)
time.sleep(.2)
print(f, end=" ")
f=f*1.5849 #math.sqrt(10)
except KeyboardInterrupt:
ddsCtrl[3]=0
sys.exit()
"""
x=0
delta=10
while True:
x+= delta
if x>(sineBufLen-1):
x-=sineBufLen
a= sineBuf[x]
#pwmA.duty_u16( (a<<4) & (255<<8)) # upper 6 bit
#pwmB.duty_u16( (a<<10) & (255<<8)) # lower 6 bit
regPoke(0x40050000 + 0x98, ((a>>6)<<16) + (a&63))
#regPoke(0x40050000 + 0x98, ((a>>6)<<16))
"""