Skip to content
This repository was archived by the owner on Dec 24, 2024. It is now read-only.

rpi: import RPi TDAQ server #43

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ jobs:
if: matrix.platform == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -qq pkg-config gcc-arm-linux-gnueabihf
sudo apt-get install -qq pkg-config gcc-arm-linux-gnueabihf libftdi1-dev

- name: Build-Linux-32b-arm
if: matrix.platform == 'ubuntu-latest'
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/go-sql-driver/mysql v1.7.0
github.com/peterh/liner v1.2.2
github.com/sbinet/pmon v0.5.0
github.com/ziutek/ftdi v0.0.1
go-hep.org/x/hep v0.32.1
golang.org/x/sync v0.1.0
golang.org/x/sys v0.7.0
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/ziutek/ftdi v0.0.1 h1:IrFtqLisIzEfgSnuLg1suZYLkn227DTyE464XswAGK4=
github.com/ziutek/ftdi v0.0.1/go.mod h1:fUzQhjslJJSlwoMW5Cd+0RUc8KuMDfsuZB+wfJAz1eg=
github.com/ziutek/lcd v0.0.0-20141212131202-924f223d0903/go.mod h1:ZBCPhfHIcCtzsrXIcyEiSPDKHrjT9fXtJNKj2t1HCKw=
go-hep.org/x/hep v0.32.1 h1:O96fOyMP+4ET8X+Uu38VFdegQb7rL0rjmFqXMCSm4VM=
go-hep.org/x/hep v0.32.1/go.mod h1:VX3IVUv0Ku5bgWhE+LxRQ1aT7BmWWxSxQu02hfsoeRI=
go.nanomsg.org/mangos/v3 v3.2.1/go.mod h1:RxVwsn46YtfJ74mF8MeVo+MFjg545KCI50NuZrFXmzc=
Expand Down
18 changes: 18 additions & 0 deletions rpi/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// 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 rpi

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
)
257 changes: 257 additions & 0 deletions rpi/device.go
Original file line number Diff line number Diff line change
@@ -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 rpi

import (
"encoding/binary"
"fmt"
"io"

"github.com/ziutek/ftdi"
)

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, fmt.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, fmt.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 fmt.Errorf("could not reset USB: %w", err)
}

err = dev.ft.SetBitmode(0, ftdi.ModeBitbang)
if err != nil {
return fmt.Errorf("could not disable bitbang: %w", err)
}

err = dev.ft.SetFlowControl(ftdi.FlowCtrlDisable)
if err != nil {
return fmt.Errorf("could not disable flow control: %w", err)
}

err = dev.ft.SetLatencyTimer(2)
if err != nil {
return fmt.Errorf("could not set latency timer to 2: %w", err)
}

err = dev.ft.SetWriteChunkSize(0xffff)
if err != nil {
return fmt.Errorf("could not set write chunk-size to 0xffff: %w", err)
}

err = dev.ft.SetReadChunkSize(0xffff)
if err != nil {
return fmt.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 fmt.Errorf("could not reset bit mode: %w", err)
}
}

err = dev.ft.PurgeBuffers()
if err != nil {
return fmt.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, fmt.Errorf("could not write USB addr 0x%x: %w", addr, err)
case n != len(p[:2]):
return 0, fmt.Errorf("could not write USB addr 0x%x: %w", addr, io.ErrShortWrite)
}

_, err = io.ReadFull(dev.ft, p)
if err != nil {
return 0, fmt.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 fmt.Errorf("could not write USB command 0x%x: %w", cmd, err)
case n != len(buf):
return fmt.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 fmt.Errorf("could not write USB register (0x%x, 0x%x): %w", addr, v, err)
case n != len(p):
return fmt.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 fmt.Errorf("could not read register 0x%x", addr)
}

v |= 0x2000
err = dev.usbRegWrite(addr, v)
if err != nil {
return fmt.Errorf("could not write to register 0x%x", addr)
}

v &= 0xffffdfff
err = dev.usbRegWrite(addr, v)
if err != nil {
return fmt.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
}
}
Loading