diff --git a/dif/const.go b/dif/const.go index a35d09fa2cae5b08266bc53a7fb9f0e499fb705a..cf38229f5f072c1a3dd0d715e7f2788ba9a29d37 100644 --- a/dif/const.go +++ b/dif/const.go @@ -17,4 +17,18 @@ const ( anHeader = 0xc4 // analog frame header marker incFrame = 0xc3 // incomplete frame marker + +) + +const ( + MaxEventSize = (hardrocV2SLCFrameSize+1)*MaxNumASICs + (20*ASICMemDepth+2)*MaxNumASICs + 3 + MaxFwHeaderSize + 2 + MaxAnalogDataSize + 50 + + MaxAnalogDataSize = 1024*64*2 + 20 + MaxFwHeaderSize = 50 + MaxNumASICs = 48 // max number of hardrocs per dif that the system can handle + MaxNumDIFs = 200 // max number of difs that the system can handle + ASICMemDepth = 128 // memory depth of one asic . 128 is for hardroc v1 + + hardrocV2SLCFrameSize = 109 + microrocSLCFrameSize = 74 ) diff --git a/dif/device.go b/dif/device.go new file mode 100644 index 0000000000000000000000000000000000000000..4429f1db5d8b2687b0116b5a99097142087eb7f3 --- /dev/null +++ b/dif/device.go @@ -0,0 +1,257 @@ +// Copyright 2020 The go-lpc Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dif + +import ( + "encoding/binary" + "io" + + "github.com/ziutek/ftdi" + "golang.org/x/xerrors" +) + +type ftdiDevice interface { + Reset() error + + SetBitmode(iomask byte, mode ftdi.Mode) error + SetFlowControl(flowctrl ftdi.FlowCtrl) error + SetLatencyTimer(lt int) error + SetWriteChunkSize(cs int) error + SetReadChunkSize(cs int) error + PurgeBuffers() error + + io.Writer + io.Reader + io.Closer +} + +type device struct { + vid uint16 // vendor ID + pid uint16 // product ID + ft ftdiDevice // handle to the FTDI device +} + +var ( + ftdiOpen = ftdiOpenImpl +) + +func ftdiOpenImpl(vid, pid uint16) (ftdiDevice, error) { + dev, err := ftdi.OpenFirst(int(vid), int(pid), ftdi.ChannelAny) + return dev, err +} + +func newDevice(vid, pid uint16) (*device, error) { + ft, err := ftdiOpen(vid, pid) + if err != nil { + return nil, xerrors.Errorf("could not open FTDI device (vid=0x%x, pid=0x%x): %w", vid, pid, err) + } + + dev := &device{vid: vid, pid: pid, ft: ft} + err = dev.init() + if err != nil { + ft.Close() + return nil, xerrors.Errorf("could not initialize FTDI device (vid=0x%x, pid=0x%x): %w", vid, pid, err) + } + + return dev, nil +} + +func (dev *device) init() error { + var err error + + err = dev.ft.Reset() + if err != nil { + return xerrors.Errorf("could not reset USB: %w", err) + } + + err = dev.ft.SetBitmode(0, ftdi.ModeBitbang) + if err != nil { + return xerrors.Errorf("could not disable bitbang: %w", err) + } + + err = dev.ft.SetFlowControl(ftdi.FlowCtrlDisable) + if err != nil { + return xerrors.Errorf("could not disable flow control: %w", err) + } + + err = dev.ft.SetLatencyTimer(2) + if err != nil { + return xerrors.Errorf("could not set latency timer to 2: %w", err) + } + + err = dev.ft.SetWriteChunkSize(0xffff) + if err != nil { + return xerrors.Errorf("could not set write chunk-size to 0xffff: %w", err) + } + + err = dev.ft.SetReadChunkSize(0xffff) + if err != nil { + return xerrors.Errorf("could not set read chunk-size to 0xffff: %w", err) + } + + if dev.pid == 0x6014 { + err = dev.ft.SetBitmode(0, ftdi.ModeReset) + if err != nil { + return xerrors.Errorf("could not reset bit mode: %w", err) + } + } + + err = dev.ft.PurgeBuffers() + if err != nil { + return xerrors.Errorf("could not purge USB buffers: %w", err) + } + + return err +} + +func (dev *device) close() error { + return dev.ft.Close() +} + +func (dev *device) usbRegRead(addr uint32) (uint32, error) { + a := (addr | 0x4000) & 0x7fff + p := []byte{uint8(a>>8) & 0xff, uint8(a>>0) & 0xff, 0, 0} + + n, err := dev.ft.Write(p[:2]) + switch { + case err != nil: + return 0, xerrors.Errorf("could not write USB addr 0x%x: %w", addr, err) + case n != len(p[:2]): + return 0, xerrors.Errorf("could not write USB addr 0x%x: %w", addr, io.ErrShortWrite) + } + + _, err = io.ReadFull(dev.ft, p) + if err != nil { + return 0, xerrors.Errorf("could not read register 0x%x: %w", addr, err) + } + + v := binary.BigEndian.Uint32(p) + return v, nil +} + +func (dev *device) usbCmdWrite(cmd uint32) error { + addr := cmd | 0x8000 // keep only 14 LSB, write, so bit 14=0,register mode, so bit 15=0 + buf := []byte{uint8(addr>>8) & 0xff, uint8(addr>>0) & 0xff} + + n, err := dev.ft.Write(buf) + switch { + case err != nil: + return xerrors.Errorf("could not write USB command 0x%x: %w", cmd, err) + case n != len(buf): + return xerrors.Errorf("could not write USB command 0x%x: %w", cmd, io.ErrShortWrite) + } + + return nil +} + +func (dev *device) usbRegWrite(addr, v uint32) error { + var ( + a = addr & 0x3fff + p = make([]byte, 6) + ) + + binary.BigEndian.PutUint16(p[:2], uint16(a)) + binary.BigEndian.PutUint32(p[2:], uint32(v)) + and0xff(p) + + n, err := dev.ft.Write(p) + switch { + case err != nil: + return xerrors.Errorf("could not write USB register (0x%x, 0x%x): %w", addr, v, err) + case n != len(p): + return xerrors.Errorf("could not write USB register (0x%x, 0x%x): %w", addr, v, io.ErrShortWrite) + } + return nil +} + +func (dev *device) setChipTypeRegister(v uint32) error { + return dev.usbRegWrite(0x00, v) +} + +func (dev *device) setDIFID(v uint32) error { + return dev.usbRegWrite(0x01, v) +} + +func (dev *device) setControlRegister(v uint32) error { + return dev.usbRegWrite(0x03, v) +} + +func (dev *device) getControlRegister() (uint32, error) { + return dev.usbRegRead(0x03) +} + +func (dev *device) difCptReset() error { + const addr = 0x03 + v, err := dev.usbRegRead(addr) + if err != nil { + return xerrors.Errorf("could not read register 0x%x", addr) + } + + v |= 0x2000 + err = dev.usbRegWrite(addr, v) + if err != nil { + return xerrors.Errorf("could not write to register 0x%x", addr) + } + + v &= 0xffffdfff + err = dev.usbRegWrite(addr, v) + if err != nil { + return xerrors.Errorf("could not write to register 0x%x", addr) + } + + return nil +} + +func (dev *device) setPwr2PwrARegister(v uint32) error { return dev.usbRegWrite(0x40, v) } +func (dev *device) setPwrA2PwrDRegister(v uint32) error { return dev.usbRegWrite(0x41, v) } +func (dev *device) setPwrD2DAQRegister(v uint32) error { return dev.usbRegWrite(0x42, v) } +func (dev *device) setDAQ2PwrDRegister(v uint32) error { return dev.usbRegWrite(0x43, v) } +func (dev *device) setPwrD2PwrARegister(v uint32) error { return dev.usbRegWrite(0x44, v) } + +func (dev *device) setEventsBetweenTemperatureReadout(v uint32) error { + return dev.usbRegWrite(0x55, v) +} + +func (dev *device) setAnalogConfigureRegister(v uint32) error { + return dev.usbRegWrite(0x60, v) +} + +func (dev *device) usbFwVersion() (uint32, error) { + return dev.usbRegRead(0x100) +} + +func (dev *device) hardrocFlushDigitalFIFO() error { + return nil +} + +func (dev *device) hardrocStopDigitalAcquisitionCommand() error { + return dev.usbCmdWrite(0x02) +} + +func (dev *device) hardrocSLCStatusRead() (uint32, error) { + return dev.usbRegRead(0x06) +} + +func (dev *device) hardrocCmdSLCWrite() error { + return dev.usbCmdWrite(0x01) +} + +func (dev *device) hardrocCmdSLCWriteCRC(v uint16) error { + p := make([]byte, 2) + binary.BigEndian.PutUint16(p, v) + _, err := dev.ft.Write(p) + return err +} + +func (dev *device) cmdSLCWriteSingleSLCFrame(p []byte) error { + _, err := dev.ft.Write(p) + return err +} + +func and0xff(p []byte) { + for i := range p { + p[i] &= 0xff + } +} diff --git a/dif/device_test.go b/dif/device_test.go new file mode 100644 index 0000000000000000000000000000000000000000..b6237a87e2305b4ba9e94e70e758be0c1619ff43 --- /dev/null +++ b/dif/device_test.go @@ -0,0 +1,145 @@ +// Copyright 2020 The go-lpc Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dif + +import ( + "io" + "testing" + + "golang.org/x/xerrors" +) + +func TestFTDIOpen(t *testing.T) { + dev, err := ftdiOpenImpl(0, 0) + if err == nil { + _ = dev.Close() + } +} + +type ierr struct { + n int + e error +} + +type failingRW struct { + rs []ierr + ws []ierr +} + +func (rw *failingRW) Read(p []byte) (int, error) { + i := len(rw.rs) + rs := rw.rs[i-1] + rw.rs = rw.rs[:i-1] + return rs.n, rs.e +} + +func (rw *failingRW) Write(p []byte) (int, error) { + i := len(rw.ws) + ws := rw.ws[i-1] + rw.ws = rw.ws[:i-1] + return ws.n, ws.e +} + +func TestDevice(t *testing.T) { + ftdiOpen = ftdiOpenTest + defer func() { + ftdiOpen = ftdiOpenImpl + }() + + dev, err := newDevice(0x1, 0x2) + if err != nil { + t.Fatalf("could not create fake device: %+v", err) + } + defer dev.close() + + var ( + rw failingRW + ft = fakeDevice{buf: &rw} + ) + dev.ft = &ft + + for _, tc := range []struct { + name string + f func() error + want error + }{ + { + name: "usbRegRead-eof", + f: func() error { + rw.ws = append(rw.ws, ierr{0, io.EOF}) + _, err := dev.usbRegRead(0x1234) + return err + }, + want: xerrors.Errorf("could not write USB addr 0x%x: %w", 0x1234, io.EOF), + }, + { + name: "usbRegRead-short-write", + f: func() error { + rw.ws = append(rw.ws, ierr{1, nil}) + _, err := dev.usbRegRead(0x1234) + return err + }, + want: xerrors.Errorf("could not write USB addr 0x%x: %w", 0x1234, io.ErrShortWrite), + }, + { + name: "usbRegRead-err-read", + f: func() error { + rw.ws = append(rw.ws, ierr{2, nil}) + rw.rs = append(rw.rs, ierr{2, io.ErrUnexpectedEOF}) + _, err := dev.usbRegRead(0x1234) + return err + }, + want: xerrors.Errorf("could not read register 0x%x: %w", 0x1234, io.ErrUnexpectedEOF), + }, + { + name: "usbCmdWrite-eof", + f: func() error { + rw.ws = append(rw.ws, ierr{0, io.EOF}) + return dev.usbCmdWrite(0x1234) + }, + want: xerrors.Errorf("could not write USB command 0x%x: %w", 0x1234, io.EOF), + }, + { + name: "usbCmdWrite-short-write", + f: func() error { + rw.ws = append(rw.ws, ierr{1, nil}) + return dev.usbCmdWrite(0x1234) + }, + want: xerrors.Errorf("could not write USB command 0x%x: %w", 0x1234, io.ErrShortWrite), + }, + { + name: "usbRegWrite-eof", + f: func() error { + rw.ws = append(rw.ws, ierr{0, io.EOF}) + return dev.usbRegWrite(0x1234, 0x255) + }, + want: xerrors.Errorf("could not write USB register (0x%x, 0x%x): %w", 0x1234, 0x255, io.EOF), + }, + { + name: "usbRegWrite-short-write", + f: func() error { + rw.ws = append(rw.ws, ierr{1, nil}) + return dev.usbRegWrite(0x1234, 0x255) + }, + want: xerrors.Errorf("could not write USB register (0x%x, 0x%x): %w", 0x1234, 0x255, io.ErrShortWrite), + }, + } { + t.Run(tc.name, func(t *testing.T) { + got := tc.f() + switch { + case got == nil && tc.want == nil: + // ok + case got == nil && tc.want != nil: + t.Fatalf("got=%v, want=%v", got, tc.want) + case got != nil && tc.want != nil: + if got, want := got.Error(), tc.want.Error(); got != want { + t.Fatalf("got= %v\nwant=%v", got, want) + } + case got != nil && tc.want == nil: + t.Fatalf("got=%+v\nwant=%v", got, tc.want) + } + }) + } +} diff --git a/dif/readout.go b/dif/readout.go new file mode 100644 index 0000000000000000000000000000000000000000..aa25b8737103e11cdcf48df3b64da6dac57709f8 --- /dev/null +++ b/dif/readout.go @@ -0,0 +1,309 @@ +// Copyright 2020 The go-lpc Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dif + +import ( + "fmt" + "io" + "time" + + "github.com/go-daq/tdaq/log" + "github.com/go-lpc/mim/internal/crc16" + "golang.org/x/xerrors" +) + +type asicKind uint32 + +const ( + microrocASIC asicKind = 11 + hardrocASIC asicKind = 2 +) + +type Readout struct { + msg log.MsgStream + dev *device + name string + difID uint32 + asic asicKind // asic type + nasics int // number of asics + ctlreg uint32 // control register + curSC uint32 // current slow-control status + reg struct { + p2pa uint32 // power to power A + pa2pd uint32 // power A to power D + pd2daq uint32 // power D to DAQ + daq2pd uint32 // DAQ to power D + pd2pa uint32 // power D to power A + } + temp [2]float32 // temperatures +} + +func NewReadout(name string, prodID uint32, msg log.MsgStream) (*Readout, error) { + dev, err := newDevice(0x0403, uint16(prodID)) + if err != nil { + return nil, xerrors.Errorf("could not find DIF driver (%s, 0x%x): %w", name, prodID, err) + } + + rdo := &Readout{ + msg: msg, + dev: dev, + name: name, + asic: hardrocASIC, + nasics: MaxNumASICs, + ctlreg: 0x80181b00, // ILC CCC + } + rdo.reg.p2pa = 0x3e8 + rdo.reg.pa2pd = 0x3e6 + rdo.reg.pd2daq = 0x4e + rdo.reg.daq2pd = 0x4e + rdo.reg.pd2pa = 0x4e + _, err = fmt.Sscanf(name, "FT101%d", &rdo.difID) + if err != nil { + _ = dev.close() + return nil, xerrors.Errorf("could not find DIF-id from %q: %w", name, err) + } + + return rdo, nil +} + +func (rdo *Readout) close() error { + err := rdo.dev.close() + if err != nil { + return xerrors.Errorf("could not close DIF driver: %w", err) + } + return nil +} + +func (rdo *Readout) start() error { + return rdo.dev.hardrocFlushDigitalFIFO() +} + +func (rdo *Readout) stop() error { + var err error + + err = rdo.dev.hardrocFlushDigitalFIFO() + if err != nil { + return xerrors.Errorf("could not flush digital FIFO: %w", err) + } + + err = rdo.dev.hardrocStopDigitalAcquisitionCommand() + if err != nil { + return xerrors.Errorf("could not stop digital acquisition: %w", err) + } + + err = rdo.dev.hardrocFlushDigitalFIFO() + if err != nil { + return xerrors.Errorf("could not flush digital FIFO: %w", err) + } + + return nil +} + +func (rdo *Readout) configureRegisters() error { + var err error + err = rdo.dev.setDIFID(rdo.difID) + if err != nil { + return xerrors.Errorf("could not set DIF ID to 0x%x: %w", rdo.difID, err) + } + + err = rdo.doRefreshNumASICs() + if err != nil { + return xerrors.Errorf("could not refresh #ASICs: %w", err) + } + + err = rdo.dev.setEventsBetweenTemperatureReadout(5) + if err != nil { + return xerrors.Errorf("could not set #events Temp readout: %w", err) + } + + err = rdo.dev.setAnalogConfigureRegister(0xc0054000) + if err != nil { + return xerrors.Errorf("could not configure analog register: %w", err) + } + + err = rdo.dev.hardrocFlushDigitalFIFO() + if err != nil { + return xerrors.Errorf("could not flush digital FIFO: %w", err) + } + + fw, err := rdo.dev.usbFwVersion() + if err != nil { + return xerrors.Errorf("could not get firmware version: %w", err) + } + rdo.msg.Infof("dif %s fw: 0x%x", rdo.name, fw) + + err = rdo.dev.difCptReset() + if err != nil { + return xerrors.Errorf("could not reset DIF cpt: %w", err) + } + + err = rdo.dev.setChipTypeRegister(map[asicKind]uint32{ + hardrocASIC: 0x100, + microrocASIC: 0x1000, + }[rdo.asic]) + if err != nil { + return xerrors.Errorf("could not set chip type: %w", err) + } + + err = rdo.dev.setControlRegister(rdo.ctlreg) + if err != nil { + return xerrors.Errorf("could not set control register: %w", err) + } + + ctlreg, err := rdo.dev.getControlRegister() + if err != nil { + return xerrors.Errorf("could not get control register: %w", err) + } + rdo.msg.Infof("ctl reg: 0x%x", ctlreg) + + err = rdo.dev.setPwr2PwrARegister(rdo.reg.p2pa) + if err != nil { + return xerrors.Errorf("could not set pwr to A register: %w", err) + } + + err = rdo.dev.setPwrA2PwrDRegister(rdo.reg.pa2pd) + if err != nil { + return xerrors.Errorf("could not set A to D register: %w", err) + } + + err = rdo.dev.setPwrD2DAQRegister(rdo.reg.pd2daq) + if err != nil { + return xerrors.Errorf("could not set D to DAQ register: %w", err) + } + + err = rdo.dev.setDAQ2PwrDRegister(rdo.reg.daq2pd) + if err != nil { + return xerrors.Errorf("could not set DAQ to D register: %w", err) + } + + err = rdo.dev.setPwrD2PwrARegister(rdo.reg.pd2pa) + if err != nil { + return xerrors.Errorf("could not set D to A register: %w", err) + } + + return err +} + +func (rdo *Readout) configureChips(scFrame [][]byte) (uint32, error) { + var frame []byte + switch rdo.asic { + case hardrocASIC: + frame = make([]byte, hardrocV2SLCFrameSize) + case microrocASIC: + frame = make([]byte, microrocSLCFrameSize) + default: + return 0, xerrors.Errorf("unknown ASIC kind %v", rdo.asic) + } + + crc := crc16.New(nil) + err := rdo.dev.hardrocCmdSLCWrite() + if err != nil { + return 0, xerrors.Errorf("%s could not send start SLC command to DIF: %w", + rdo.name, err, + ) + } + + for i := rdo.nasics; i > 0; i-- { + copy(frame, scFrame[i-1]) + _, err = crc.Write(frame) + if err != nil { + return 0, xerrors.Errorf("%s could not update CRC-16: %w", rdo.name, err) + } + + err = rdo.dev.cmdSLCWriteSingleSLCFrame(frame) + if err != nil { + return 0, xerrors.Errorf("%s could not send SLC frame to DIF: %w", + rdo.name, err, + ) + } + } + + crc16 := crc.Sum16() + err = rdo.dev.hardrocCmdSLCWriteCRC(crc16) + if err != nil { + return 0, xerrors.Errorf("%s could not send CRC 0x%x to SLC: %w", + rdo.name, crc16, err, + ) + } + + time.Sleep(400 * time.Millisecond) // was 500ms + + st, err := rdo.doReadSLCStatus() + if err != nil { + return 0, xerrors.Errorf("%s could not read SLC status: %w", + rdo.name, err, + ) + } + rdo.curSC = st + + return st, nil +} + +func (rdo *Readout) Readout(p []byte) (int, error) { + var ( + dif DIF + w = bwriter{p: p} + dec = NewDecoder(uint8(rdo.difID), io.TeeReader(rdo.dev.ft, &w)) + ) + err := dec.Decode(&dif) + if err != nil { + return w.c, xerrors.Errorf("%s could not decode DIF data: %w", + rdo.name, err, + ) + } + + return w.c, nil +} + +func (rdo *Readout) doRefreshNumASICs() error { + var ( + v uint32 + l1 = uint8(rdo.nasics>>0) & 0xff + l2 = uint8(rdo.nasics>>8) & 0xff + l3 = uint8(rdo.nasics>>16) & 0xff + l4 = uint8(rdo.nasics>>24) & 0xff + n = l1 + l2 + l3 + l4 + ) + + f := func(n, l1, l2, l3, l4 uint8) uint32 { + return uint32(n) + uint32(l1<<8) + uint32(l2<<14) + uint32(l3<<20) + uint32(l4<<26) + } + switch rdo.asic { + case microrocASIC: + v = f(n, l1, l2, l3, l4) + default: + v = f(n, n, 0, 0, 0) + } + + err := rdo.dev.usbRegWrite(0x05, v) + if err != nil { + return xerrors.Errorf("could not refresh num-asics: %w", err) + } + + return nil +} + +func (rdo *Readout) doReadSLCStatus() (uint32, error) { + st, err := rdo.dev.hardrocSLCStatusRead() + if err != nil { + return 0, xerrors.Errorf("could not read SLC status: %w", err) + } + rdo.curSC = st + return st, nil +} + +type bwriter struct { + p []byte + c int +} + +func (w *bwriter) Write(p []byte) (int, error) { + if w.c >= len(w.p) { + return 0, io.EOF + } + n := copy(w.p[w.c:], p) + w.c += n + return n, nil +} diff --git a/dif/readout_test.go b/dif/readout_test.go new file mode 100644 index 0000000000000000000000000000000000000000..8667fe2d94c90beeff1b4a04d807fda14a1718cc --- /dev/null +++ b/dif/readout_test.go @@ -0,0 +1,148 @@ +// Copyright 2020 The go-lpc Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package dif + +import ( + "bytes" + "io" + "os" + "testing" + + "github.com/go-daq/tdaq/log" + "github.com/ziutek/ftdi" +) + +func ftdiOpenTest(vid, pid uint16) (ftdiDevice, error) { + return &fakeDevice{buf: new(bytes.Buffer)}, nil +} + +func TestReadout(t *testing.T) { + ftdiOpen = ftdiOpenTest + defer func() { + ftdiOpen = ftdiOpenImpl + }() + + const ( + name = "FT101042" + prodID = 0x6014 + ) + + rdo, err := NewReadout(name, prodID, log.NewMsgStream("readout-"+name, log.LvlDebug, os.Stderr)) + if err != nil { + t.Fatalf("could not create readout: %+v", err) + } + + err = rdo.configureRegisters() + if err != nil { + t.Fatalf("could not configure registers: %+v", err) + } + + slow := make([][]byte, rdo.nasics) + for i := range slow { + slow[i] = make([]byte, hardrocV2SLCFrameSize) + } + _, err = rdo.configureChips(slow) + if err != nil { + t.Fatalf("could not configure chips: %+v", err) + } + + err = rdo.start() + if err != nil { + t.Fatalf("could not start readout: %+v", err) + } + + data := make([]byte, MaxEventSize) + { + w := new(bytes.Buffer) + dif := DIF{ + Header: GlobalHeader{ + ID: uint8(rdo.difID), + DTC: 10, + ATC: 11, + GTC: 12, + AbsBCID: 0x0000112233445566, + TimeDIFTC: 0x00112233, + }, + Frames: []Frame{ + { + Header: 1, + BCID: 0x001a1b1c, + Data: [16]uint8{0xa, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}, + }, + { + Header: 2, + BCID: 0x002a2b2c, + Data: [16]uint8{ + 0xb, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 210, 211, 212, 213, 214, 215, + }, + }, + }, + } + err = NewEncoder(w).Encode(&dif) + if err != nil { + t.Fatalf("could not encode DIF data: %+v", err) + } + rdo.dev.ft = &fakeDevice{w} + } + n, err := rdo.Readout(data) + if err != nil { + t.Fatalf("could not readout data: %+v", err) + } + if n <= 0 { + t.Fatalf("could not readout data: n=%d", n) + } + data = data[:n] + + err = rdo.stop() + if err != nil { + t.Fatalf("could not stop readout: %+v", err) + } + + err = rdo.close() + if err != nil { + t.Fatalf("could not close readout: %+v", err) + } +} + +type fakeDevice struct { + buf io.ReadWriter +} + +func (dev *fakeDevice) Reset() error { return nil } + +func (dev *fakeDevice) SetBitmode(iomask byte, mode ftdi.Mode) error { + return nil +} + +func (dev *fakeDevice) SetFlowControl(flowctrl ftdi.FlowCtrl) error { + return nil +} + +func (dev *fakeDevice) SetLatencyTimer(lt int) error { + return nil +} + +func (dev *fakeDevice) SetWriteChunkSize(cs int) error { + return nil +} + +func (dev *fakeDevice) SetReadChunkSize(cs int) error { + return nil +} + +func (dev *fakeDevice) PurgeBuffers() error { + return nil +} + +func (dev *fakeDevice) Read(p []byte) (int, error) { + return dev.buf.Read(p) +} + +func (dev *fakeDevice) Write(p []byte) (int, error) { + return dev.buf.Write(p) +} + +func (dev *fakeDevice) Close() error { return nil } diff --git a/go.mod b/go.mod index 89756fd475824adce515bf937e8165cc4e9b6d70..899edc2bee30beb553189ba90fc05ff02c7abebb 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.14 require ( github.com/go-daq/tdaq v0.13.0 github.com/peterh/liner v1.1.0 + github.com/ziutek/ftdi v0.0.0-20181130113013-aef9e445a2fa golang.org/x/net v0.0.0-20200202094626-16171245cfb2 // indirect golang.org/x/sys v0.0.0-20200217220822-9197077df867 // indirect golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 diff --git a/go.sum b/go.sum index 426ec820725fb490ddaf3fcd0ba29c0e7cbc0e7e..af8130451a5f7c9d5079dd5aaa650f3cfb18a7f3 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qq github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/ziutek/ftdi v0.0.0-20181130113013-aef9e445a2fa h1:8J6YeSHVtoJG5sodX1Y6qPM3eaLmxC0noolyHwWdbsM= +github.com/ziutek/ftdi v0.0.0-20181130113013-aef9e445a2fa/go.mod h1:N08Z75zCaXPhywWVtQxjPLGCh0HtZ0pUIEeV/UlHmhI= go.nanomsg.org/mangos/v3 v3.0.0 h1:50i1v/XDhTcYW2CnJYxjpuHKf041obWL0Ccezz6SsJs= go.nanomsg.org/mangos/v3 v3.0.0/go.mod h1:+o2RKKCIEB6Dw/4Frf2biiEuqcRDKcEUSrC0r9OWDE0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -46,7 +48,6 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa h1:F+8P+gmewFQYRk6JoLQLwjBCTu3mcIURZfNkVweuRKA= golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200202094626-16171245cfb2 h1:CCH4IOTTfewWjGOlSp+zGcjutRKlBEZQ6wTn8ozI/nI= golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -59,7 +60,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200217220822-9197077df867 h1:JoRuNIf+rpHl+VhScRQQvzbHed86tKkqwPMV34T8myw= golang.org/x/sys v0.0.0-20200217220822-9197077df867/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=