• 0

Generating a custom pattern with python interface longer than 1024 "bits".


Question

I'm trying to output a custom digital waveform that is a frequency modulated bit stream. The basic scheme is as follows:

1. Preamble: frequency starts out at 10KHz for 400 cycles

After

2. for a 1 bit, send 20 13KHz cycles, followed by 20 10KHz cycles

3. for a 0 bit, send 10 6KHz cycles, followed by 20 10KHz cycles

4. Postable: frequency runs at 10KHz for 400 Cycles.

I can generate the signal with python but I seem to be running into bitstream length issue. The moment the data gets over 1024 "bits" (actual bits, not the frequency modulated ones), the signal is not generated.  My code is below but it's modified to only send 1024 bits.

My second issue is that when this pattern works, it repeats. I would like it to run only once. I tried a few things found in forums but there's no documentation for the python interface.

 

from ctypes import *
from dwfconstants import *
import sys
import time

if sys.platform.startswith("win"):
    dwf = cdll.dwf
elif sys.platform.startswith("darwin"):
    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
    dwf = cdll.LoadLibrary("libdwf.so")

hdwf = c_int()

version = create_string_buffer(16)
dwf.FDwfGetVersion(version)
print("DWF Version: "+str(version.value))


print("Opening first device")
dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))

if hdwf.value == 0:
    print("failed to open device")
    szerr = create_string_buffer(512)
    dwf.FDwfGetLastErrorMsg(szerr)
    print(str(szerr.value))
    quit()

print("Configuring Digital Out")

hzSys = c_double()
dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))

data_one_wave   = [1,1,1,0,0,0]
data_zero_wave  = [1,1,1,1,1,1,0,0,0,0,0,0]
data_amble_wave = [1,1,1,1,0,0,0,0]

data_preamble = data_amble_wave * 4
data_zero_bit = (data_zero_wave * 2) + (data_amble_wave * 3)
data_one_bit = (data_one_wave * 4) + (data_amble_wave * 3)
data_postamble = data_preamble

# Message with short preamble, 07, 1000, 07, short postamble
data_to_send = data_preamble \
     + data_zero_bit + data_zero_bit + data_zero_bit + data_one_bit \
     \
     + data_zero_bit + data_zero_bit + data_one_bit  + data_one_bit  \
     + data_one_bit  + data_one_bit  + data_one_bit  + data_zero_bit \
     + data_one_bit  + data_zero_bit + data_zero_bit + data_zero_bit \
     \
     + data_zero_bit + data_zero_bit + data_zero_bit + data_one_bit \
     + data_postamble
time_to_sleep = 5

# Message with just preamble - 10KHz
# data_to_send = data_preamble
# time_to_sleep = 3

print("Sending " + str(len(data_to_send)) + " bit of data")

data_py = data_to_send

# how many bytes we need to fit this many bits, (+7)/8
rgbdata=(c_ubyte*((len(data_py)+7)>>3))(0) 

# array to bits in byte array
for i in range(len(data_py)):
    if data_py[i] != 0:
        rgbdata[i>>3] |= 1<<(i&7)
        
        
pin=0
# generate pattern
dwf.FDwfDigitalOutEnableSet(hdwf, c_int(pin), c_int(1))
dwf.FDwfDigitalOutIdleSet(hdwf, c_int(0), DwfDigitalOutIdleHigh)
dwf.FDwfDigitalOutTypeSet(hdwf, c_int(pin), DwfDigitalOutTypeCustom)
# 80kHz sample rate
dwf.FDwfDigitalOutDividerSet(hdwf, c_int(pin), c_int(int(hzSys.value/80e3))) # set sample rate
dwf.FDwfDigitalOutDataSet(hdwf, c_int(pin), byref(rgbdata), c_int(len(data_py)))
# This doesn't seem to work.
dwf.FDwfDigitalOutRepeatSet(hdwf, c_int(1)) # repeat once

print("Generating pattern...")
dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))

time.sleep(time_to_sleep)

dwf.FDwfDigitalOutReset(hdwf)
dwf.FDwfDeviceCloseAll()

If I bump any of the "multipliers on the data_preamble or similar variables to make a longer stream, the output doesn't get generated.

I'm basically using a "common denominator" clock that can handle all 3 frequencies and mapping the 1s and 0s as needed. If there's a better way to do this, I'm all ears. The only requirement is that the control of the number of cycles must be exact.

Can you help?

 

Edited by rost0031
Had to fix a comment in code
Link to post
Share on other sites

6 answers to this question

Recommended Posts

  • 0

Hi @rost0031

See the earlier inserted post.

Instead: dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
use: dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf))
This way you can use 16Ki bits with:
dwf.FDwfDigitalOutDataSet(hdwf, c_int(pin), byref(rgbdata), c_int(len(data_py)))

To limit the run length use:
dwf.FDwfDigitalOutRunSet(hdwf, c_double(len(data_py)/80e3))
like it is in the DigitalOut_CustomBus.py example

Link to post
Share on other sites
  • 0

Ok, thank you. I got the buffer size to accommodate my entire signal. But I can't get the output stream to stop using your suggestion. When I try it with the sleep() option, it repeats as expected. I can tweak the sleep value to get it to cut but it's not exact. When I try it without the sleep with your suggestion, it outputs 3 pulses or so and stops.  I'm including my code below.

from ctypes import *
from dwfconstants import *
import sys
import time

if sys.platform.startswith("win"):
    dwf = cdll.dwf
elif sys.platform.startswith("darwin"):
    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
    dwf = cdll.LoadLibrary("libdwf.so")

hdwf = c_int()

version = create_string_buffer(16)
dwf.FDwfGetVersion(version)
print("DWF Version: "+str(version.value))


print("Opening first device")
# Opens the device with a somehow magically larger buffer  
dwf.FDwfDeviceConfigOpen(c_int(-1), 3, byref(hdwf))

if hdwf.value == 0:
    print("failed to open device")
    szerr = create_string_buffer(512)
    dwf.FDwfGetLastErrorMsg(szerr)
    print(str(szerr.value))
    quit()

print("Configuring Digital Out")

hzSys = c_double()
dwf.FDwfDigitalOutInternalClockInfo(hdwf, byref(hzSys))

data_one_wave   = [1,1,1,0,0,0]
data_zero_wave  = [1,1,1,1,1,1,0,0,0,0,0,0]
data_amble_wave = [1,1,1,1,0,0,0,0]

data_preamble = data_amble_wave * 400
data_zero_bit = (data_zero_wave * 8) + (data_amble_wave * 13)
data_one_bit = (data_one_wave * 16) + (data_amble_wave * 13)
data_postamble = data_preamble

# Message with short preamble, 07, 1000, 07, short postamble
data_to_send = data_preamble \
     + data_zero_bit + data_one_bit + data_one_bit + data_one_bit \
     \
     + data_zero_bit + data_zero_bit + data_one_bit  + data_one_bit  \
     + data_one_bit  + data_one_bit  + data_one_bit  + data_zero_bit \
     + data_one_bit  + data_zero_bit + data_zero_bit + data_zero_bit \
     \
     + data_zero_bit + data_one_bit + data_one_bit + data_one_bit \
     + data_postamble
# time_to_sleep = .2
# time_to_sleep = 1

# Message with just preamble - 10KHz
# data_to_send = data_preamble
# time_to_sleep = 3

print("Sending " + str(len(data_to_send)) + " bit of data")

data_py = data_to_send

# how many bytes we need to fit this many bits, (+7)/8
rgbdata=(c_ubyte*((len(data_py)+7)>>3))(0) 

# array to bits in byte array
for i in range(len(data_py)):
    if data_py[i] != 0:
        rgbdata[i>>3] |= 1<<(i&7)
        
        
pin=0
# generate pattern
dwf.FDwfDigitalOutEnableSet(hdwf, c_int(pin), c_int(1))
dwf.FDwfDigitalOutIdleSet(hdwf, c_int(0), DwfDigitalOutIdleHigh)
dwf.FDwfDigitalOutTypeSet(hdwf, c_int(pin), DwfDigitalOutTypeCustom)
# 80kHz sample rate
dwf.FDwfDigitalOutDividerSet(hdwf, c_int(pin), c_int(int(hzSys.value/80e3))) # set sample rate
dwf.FDwfDigitalOutDataSet(hdwf, c_int(pin), byref(rgbdata), c_int(len(data_py)))

# THIS DOESN'T SEEM TO WORK
dwf.FDwfDigitalOutRunSet(hdwf, c_double(len(data_py)/80e3)) 
dwf.FDwfDigitalOutRepeatSet(hdwf, c_int(1)) # repeat once

print("Generating pattern...")
dwf.FDwfDigitalOutConfigure(hdwf, c_int(1))

dwf.FDwfDigitalOutReset(hdwf)
dwf.FDwfDeviceCloseAll()



 

Link to post
Share on other sites
  • 0

Ok, I just tried something and it seemed to kinda work. If I try your suggestion but with the sleep, it seems to work as long as the sleep is for longer than the pattern I want. The pattern comes out fully and stops at the end. I guess that works so I am happy with that.

Is there a reference manual for the Python (or the underlying C) API?  I would like to avoid bugging you with silly questions like this.

Once again, thank you for your help.

Edited by rost0031
Minor wording change
Link to post
Share on other sites
  • 0

Hi @rost0031

In you code the pattern is started and after about 1ms it is stopped by the reset function
dwf.FDwfDigitalOutConfigure(hdwf, c_int(1)) # pattern is started
dwf.FDwfDigitalOutReset(hdwf) # pattern is stopped

1. The easiest is to add a sleep between these two.

2. Or you can remove reset and before opening the device specify to continue to run on close. This way the device will continue to run after device close, script exit.
dwf.FDwfParamSet(DwfParamOnClose, c_int(0)) # 0 = run, 1 = stop, 2 = shutdown

3. Or you can make the script to wait the pattern run to be finished, adding after configure function:
while True:
    dwf.FDwfDigitalOutStatus(hdwf, byref(sts))
    if sts.value == stsDone.value :
        break

 

You can find all these in the manual and in the examples.

Edited by attila
Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now