added dac driver support

master
Ondřej Hruška 6 years ago
parent 92d3724dcd
commit d8cf016f87
Signed by: MightyPork
GPG Key ID: 2C5FD5035250423D
  1. 1
      gex/__init__.py
  2. 228
      gex/units/DAC.py
  3. 46
      test_dac.py

@ -21,6 +21,7 @@ from gex.units.SIPO import SIPO
from gex.units.FCAP import FCAP
from gex.units.TOUCH import TOUCH
from gex.units.PWMDim import PWMDim
from gex.units.DAC import DAC
# General, low level

@ -0,0 +1,228 @@
import gex
CMD_WAVE_DC = 0
CMD_WAVE_SINE = 1
CMD_WAVE_TRIANGLE = 2
CMD_WAVE_SAWTOOTH_UP = 3
CMD_WAVE_SAWTOOTH_DOWN = 4
CMD_WAVE_RECTANGLE = 5
CMD_SYNC = 10
CMD_SET_FREQUENCY = 20
CMD_SET_PHASE = 21
CMD_SET_DITHER = 22
LUT_LEN = 8192
class DAC(gex.Unit):
"""
Analog output (2 channels)
"""
def _type(self):
return 'DAC'
def dc(self, channel, level, confirm=True):
"""
Set DC levels, 0-4095. None to leave the level unchanged
channel: 1,2 (3 = both)
level: 0-4095
"""
if channel != 1 and channel != 2 and channel != 3:
raise Exception("Bad channel arg: %s" % channel)
pb = gex.PayloadBuilder()
pb.u8(channel)
pb.u16(level)
if channel==3:
pb.u16(level)
self._send(CMD_WAVE_DC, pld=pb.close(), confirm=confirm)
def dc_dual(self, ch1, ch2, confirm=True):
"""
Set DC levels, 0-4095
"""
pb = gex.PayloadBuilder()
pb.u8(0b11)
pb.u16(ch1)
pb.u16(ch2)
self._send(CMD_WAVE_DC, pld=pb.close(), confirm=confirm)
def rectangle(self, channel, duty=None, high=None, low=None, confirm=True):
""" Enter rectangle gen mode (duty 0..1000) """
if channel != 1 and channel != 2 and channel != 3:
raise Exception("Bad channel arg: %s" % channel)
pb = gex.PayloadBuilder()
pb.u8(channel) # 0b01 or 0b10
for i in range(0,1 if channel != 3 else 2): # repeat if dual
pb.u16(round(duty * LUT_LEN) if duty is not None # todo ??
else 0xFFFF)
pb.u16(high if high is not None else 0xFFFF)
pb.u16(low if low is not None else 0xFFFF)
self._send(CMD_WAVE_RECTANGLE, pld=pb.close(), confirm=confirm)
def rectangle_dual(self,
duty1=None, duty2=None,
high1=None, high2=None,
low1=None, low2=None,
confirm=True):
""" Set rectangle dual (both at once in sync) """
pb = gex.PayloadBuilder()
pb.u8(0b11) # 0b01 or 0b10
pb.u16(round(duty1*LUT_LEN))
pb.u16(high1 if high1 is not None else 0xFFFF)
pb.u16(low1 if low1 is not None else 0xFFFF)
pb.u16(round(duty2*LUT_LEN))
pb.u16(high2 if high2 is not None else 0xFFFF)
pb.u16(low2 if low2 is not None else 0xFFFF)
self._send(CMD_WAVE_RECTANGLE, pld=pb.close(), confirm=confirm)
def sync(self, confirm=True):
self._send(CMD_SYNC, confirm=confirm)
def waveform(self, channel, waveform, confirm=True):
"""
Set a waveform. For DC or rectangle,
use the dedicated functions with extra parameters
channel: 1,2 (3 = both)
waveform:
- None - leave unchanged
- SINE
- TRIANGLE
- SAW_UP
- SAW_DOWN
"""
lookup = {'SINE': CMD_WAVE_SINE,
'SIN': CMD_WAVE_SINE,
'TRI': CMD_WAVE_TRIANGLE,
'TRIANGLE': CMD_WAVE_TRIANGLE,
'SAW': CMD_WAVE_SAWTOOTH_UP,
'RAMP': CMD_WAVE_SAWTOOTH_UP,
'RAMP_UP': CMD_WAVE_SAWTOOTH_UP,
'SAW_UP': CMD_WAVE_SAWTOOTH_UP,
'SAW_DOWN': CMD_WAVE_SAWTOOTH_DOWN,
'RAMP_DOWN': CMD_WAVE_SAWTOOTH_DOWN,
}
if channel != 1 and channel != 2 and channel != 3:
raise Exception("Bad channel arg: %s" % channel)
pb = gex.PayloadBuilder()
pb.u8(channel) # 0b01 or 0b10
self._send(lookup[waveform], pld=pb.close(), confirm=confirm)
def set_frequency(self, channel, freq, confirm=True):
"""
Set frequency using float in Hz
"""
if channel != 1 and channel != 2 and channel != 3:
raise Exception("Bad channel arg: %s" % channel)
pb = gex.PayloadBuilder()
pb.u8(channel)
pb.float(freq)
if channel == 3:
pb.float(freq)
self._send(CMD_SET_FREQUENCY, pld=pb.close(), confirm=confirm)
def set_frequency_dual(self, freq1, freq2, confirm=True):
"""
Set frequency of both channels using float in Hz
"""
pb = gex.PayloadBuilder()
pb.u8(0b11)
pb.float(freq1)
pb.float(freq2)
self._send(CMD_SET_FREQUENCY, pld=pb.close(), confirm=confirm)
def set_phase(self, channel, phase360, confirm=True):
"""
Set channel phase relative to it's "base phase".
If both channels use the same frequency, this could be used for drawing XY figures.
"""
if channel != 1 and channel != 2 and channel != 3:
raise Exception("Bad channel arg: %s" % channel)
pb = gex.PayloadBuilder()
pb.u8(channel)
pb.u16(round((phase360/360) * LUT_LEN))
if channel == 3:
pb.u16(round((phase360/360) * LUT_LEN))
self._send(CMD_SET_PHASE, pld=pb.close(), confirm=confirm)
def set_phase_dual(self, phase1, phase2, confirm=True):
"""
Set phase for both channels at once
"""
pb = gex.PayloadBuilder()
pb.u8(0b11)
pb.u16((phase1/360) * LUT_LEN)
pb.u16((phase2/360) * LUT_LEN)
self._send(CMD_SET_PHASE, pld=pb.close(), confirm=confirm)
def set_dither(self, channel, type=None, bits=None, confirm=True):
"""
Set dithering (superimposed noise waveform)
type: NONE, TRIANGLE, WHITE
bits: 1-12
"""
if channel != 1 and channel != 2 and channel != 3:
raise Exception("Bad channel arg: %s" % channel)
lookup = {'NONE': 0,
'WHITE': 1,
'NOISE': 1,
'TRIANGLE': 2,
'TRI': 2}
pb = gex.PayloadBuilder()
pb.u8(channel)
for i in range(0,1 if channel != 3 else 2): # repeat if dual
pb.u8(lookup[type] if type is not None else 0xFF)
pb.u8(bits if bits is not None else 0xFF)
self._send(CMD_SET_DITHER, pld=pb.close(), confirm=confirm)

@ -0,0 +1,46 @@
#!/bin/env python3
import time
import math
import gex
from scipy.io import wavfile
with gex.Client(gex.TrxRawUSB()) as client:
dac = gex.DAC(client, 'dac')
# dac.set_dither(1, 'TRI', 8)
# # dac.set_dither(3, 'NONE', 8)
# # #
# # # dac.set_frequency(2, 1)
# # # dac.set_frequency(1, 10.01)
# dac.set_waveform(1, 'SIN')
# # dac.set_waveform(2, 'RAMP')
#
# dac.rectangle(2, 0.5, 4095, 0)
#
# dac.set_frequency(1, 100)
# dac.set_frequency(2, 50)
# #
# dac.sync()
for i in range(0, 1000):
dac.set_frequency(1, i)
time.sleep(0.001)
# dac.waveform(1, 'SIN')
# # dac.set_frequency(1, 1000)
# # dac.dc(1,1000)
# dac.dc(2,1000)
#
# for i in range(0,360*5, 3):
# dac.dc_dual(round(2047+math.cos(((i*3.01)/180)*math.pi)*1900),
# round(2047+math.sin(((i*2.01)/180)*math.pi)*1900),
# confirm=False)
# time.sleep(0.01)
#
# dac.dc_dual(2047,2047)
Loading…
Cancel
Save