Skip to content
Snippets Groups Projects
Commit f2247d7e authored by BRONES Romain's avatar BRONES Romain
Browse files

Add PSCGEN application

parent a0858b6c
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env python3
import deviceaccess
import logging
import argparse
import numpy as np
# Prepare logger
logger = logging.getLogger("pscgen")
# DAQ device
deviceaccess.setDMapFilePath("/opt/fofb/map/devices.dmap")
appdev = deviceaccess.Device("APPUIO")
appdev.open()
def configure_raw(idx, rst=None, phincr=None, phoffs=None, scale=None, offset=None):
"""
Configure PSC sinewave generator for a PSCID.
If a parameter is set on 'None', the value is kept unchanged.
PARAMETERS:
-----------
idx: int
PSCID of the line to configure
rst: bool
Set the reset bit
phincr: int
Phase increment value. NCO is on 16 bits.
phoffs: int
Phase offset value. NCO is on 16 bits.
scale: int
Amplitude scaler. Unsigned on 16 bits.
offset: int
Amplitude offset. Signed on 16 bits.
"""
_phincr = appdev.getOneDRegisterAccessor(np.uintc, "APP.pscgen_0.TABLE_PHASE_INCR")
_phoffs = appdev.getOneDRegisterAccessor(np.uintc, "APP.pscgen_0.TABLE_PHASE_OFFS")
_scale = appdev.getOneDRegisterAccessor(np.uintc, "APP.pscgen_0.TABLE_SCALE")
_phincr.read()
_phoffs.read()
_scale.read()
if not rst is None:
if rst==1:
_phoffs[idx] = _phoffs[idx] | 0x10000
else:
_phoffs[idx] = _phoffs[idx] & 0xFFFF
if not phincr is None:
_phincr[idx] = phincr
if not phoffs is None:
_phoffs[idx] = phoffs + (_phoffs[idx] & 0x10000)
if not scale is None:
_scale[idx] = (_scale[idx] & 0xFFFF0000) + scale
if not offset is None:
_scale[idx] = (_scale[idx] & 0xFFFF) + (offset<<16)
_scale.write()
_phincr.write()
_phoffs.write()
def configure(idx, freq=None, phase=None, amp=None, offset=None):
"""
Convenient method to set PSC sinewave generator with physical inputs (Hz, A, degree)
It calls psc_configure() and return the exact values.
PARAMETERS:
-----------
idx: int
PSCID of the line to configure
freq: float
Set the sine wave frequency (Hz, <5000)
A negative value reset the generator.
phase: float
Set the sine wave phase (deg, 0<=phase<360)
amp: float
Peak to peak amplitude of the sine wave (A, <20))
offset: float
Offset of the sine wave (A, -10<=offset<=10))
RETURNS
-------
idx, rst, phincr, phoffs, scale, offset:
Parameters used to call psc_configure()
"""
if not freq is None:
if freq > 5000:
raise ValueError("Frequency shall be < 5000")
phincr = int(np.round(freq/10079*2**16))
rst = 0
if freq <= 0:
rst = 1
phincr=None
else:
phincr = None
rst= None
if not phase is None:
if phase >= 360 or phase < 0:
raise ValueError("Phase shall be 0 <= phase < 360")
phoffs = int(np.round(phase/360*2**16))
else:
phoffs = None
if not amp is None:
if amp > 20 or amp < 0:
raise ValueError("Amp shall be in [ 0 ; 20 ] A")
scale = int(0xFFFF * amp/20)
else:
scale=None
if not offset is None:
if offset > 10 or offset < -10:
raise ValueError("Amp shall be in [ -10 ; 10 ] A")
if offset >= 0:
offset = int(0x7FFF * offset/10)
else:
offset = int(0xFFFF+0x7FFF*offset/10)
else:
offset=None
logger.debug("rst={} phincr={} phoffs={} scale={} offset={}".format(rst, phincr, phoffs, scale, offset))
configure_raw(idx, rst, phincr, phoffs, scale, offset)
return idx, rst, phincr, phoffs, scale, offset
def reset():
# Table depth to 100 entries
appdev.write("APP.pscgen_0.TABLE_DEPTH", np.uintc(100))
# Ticker rate to 10075 Hz
appdev.write("APP.pscgen_0.TICKER_RATE", np.uintc(100e6//10074))
# All line to reset, scale 0, offset 0
for i in range(100):
configure_raw(i, rst=1, scale=0, offset=0)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PSC sine wave generator")
parser.add_argument("--reset", action="store_true", help="Reset configuration. First action performed if selected.")
parser.add_argument("--raw", action="store_true", help="Switch to raw inputs: phase increment, DAC units. All inputs must be given")
parser.add_argument("pscid", type=int, help="ID of the PSC to configure")
parser.add_argument("-f", type=float, default=None, help="Set frequency in Hz. Use a negative frequency to reset NCO")
parser.add_argument("-p", type=float, default=None, help="Set phase in degree")
parser.add_argument("-a", type=float, default=None, help="Set pk-pk amplitude in A")
parser.add_argument("-o", type=float, default=None, help="Set DC offset in A")
args = parser.parse_args()
if args.reset:
reset()
if args.raw:
configure_raw(args.pscid, 0, int(args.f), int(args.p), int(args.a), int(args.o))
else:
configure(args.pscid, args.f, args.p, args.a, args.o)
SUMMARY = "Simple python tool to use the PSC sinus generator"
SECTION = "opt"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = " file://pscgen"
RDEPENDS_${PN}=" deviceaccess-mapfiles deviceaccess-python-bindings"
FILES_${PN}+="/usr/bin/pscgen"
do_install() {
# Add FPGA version reader and FoFb Configurator
install -d ${D}/usr/bin/
install -m 0755 ${WORKDIR}/pscgen ${D}/usr/bin/pscgen
}
...@@ -28,7 +28,7 @@ IMAGE_INSTALL_append = " deviceaccess" ...@@ -28,7 +28,7 @@ IMAGE_INSTALL_append = " deviceaccess"
IMAGE_INSTALL_append = " deviceaccess-python-bindings" IMAGE_INSTALL_append = " deviceaccess-python-bindings"
IMAGE_INSTALL_append = " fofb-opcua-server" IMAGE_INSTALL_append = " fofb-opcua-server"
IMAGE_INSTALL_append = " fofb-init" IMAGE_INSTALL_append = " fofb-init"
IMAGE_INSTALL_append = " fofb-daqcapt" IMAGE_INSTALL_append = " fofb-daqcapt fofb-pscgen"
IMAGE_INSTALL_append = " nfs-utils" IMAGE_INSTALL_append = " nfs-utils"
# We do not need that # We do not need that
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment