diff --git a/Makefile b/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..c8557b35adc701ba97d3369fedfac3c6e6a66dfb --- /dev/null +++ b/Makefile @@ -0,0 +1,91 @@ +# +# 'make' build executable file 'main' +# 'make clean' removes all .o and executable files +# + +# define the Cpp compiler to use +CXX = g++ + +# define any compile-time flags +CXXFLAGS := -std=c++17 -Wall -Wextra -g + +# define library paths in addition to /usr/lib +# if I wanted to include libraries not in /usr/lib I'd specify +# their path using -Lpath, something like: +LFLAGS = -lcapnp -lkj + +# define output directory +OUTPUT := output + +# define source directory +SRC := src + +# define include directory +INCLUDE := include + +# define lib directory +LIB := lib + +ifeq ($(OS),Windows_NT) +MAIN := main.exe +SOURCEDIRS := $(SRC) +INCLUDEDIRS := $(INCLUDE) +LIBDIRS := $(LIB) +FIXPATH = $(subst /,\,$1) +RM := del /q /f +MD := mkdir +else +MAIN := main +SOURCEDIRS := $(shell find $(SRC) -type d) +INCLUDEDIRS := $(shell find $(INCLUDE) -type d) +LIBDIRS := $(shell find $(LIB) -type d) +FIXPATH = $1 +RM = rm -f +MD := mkdir -p +endif + +# define any directories containing header files other than /usr/include +INCLUDES := $(patsubst %,-I%, $(INCLUDEDIRS:%/=%)) + +# define the C libs +LIBS := $(patsubst %,-L%, $(LIBDIRS:%/=%)) + +# define the C source files +SOURCES := $(wildcard $(patsubst %,%/*.cpp, $(SOURCEDIRS))) + +# define the C object files +OBJECTS := $(SOURCES:.cpp=.o) + +# +# The following part of the makefile is generic; it can be used to +# build any executable just by changing the definitions above and by +# deleting dependencies appended to the file from 'make depend' +# + +OUTPUTMAIN := $(call FIXPATH,$(OUTPUT)/$(MAIN)) + +all: $(OUTPUT) $(MAIN) + @echo Executing 'all' complete! + +$(OUTPUT): + $(MD) $(OUTPUT) + +$(MAIN): $(OBJECTS) + $(CXX) $(CXXFLAGS) $(INCLUDES) -o $(OUTPUTMAIN) $(OBJECTS) $(LFLAGS) $(LIBS) + +# this is a suffix replacement rule for building .o's from .c's +# it uses automatic variables $<: the name of the prerequisite of +# the rule(a .c file) and $@: the name of the target of the rule (a .o file) +# (see the gnu make manual section about automatic variables) +.cpp.o: + $(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ + +.PHONY: clean +clean: + $(RM) $(OUTPUTMAIN) + $(RM) $(call FIXPATH,$(OBJECTS)) + @echo Cleanup complete! + +run: all + ./$(OUTPUTMAIN) + @echo Executing 'run: all' complete! \ No newline at end of file diff --git a/README.md b/README.md index 23ec5e0a9d302f8159fd7b5fadf5bc64cd5faf19..e58b63f42d28485b59c0c782ec90ba05ff5a73b2 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ # PyPCC Python OPC-UA server to control the I2C devices in the LTS. + + opcuserv.py: OPC-UA server that expose (visible) variables and methods. # Prerequisites diff --git a/compile.sh b/compile.sh new file mode 100644 index 0000000000000000000000000000000000000000..256c591e106a03f05b35f8c588a3553650920dd3 --- /dev/null +++ b/compile.sh @@ -0,0 +1,7 @@ +rm pypcc/pypcc.capnp +cd src/interface +capnp compile -oc++ pypcc.capnp +cp pypcc.capnp ../../pypcc/. +cd ../.. +make clean +make \ No newline at end of file diff --git a/pcctypes.py b/pcctypes.py deleted file mode 100644 index 1450ec4701ec6f76d6a96a1141b592e874666fc2..0000000000000000000000000000000000000000 --- a/pcctypes.py +++ /dev/null @@ -1,79 +0,0 @@ -#For capnproto -from collections import namedtuple -from enum import Enum -from recordclass import recordclass - -#I2C ports & Switch addresses of device -MPaddr=namedtuple("MPaddr","nI2C I2C nSwitch Switch"); - -#Device registers -DevReg=namedtuple("DevReg","Addr Register_R Register_W store"); -#Addr: Byte (I2C) or *BBdev -#Register_R/W: Byte (I2C register) -#store: Byte 0=not stored else store index - -#Bitbang devices -BBdev=namedtuple("BBdev","nPins devs pins addr") -# devs: *DevReg[nPins] -# pins: Byte[nPins] -# addr: Byte (SPI device address) - - -class I2Cmodules(Enum): - Switch = 0 - RCU = 1 - CLK = 2 - UNB2 = 3 - -class DevType(Enum): - Var = 0 - I2C = 1 - SPIbb= 2 - I2Cbb= 3 - Instr =4 - VarUpdate = 5 - Internal = 6 - HBA1 = 7 - HBA2 = 8 - -class RW(Enum): - Hidden = 0 #Not an OPC_UA variable - ReadOnly = 1 #OPC_variable name_R - WriteOnly = 2 #OPC_variable name_RW - ReadWrite = 3 #both of above - -class datatype(Enum): - dInt = 0 - dfloat = 1 - dstring = 2 - -#Variable two device link -Var2dev=namedtuple("Var2dev","name module type devreg width bitoffset Scale") -#name: string (Currently unused!) -#module: I2Cmodules -#Type: DevType -#DevReg: *DevReg -#Width: Byte (# of bits) -#Bitoffset: Byte -#Scale: Float (=1 means no scaling i.e. integer) - -#OPC-UA variable: Array of similar variables -VarArray=recordclass("VarArray","name nVars Vars RW type size OPCR OPCW") #OPCR and OPCW linked at runtime -#name: string -#Vars: *Var2dev[nVars] -#RW: RW -#type: datatype -#size: =nVars (default), but x16/32 for HBA antennas -#OPCR/W: pointer to variable in OPC-UA server (linked during runtime) - -#Instruction -Instr=namedtuple("DevInstr","type dev nvalue value") -#Type: DevType -#dev: pointer to vararray / DevReg / etc depending on type -#value: Bytes[nvalue] - -#List of instructions -Instrs=namedtuple("Instr","name ninstr instr") -#name: string -#inst: Instr[ninstr] - diff --git a/pypcc/RCU.py b/pypcc/RCU.py new file mode 100644 index 0000000000000000000000000000000000000000..2c0511a932f9d4796f9cf18ec2c8d1a41ca56d9d --- /dev/null +++ b/pypcc/RCU.py @@ -0,0 +1,348 @@ +from . import Vars +import numpy as np +import logging +from .spibitbang1 import * +import threading + + +def ApplyMask(value,width=8,bitoffset=0,previous=0): + mask=(1<<width)-1 + if bitoffset>0: + value<<=bitoffset; + mask<<=bitoffset; + return (value & mask) + (previous - (previous & mask)); +def UnMask(value,width=8,bitoffset=0): + mask=(1<<width)-1 + if bitoffset>0: + value>>=bitoffset; + value=value&mask; + return value; + +def bytes2int(bts): + x=0; + for b in bts: + x=x*256+b; + return x; +def int2bytes(i): + b=[]; + while i>255: + b=[i%256]+b; + i>>=8; + return [i]+b; + +def strs2bytes(var): +# print("str2bytes",var) + if len(var)==0: return var; + if isinstance(var[0],str): #make string a byte array +# return [ord(c.encode('utf-8')[0]) for s in var for c in s] + return [c.encode('utf-8')[0] for s in var for c in s] + return var + +def bytes2strs(var,step,dtype): + if not(dtype==Vars.datatype.dstring): return var + cnt=int(len(var)/step) + print(var) + return [(bytearray(var[i*step:(i+1)*step]).decode("utf-8")) for i in range(cnt)] + +class RCU1(): + def __init__(self,number,I2Ccallback,Switchcallback): + self.N=number; + self.I2Ccallback=I2Ccallback + self.SWcallback=Switchcallback + self.previous=np.zeros([number,Vars.RCU_storeReg],dtype='int') + + def load(self): + Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_init,0,[]) #Read the current status of GPIO IOs + self.SetVar(Inst1) +#Vars.RCU_mask.OPCW.get_data_value().Value.Value=[1,1,0,0] +#Vars.Ant_mask.OPCW.get_data_value().Value.Value=[1,1,0,0,0,0,0,0,0,0,1,0] + +#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_init,0,[]) #Read the current status of GPIO IOs +#RCU.SetVar(Inst1) + +#Inst1=Vars.Instr(Vars.DevType.Var,Vars.RCU_att,12,[0,1,2,3,4,5,6,7,8,9,11]) +#RCU.SetVar(Inst1) + +#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_off,0,[]) +#RCU.SetVar(Inst1) + +#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.RCU_on,0,[]) +#RCU.SetVar(Inst1) + +#Inst1=Vars.Instr(Vars.DevType.Instr,Vars.ADC1_on,0,[]) +#RCU.SetVar(Inst1) + +#print(Vars.RCU) + + def SetVar(self,Instr,Mask=[]): +# Instr.value=strs2bytes(Instr.value) #Alwast be an array of bytes + if Instr.type==Vars.DevType.Instr: + #Execute instructions + Iset=Instr.dev; + if len(Mask)==0: Mask=Vars.RCU_mask.OPCW.get_data_value().Value.Value + for i in Iset.instr: + logging.debug(str(("Inst",i))) + self.SetVar(i,Mask=Mask) + return; + if Instr.type in [Vars.DevType.I2C,Vars.DevType.SPIbb,Vars.DevType.I2Cbb]: + if len(Mask)==0: Mask=Vars.RCU_mask.OPCW.get_data_value().Value.Value + mask=0; + RCU0=-1; + for RCUi in range(self.N): + if (Mask[RCUi]): + mask|=1<<Vars.RCU_MPaddr.Switch[RCUi] + if RCU0<0: RCU0=RCUi; + if RCU0<0: return; #Mask all zero + self.SWcallback(mask) + if Instr.type==Vars.DevType.I2C: + logging.info(str(('** Set I2C:',Instr.dev,Instr.value))) + self.SetI2C(RCU0,Instr.dev,8,0,strs2bytes(Instr.value)) + return; + elif Instr.type==Vars.DevType.SPIbb: + logging.debug(str(('** Set SPIbb:',Instr.dev,Instr.value))) + SetSPIbb(self.SetI2C,RCU0,Instr.dev,strs2bytes(Instr.value)) + return; + elif Instr.type==Vars.DevType.I2Cbb: + logging.info(str(('** Set I2Cbb:',Instr.dev,Instr.value))) +# self.SetI2C(RCUi,Instr.dev,8,0,strs2bytes(Instr.value)) + return; + V1=Instr.dev + if not((Instr.nvalue==V1.nVars) and (Instr.type==Vars.DevType.VarUpdate)) and not(Instr.nvalue==V1.size*self.N): + logging.error("Wrong size of value") + return False + if V1.Vars[0].type==Vars.DevType.Internal: + Instr.dev.OPCW.get_data_value().Value.Value=Instr.value + logging.debug("Update internal variable") + return +# if V1.Vars[0].type==Vars.DevType.Internal: return; + Step=V1.nVars + Step2=int(V1.size/V1.nVars) + Mask=(Vars.RCU_mask if Step==1 else Vars.Ant_mask) + Mask=Mask.OPCW.get_data_value().Value.Value + value1=strs2bytes(Instr.value) if V1.OPCR is None else strs2bytes(V1.OPCR.get_data_value().Value.Value) + if (len(value1)==V1.nVars) and (self.N>1): value1=(value1*self.N); + if Instr.type==Vars.DevType.Var: + logging.info(str(('** Set Var:',V1.name,value1))) + for RCUi in range(self.N): + for Vari in range(Step): + if not(Mask[RCUi*Step+Vari]): continue + i0=(RCUi*Step+ Vari)*Step2 + i1=(RCUi*Step+(Vari+1))*Step2 + self.SetVarValue(RCUi,V1.Vars[Vari],Instr.value[i0:i1]) + value2=value1[i0:i1] + self.GetVarValue(RCUi,V1.Vars[Vari],value2) + value1[i0:i1]=value2 + if not(V1.OPCR is None): V1.OPCR.get_data_value().Value.Value=bytes2strs(value1,Step2,V1.type) + + elif Instr.type==Vars.DevType.VarUpdate: + self.GetVarValueAll(V1,value1) + if not(V1.OPCR is None): V1.OPCR.get_data_value().Value.Value=bytes2strs(value1,Step2,V1.type) +# V1.OPCR.get_data_value().Value.Value=value1 + + logging.info(str(('** Readback:',V1.name,value1))) + + def GetVarValue(self,RCUi,var,value): + logging.info(str(("RCU1 Get ",RCUi,var,value))) + if var.type==Vars.DevType.I2C: + self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi]) + self.GetI2C(RCUi,var.devreg,var.width,var.bitoffset,value) + elif var.type==Vars.DevType.I2Cbb: + logging.error("I2Cbb Implemented") + elif var.type==Vars.DevType.SPIbb: + logging.error("SPIbb Implemented") + else: + logging.error("Not Implemented") + + def GetVarValueAll(self,V1,value1): + mask=0; + for RCUi in range(self.N): + mask|=1<<Vars.RCU_MPaddr.Switch[RCUi] + Step=V1.nVars + Step2=int(V1.size/V1.nVars) + if V1.Vars[0].type==Vars.DevType.I2C: + for Vari in range(Step): + DevReg=V1.Vars[Vari].devreg + self.SWcallback(mask) + self.SetI2CAddr(self,DevReg) + if DevReg.Register_R>255: self.I2Ccallback(DevReg.Addr,[250],read=3) #Wait for ADC + for RCUi in range(self.N): + self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi]) + i0=(RCUi*Step+ Vari)*Step2 + i1=(RCUi*Step+(Vari+1))*Step2 + value2=value1[i0:i1] + var=V1.Vars[Vari] +# print(Step,Step2,i0,i1,value2,len(value1)) + self.GetI2Cnoreg(RCUi,var.devreg,var.width,var.bitoffset,value2) +# print(value2) + if (var.Scale!=0): value2[0]*=var.Scale; + value1[i0:i1]=value2 + elif V1.Vars[0].type==Vars.DevType.SPIbb: + self.GetBBValueAll(V1,value1,mask) +# logging.info("SPIbb all not implemented yet") + else: + logging.error("Type not implemented") +# print(value1) + def GetBBValueAll(self,V1,value1,mask): + def SetBit(RCUi,dev,width,bitoffset,value,buffer=False): + if not(buffer): self.SWcallback(mask) + self.SetI2C(RCUi,dev,width,bitoffset,value,buffer=buffer) + def GetBit(RCUixx,dev,width,bitoffset,buffer=False): + value=[0 for RCUi in range(self.N)] + value2=[0] + if buffer: + for RCUi in range(self.N): + self.GetI2Cbuffer(RCUi,dev,width,bitoffset,value2) + value[RCUi]=value2[0] + return value + self.SWcallback(mask) + self.SetI2CAddr(self,dev) + for RCUi in range(self.N): + self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi]) + #for i in range(len(value2)): value2[i]*=0; + value2[0]=0 + self.GetI2Cnoreg(RCUi,dev,width,bitoffset,value2) + value[RCUi]=value2[0] + return value; + devs=[V1.Vars[Vari].devreg for Vari in range(V1.nVars)] + GetSPIbb2(SetBit,GetBit,0,devs,value1) + + + def SetVarValue(self,RCUi,var,value): + if var.devreg.Register_W==-1: return True; #We can not set it, only read it e.g. temperature + logging.debug(str(("RCU1 Set ",RCUi,var,value))) + if var.type==Vars.DevType.I2C: + self.SWcallback(1<<Vars.RCU_MPaddr.Switch[RCUi]) + self.SetI2C(RCUi,var.devreg,var.width,var.bitoffset,value) + elif var.type==Vars.DevType.I2Cbb: + logging.error("I2Cbb Implemented") + elif var.type==Vars.DevType.SPIbb: + logging.error("SPIbb Implemented") + else: + logging.error("Not Implemented") + + def SetI2C(self,RCUi,dev,width,bitoffset,value,buffer=False): + if dev.store>0: + previous=self.previous[RCUi,dev.store-1]; + value[0]=ApplyMask(value[0],width,bitoffset,previous); + self.previous[RCUi,dev.store-1]=value[0] +# logging.debug(str(('masked to',value))) +# logging.debug(str(("Store buffer",RCUi,dev.store,value[0]))) + if buffer: return True; + return self.I2Ccallback(dev.Addr,value,reg=dev.Register_W) + + def GetI2Cbuffer(self,RCUi,dev,width,bitoffset,value): + if not(dev.store>0): return False; + value[0]=self.previous[RCUi,dev.store-1]; +# logging.debug(str(("GetI2Cbuffer",RCUi,dev.store,value))) + l1=int(np.floor((width+bitoffset+7)/8)) + if (width!=l1*8) or (bitoffset>0): + for i in range(len(value)): + value[i]=UnMask(value[i],width,bitoffset) + return True + + def GetI2C(self,RCUi,dev,width,bitoffset,value): +# if dev.store>0: +# value[0]=self.previous[RCUi,dev.store-1] +# return True + l1=int(np.floor((width+bitoffset+7)/8)) +# print(width,bitoffset,l1) + makesinglevalue=((len(value)==1) and (l1>1)); + if makesinglevalue: value2=[0 for x in range(l1)] + else: value2=value + reg=dev.Register_R + if reg>255: #This is for the monitor ADC + if not(self.I2Ccallback(dev.Addr,int2bytes(reg),read=2)): return False; + I2Ccallback(Addr,[250],read=3) + if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False; + else: + if not(self.I2Ccallback(dev.Addr,value2,reg=reg,read=1)): return False; + if value2[0] is None: return False + if makesinglevalue: value[0]=bytes2int(value2) + else: value[:]=value2[:]; + if dev.store>0: + self.previous[RCUi,dev.store-1]=value[0] +# logging.debug(str(("Store buffer",RCUi,dev.store,value[0]))) + if (width!=l1*8) or (bitoffset>0): + for i in range(len(value)): + value[i]=UnMask(value[i],width,bitoffset) + else: value[0]=value2[0] + return True; + def GetI2Cbit(self,RCUi,dev,pin): + value2=[value] + self.I2CGet(RCUi,dev,1,1<<pin,value2) + return value2[0] + + + def SetI2CAddr(self,RCUi,dev): + return self.I2Ccallback(dev.Addr,int2bytes(dev.Register_R),read=2) + + + + def GetI2Cnoreg(self,RCUi,dev,width,bitoffset,value): + #print(width,len(value)) + l1=int(np.floor((width+bitoffset+7)/8)) + makesinglevalue=((len(value)==1) and (l1>1)); + if makesinglevalue: value2=[0 for x in range(l1)] + else: value2=value + reg=dev.Register_R + if not(self.I2Ccallback(dev.Addr,value2,read=1)): return False; + if value2[0] is None: return False + if makesinglevalue: value[0]=bytes2int(value2) + else: value[:]=value2[:]; + if dev.store>0: + self.previous[RCUi,dev.store-1]=value[0] +# logging.debug(str(("Store buffer",RCUi,dev.store,value[0]))) +# if width<8: + if (width!=l1*8) or (bitoffset>0): + for i in range(len(value)): + value[i]=UnMask(value[i],width,bitoffset) +# value[0]=UnMask(value[0],width,bitoffset) + #else: value[0]=value2[0] + #if (len(value)>1) and (width<8): print value + return True; + + def start(self,Q1): + def RCUthread(Q1): + while True: + item = Q1.get() + if item is None: break; + self.SetVar(item) + logging.info("End RCU thread") + + RCUthread1 = threading.Thread(target=RCUthread, args=(Q1,)) + RCUthread1.start() + + return RCUthread1 + + def Queue_Monitor(self,Q1): + Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_temp,32,[0]*32) + Q1.put(Inst1) +# Inst1=Vars.Instr(Vars.DevType.VarUpdate,Vars.RCU_ADC_lock,96,[0]*96) +# Q1.put(Inst1) + + def AddVars(self,Q1,AddVarR,AddVarW): + for v in Vars.OPC_devvars: + dim1=Vars.RCU_MPaddr.nI2C*Vars.RCU_MPaddr.nSwitch*v.nVars + dim2=Vars.RCU_MPaddr.nI2C*Vars.RCU_MPaddr.nSwitch*v.size + dim3=int(v.size/v.nVars) + #print(v.name,dim) + varvalue2=0 + if v.type==Vars.datatype.dInt: varvalue2=dim2*[0] + elif v.type==Vars.datatype.dfloat: varvalue2=dim2*[0.0] + elif v.type==Vars.datatype.dstring: varvalue2=dim1*[" "*dim3] + print(len(varvalue2),varvalue2) + if v.RW in [Vars.RW.ReadOnly,Vars.RW.ReadWrite]: + var1=AddVarR(v.name+"_R",varvalue2,v) +# print(len(varvalue1),len(varvalue2),v.size,dim2) + v.OPCR=var1 + Inst=Vars.Instr(Vars.DevType.VarUpdate,v,dim2,varvalue2) + Q1.put(Inst) + + if v.RW in [Vars.RW.WriteOnly,Vars.RW.ReadWrite]: + var1=AddVarW(v.name+"_RW",varvalue2,v,Q1) + v.OPCW=var1 + + def AddMethod(self,Q1,Addmethod): + for v in Vars.OPC_methods: + Inst1=Vars.Instr(Vars.DevType.Instr,v,0,[]) + Addmethod(v.name,Inst1,Q1) diff --git a/pypcc/i2cserv.py b/pypcc/i2cserv.py new file mode 100644 index 0000000000000000000000000000000000000000..2867c7cb98b1af6103cfb0bbbdf6f3c6e80acdbe --- /dev/null +++ b/pypcc/i2cserv.py @@ -0,0 +1,50 @@ + +import capnp +import pypcc_capnp as pp +import os +import select; + + +class i2cserv(): + def __init__(self,name='RCU'): + self.name=name; + print("Try to connecting to "+name) + self.Output=os.open('../serv_to_'+name,os.O_WRONLY ) #Wait for other side ... + self.Input=open('../'+name+'_to_serv','rb' ) + capnp.TwoPartyClient(self.Input) + print("Connected") + self.poll=select.poll(); + self.poll.register(self.Input.fileno(),select.POLLIN) + self.message_iterator=iter(pp.OPCUAset.read_multiple_packed(self.Input)) + + def __del__(self): + print("Disconnecting") + os.close(self.Output) + self.Input.close() + + def readvar(self,id): + Set=pp.OPCUAset.new_message(id=id,type=pp.InstType.varRead) + Data=Set.to_bytes_packed() + print('Send readvar, len=',len(Data)) + os.write(self.Output,Data) + + def setvar(self,id,data=[],mask=[]): + Set=pp.OPCUAset.new_message(id=id,type=pp.InstType.varSet,data=data,mask=mask) #set_led + Data=Set.to_bytes_packed() + print('Send setvar, len=',len(Data)) + os.write(self.Output,Data) + + def callmethod(self,id,mask=[]): + Set=pp.OPCUAset.new_message(id=id,type=pp.InstType.method,mask=mask) #set_led + Data=Set.to_bytes_packed() + print('Send method, lenmask=',len(mask)) + os.write(self.Output,Data) + + def data_waiting(self): + return (self.Input.fileno(),select.POLLIN) in self.poll.poll(100) + + def readdata(self): + message=next(self.message_iterator) + return message.id,message.data,message.mask + + diff --git a/opcuaserv.py b/pypcc/opcuaserv.py similarity index 90% rename from opcuaserv.py rename to pypcc/opcuaserv.py index f38b8acb5a4ced13f3e49bb6d45c1897de1de520..daa3cddd032508c6300deadce94409c870336b38 100644 --- a/opcuaserv.py +++ b/pypcc/opcuaserv.py @@ -8,7 +8,7 @@ from datetime import datetime; import logging #import Vars #import HWconf -from pcctypes import * +#from pcctypes import * Vars_R={} Vars_W={} @@ -21,14 +21,15 @@ class SubHandler(object): def datachange_notification(self, node, val, data): # print("Python: New data change event", node, val,data) if not(running): return - vname,myvar,VarD,Q1=Vars_W[node.nodeid.Identifier] + vname,myvar,v,reader=Vars_W[node.nodeid.Identifier] # val=(val if isinstance(val, list) else [val] ) logging.info(str(("Datachange callback",vname,val))) # myvar2.Value.Value=val # myvar2.SourceTimestamp = datetime.utcnow() + reader.setvar(v,val) - Inst=Instr(DevType.Var,VarD,len(val),val) - Q1.put(Inst) +# Inst=Instr(DevType.Var,VarD,len(val),val) +# Q1.put(Inst) # P1.SetVarValue(vname,val) #readback # if True: @@ -46,7 +47,7 @@ class SubHandler(object): def CallMethod(ObjectID,name,Inst1,Q1): logging.info(str(("Callmethod",ObjectID,name))) # Inst1=Vars.Instr(Vars.DevType.Instr,instrs,0,[]) - Q1.put(Inst1) + Q1.callMethod(Inst1) # P1.CallMethod(name,None) @@ -58,18 +59,17 @@ def AddVar(name,value): def AddVarR(vname,varvalue2,v): myvar = PCCobj.add_variable(idx, vname, varvalue2) logging.info(str(("Variable added: ",vname,len(varvalue2)))) - Vars_R[myvar.nodeid.Identifier]=[v.name,myvar.get_data_value(),varvalue2,v] + Vars_R[myvar.nodeid.Identifier]=[vname,myvar.get_data_value(),varvalue2,v] return myvar def AddVarW(vname,varvalue2,v,Q1): logging.info(str(("Variable added: ",vname)))#,'=',varvalue2) myvar2 = PCCobj.add_variable(idx, vname, varvalue2) myvar2.set_writable() - Vars_W[myvar2.nodeid.Identifier]=[v.name,myvar2.get_data_value(),v,Q1] + Vars_W[myvar2.nodeid.Identifier]=[vname,myvar2.get_data_value(),v,Q1] handle = sub.subscribe_data_change(myvar2) return myvar2 - def Addmethod(vname,v,Q1): myvar = PCCobj.add_method(idx, vname, lambda ObjectId,name=vname,inst=v,Q1=Q1 : CallMethod(ObjectId,name,inst,Q1), [],[] ) logging.info(str(("AddMethod:",vname))) diff --git a/pypcc/pypcc.capnp b/pypcc/pypcc.capnp new file mode 100644 index 0000000000000000000000000000000000000000..8486fe7b70647b2988d05590248ca69d6ff89573 --- /dev/null +++ b/pypcc/pypcc.capnp @@ -0,0 +1,14 @@ +@0x9f2c99de8c7edd7f; + +enum InstType { + varSet @0; + varRead @1; + method @2; +} + +struct OPCUAset { + id @0: UInt8; + type @1: InstType; + data @2: List(UInt8); + mask @3: List(Bool); +} diff --git a/pypcc2.py b/pypcc/pypcc3.py similarity index 62% rename from pypcc2.py rename to pypcc/pypcc3.py index 9907c49deb224044a780d1129cb57f5b7c6bbf56..906e5e7be22a4af3eb2c4fdfb756301780e7b9cd 100644 --- a/pypcc2.py +++ b/pypcc/pypcc3.py @@ -3,9 +3,6 @@ try: import queue except ImportError: import Queue as queue; -from rcu import RCU -from clk import CLK -from i2c import I2Cswitch1 import threading import signal import sys @@ -13,9 +10,11 @@ import time #import Vars import logging import argparse +import i2cserv +import yamlreader parser = argparse.ArgumentParser() -parser.add_argument("-s", "--simulator", help="Do not connect to I2c, but simulate behaviour.", action="store_true") +#parser.add_argument("-s", "--simulator", help="Do not connect to I2c, but simulate behaviour.", action="store_true") parser.add_argument("-p", "--port", help="Port number to listen on [%(default)s].", type=int, default=4842) parser.add_argument("-l", "--loglevel", help="Log level [%(default)s].", type=str, choices=["DEBUG","INFO","WARNING","ERROR"], default="INFO") args = parser.parse_args() @@ -27,31 +26,27 @@ if not isinstance(loglevel_nr, int): #logging.basicConfig(level=loglevel_nr, format="%(asctime)s [%(levelname)8s] %(message)s") logging.basicConfig(level=loglevel_nr,format='%(asctime)s [%(levelname)-8s,%(filename)-20s:%(lineno)-3d] %(message)s') -if args.simulator: - from i2c import I2C_dummy as I2C -else: - from i2c import I2C #Queue used to pass instructions from opc-ua server to RCU -Q1=queue.Queue() #RCUs -Q2=queue.Queue() #CLK +#Q1=queue.Queue() #RCUs +#Q2=queue.Queue() #CLK #Setup OPCUA server (running in its own thread) opcuaserv.InitServer(port=args.port) logging.info("OPC-UA Server started") -SW1=I2Cswitch1.I2Cswitch1(I2C.I2C1server) -SW0=I2Cswitch1.I2Cswitch0(I2C.I2C2server) #Dummy switch as their is no switch on LTS +#SW1=I2Cswitch1.I2Cswitch1(I2C.I2C1server) +RCU_I2C=i2cserv.i2cserv() +RCU_conf=yamlreader.yamlreader(RCU_I2C,yamlfile='RCU') +#RCU=RCU.RCU1(32,I2C.I2C1server,SW1.SetChannel) +RCU_conf.AddVars(opcuaserv.AddVarR,opcuaserv.AddVarW) +RCU_conf.AddMethod(opcuaserv.Addmethod) +#RCU.load() #Load current register values from HW -RCU=RCU.RCU1(32,I2C.I2C1server,SW1.SetChannel) -RCU.AddVars(Q1,opcuaserv.AddVarR,opcuaserv.AddVarW) -RCU.AddMethod(Q1,opcuaserv.Addmethod) -RCU.load() #Load current register values from HW - -CLK=CLK.RCU1(1,I2C.I2C2server,SW0.SetChannel) -CLK.AddVars(Q2,opcuaserv.AddVarR,opcuaserv.AddVarW) -CLK.AddMethod(Q2,opcuaserv.Addmethod) -CLK.load() #Load current register values from HW +#CLK=CLK.RCU1(1,I2C.I2C1server,SW1.SetChannel) +#CLK.AddVars(Q2,opcuaserv.AddVarR,opcuaserv.AddVarW) +#CLK.AddMethod(Q2,opcuaserv.Addmethod) +#CLK.load() #Load current register values from HW #logging.debug(str(("I2C bytes=",I2C.I2Ccounter))) @@ -59,11 +54,11 @@ if False: opcuaserv.server.stop() exit() -RCUthread1=RCU.start(Q1) -CLKthread1=CLK.start(Q2) +#RCUthread1=RCU.start(Q1) +#CLKthread1=CLK.start(Q2) RunTimer=True; -def TimerThread(Q1,RCU): +def TimerThread(RCU_I2C,RCU_conf): V1=opcuaserv.AddVar("RCU_monitor_rate_RW",30) cnt=0;#Count second ticks while RunTimer: @@ -73,21 +68,21 @@ def TimerThread(Q1,RCU): continue; cnt+=1; if cnt>=T1: - if Q1.qsize()>3: continue; + # if Q1.qsize()>3: continue; cnt=0; - logging.debug(str(("I2C bytes=",I2C.I2Ccounter," Qlength=",Q1.qsize()))) - RCU.Queue_Monitor(Q1) + # logging.debug(str(("I2C bytes=",I2C.I2Ccounter," Qlength=",Q1.qsize()))) + # RCU.Queue_Monitor(Q1) logging.info("End Timer thread") -Timerthread1 = threading.Thread(target=TimerThread, args=(Q1,RCU)) +Timerthread1 = threading.Thread(target=TimerThread, args=(RCU_I2C,RCU_conf)) Timerthread1.start() # on SIGINT: stop thread(s) by adding None to instruction queue(s) def signal_handler(sig, frame): logging.info('Stop RCU thread') - Q1.put(None) - Q2.put(None) +# Q1.put(None) +# Q2.put(None) logging.info('Stop timer thread') global RunTimer; RunTimer=False @@ -99,10 +94,12 @@ opcuaserv.start() try: #Do nothing. while RunTimer: - time.sleep(1) +# time.sleep(0.01) + RCU_conf.getvar(); + finally: logging.info("Stop OPC-UA server") opcuaserv.server.stop() - RCUthread1.join() +# RCUthread1.join() # CLKthread1.join() Timerthread1.join() diff --git a/pypcc/test1.py b/pypcc/test1.py new file mode 100644 index 0000000000000000000000000000000000000000..2470a7fc27ff1746d24d8c04c033fe207b11b8be --- /dev/null +++ b/pypcc/test1.py @@ -0,0 +1,82 @@ + +# coding: utf-8 + +# In[1]: + + +import capnp +import pypcc_capnp as pp +import os + + +# In[2]: + + +data=[0]*32; +mask=[False]*32; +mask[0]=True; +Set=pp.OPCUAset.new_message(id=4,type=pp.InstType.varSet,data=data,mask=mask) #set_led + + +# In[3]: + + +print(Set) +Data=Set.to_bytes_packed() +#Data=Set.to_bytes() +print(Data) + + +# In[4]: + + +Output=os.open('../serv_to_RCU',os.O_WRONLY ) #Wait for other side ... +Input=open('../RCU_to_serv','rb' ) + + +# In[11]: + + +os.write(Output,Data) +os.write(Output,Data) + + +# In[6]: + + +print(Input,Input.fileno()) + + +# In[7]: + + +import select; +poll=select.poll(); +poll.register(Input.fileno(),select.POLLIN) + + +# In[8]: + + +#pp.OPCUAset.` +message_iterator=iter(pp.OPCUAset.read_multiple_packed(Input)) + + +# In[12]: + + +while (Input.fileno(),select.POLLIN) in poll.poll(100): +# message=pp.OPCUAset.read_packed(Input) + message=next(message_iterator) + print("read!",message) +# message=pp.OPCUAset.read_packed(Input) +# print("read!") + + +# In[13]: + + +os.close(Output) +Input.close() +#Input.close() + diff --git a/pypcc/yamlreader.py b/pypcc/yamlreader.py new file mode 100644 index 0000000000000000000000000000000000000000..815e5d53e935eb9bff9b20f8dc540eb903fef937 --- /dev/null +++ b/pypcc/yamlreader.py @@ -0,0 +1,185 @@ +import yaml +import struct +def Find(L,name,value): + for x in L: + if x[name]==value: + return x; + return False; + +def bytes2int(bts): + x=0; + for b in bts: + x=x*256+b; + return x; + +def int2bytes(i): + b=[]; + while i>255: + b=[i%256]+b; + i>>=8; + return [i]+b; + + +class yamlreader(): + def __init__(self,i2cserver,yamlfile='RCU'): + self.conf=yaml.load(open("../src/apsctl/"+yamlfile+'.yaml')) + for i,v in enumerate(self.conf['variables']): + v['id']=i + for i,v in enumerate(self.conf['methods']): + v['id']=i + self.server=i2cserver; + + + def AddVars(self,AddVarR,AddVarW): + for v in self.conf['variables']: + print(v) + dim1=v.get('dim',1); + name=v.get('name'); + datatype=v.get('dtype','integer') +# dim1=Vars.RCU_MPaddr.nI2C*Vars.RCU_MPaddr.nSwitch*v.nVars +# dim2=Vars.RCU_MPaddr.nI2C*Vars.RCU_MPaddr.nSwitch*v.size +# dim3=int(v.size/v.nVars) + #print(v.name,dim) + varvalue2=0 + if datatype in ['uint8','uint16','uint32','uint64']: varvalue2=dim1*[0] + elif datatype=='double': varvalue2=dim1*[0.0] + elif datatype=='boolean': varvalue2=dim1*[False] + elif datatype=='string': varvalue2=dim1*[""] +# print(len(varvalue2),varvalue2) + if v.get('rw') in ['ro','rw']: + var1=AddVarR(name+"_R",varvalue2,v['id']) + v['OPCR']=var1 + print("Var added:"+name+"_R") + self.server.readvar(v['id']) +# Inst=Vars.Instr(Vars.DevType.VarUpdate,v,dim2,varvalue2) +# Q1.put(Inst) + + if v.get('rw') in ['wo','rw','variable']: + var1=AddVarW(name+"_RW",varvalue2,v['id'],self) + v['OPCW']=var1 + print("Var added:"+name+"_RW") + for v in self.conf['variables']: + mask=v.get('mask'); + if not(mask): continue; + mask=Find(self.conf['variables'],'name',mask) + if not(mask): continue; + mask=mask.get('OPCW',None) + if (mask==None): continue; + v['maskOPC']=mask + + def AddMethod(self,Addmethod): + for v in self.conf['methods']: + if v.get('rw','')=='hidden': continue; + print(v) +# Inst1=Vars.Instr(Vars.DevType.Instr,v,0,[]) + Addmethod(v['name'],v['id'],self) + mask=v.get('mask'); + if not(mask): continue; + mask=Find(self.conf['variables'],'name',mask) + if not(mask): continue; + mask=mask.get('OPCW',None) + if (mask==None): continue; + v['maskOPC']=mask + + def callMethod(self,id): + v=self.conf['methods'][id]; + print("Method called!",v['name']) + mask=v.get('maskOPC',None); + mask=mask.get_value() if (mask!=None) else []; + self.server.callmethod(id,mask) + + def setvar(self,id,data=[]): + v=self.conf['variables'][id]; + if v['rw']=='variable': return; + mask=v.get('maskOPC',None); + mask=mask.get_value() if (mask!=None) else []; + print("M2:",mask) + dtype=v.get('dtype','integer'); + width=(v.get('width',8)-1)//8+1 + if (dtype=="float"): + scale=v.get('scale',1.) + data=[int(d/scale) for d in data] + if (dtype=="boolean"): + data2=bytearray(data*1); + elif (dtype in ['uint8','uint16','uint32','uint64','double']): + if width<=1: + data2=bytearray(data) + elif width==2: + data2 = struct.pack('>%sH' % len(data), *data) + elif width==3: + data2=bytearray() + for a in data: data2.extend(struct.pack('>L',a)[1:]) + elif width==4: + data2 = struct.pack('>%sL' % len(data), *data) + elif width==8: + data2 = struct.pack('>%sQ' % len(data), *data) + else: + print("setvar",v['name']," unsupported width!",width) + return; + elif (dtype=="string"): + data2=bytearray() + for s in data: + data2.extend('{s:>{width}'.format(s=s[:width],width=width).encode('ascii')); + else: + print("setvar unsupported type"); + return; + data2=[d for d in data2] + print("setvar ",v['name'],data2,mask); + self.server.setvar(id,data2,mask) + + def getvar(self): + if not(self.server.data_waiting()): return; + print("getvar ...") + while True: + try: + id,data,mask=self.server.readdata(); + print("**getvar",id,data,mask); + if len(data)==0: continue; + except: + print('finished') + return; + self.OPCset(id,data,mask); + + def OPCset(self,id,data,mask): + v=self.conf['variables'][id]; + dtype=v.get('dtype','integer'); + width=(v.get('width',8)-1)//8+1 + print("OPCset",width,data) + if dtype=="boolean": + data2=[d==1 for d in data]; + elif (dtype in ['uint8','uint16','uint32','uint64','double']): + data=bytearray(data) + if width<=1: + data2=[d for d in data] + elif width==2: + data2 = struct.unpack('>%sH' % len(data), data) + elif width==3: + data2 = [struct.unpack('>L' ,bytearray([0])+data[x*3:x*3+3])[0] for x in range(len(data)//3)] + elif width==4: + data2 = struct.unpack('>%sL' % len(data), data) + elif width==8: + data2 = struct.unpack('>%sQ' % len(data), data) + else: + print("OPCset",v['name']," unsupported width!",width) + return; + elif dtype=="string": + cnt=int(len(data)/width) + data2=[(bytearray(data[i*width:(i+1)*width]).decode("utf-8")) for i in range(cnt)] + else: + print("OPCset unsupported type"); + return; + if dtype=="float": + scale=float(v.get('scale',1.)) + data2=[(d*scale) for d in data2] + data3=v['OPCR'].get_value(); +# print("OPCset",v['name'],data3,mask) + if mask: #Only update masked values + step=len(data2)//len(mask) + print("mask step=",step) + for i in range(len(data2)): + if mask[i//step]: data3[i]=data2[i] + else: + data3=data2; + print("OPCset",v['name'],data3) + v['OPCR'].set_value(data3); + diff --git a/requirements.txt b/requirements.txt index a60ca7ecbd7bfebc36f787dd6425b771587835b1..e503c85dbfbb6c97a126e513ebc82bc3ba8264cf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -git+https://github.com/amaork/libi2c.git; platform_system == "linux" opcua numpy -recordclass +pycapnp +capnp diff --git a/run.sh b/run.sh new file mode 100644 index 0000000000000000000000000000000000000000..64c418f2dfae847bea63c38072043cc9a9e33681 --- /dev/null +++ b/run.sh @@ -0,0 +1,12 @@ +#Make fifo buffers +rm RCU_to_serv +rm serv_to_RCU +mkfifo RCU_to_serv +mkfifo serv_to_RCU + +#Run I2C controller +./output/main >log1.txt 2>log2.txt & + +#Run OPC-UA server +cd pypcc +python3 pypcc3.py \ No newline at end of file diff --git a/scripts/ADCreset.py b/scripts/ADCreset.py index b0f208abaf03277f350b210cc2ee279566f3c96a..561b6e6dcff36af5f9bb7f02507e39d60c429efa 100644 --- a/scripts/ADCreset.py +++ b/scripts/ADCreset.py @@ -3,11 +3,11 @@ from test_common import * RCUs=[0]; setRCUmask(RCUs) -callmethod("RCU_off") -time.sleep(1) +#callmethod("RCU_off") +#time.sleep(1) callmethod("RCU_on") -callmethod("RCU_on") -time.sleep(1) -callmethod("ADC_on") +#callmethod("RCU_on") +#time.sleep(1) +#callmethod("ADC_on") disconnect(); diff --git a/scripts/Att.py b/scripts/Att.py index 6e5d7b14ec651ce3f809a7a380db6e671faff67c..174e126f3adce597ce62c002bcabbc909c4d3eee 100644 --- a/scripts/Att.py +++ b/scripts/Att.py @@ -1,26 +1,19 @@ from test_common import * name="RCU_attenuator" -RCU=0; -Att=[5,5,5] +RCU=1; +Att=[1,2,2] - -#setAntmask([RCU]) +setAntmask([RCU]) att=get_value(name+"_R") -val=att.Value.Value -print("Att old:",val) -#print("Att old:",att[3*RCU:3*RCU+3]) +print("Att old:",att[3*RCU:3*RCU+3]) -val[3*RCU:3*RCU+3]=Att -att.Value.Value=val -print("Att set:",val) -#att[3*RCU]+=1 +att[3*RCU:3*RCU+3]=Att set_value(name+"_RW",att) time.sleep(0.5) att=get_value(name+"_R") -print("Att new:",att.Value.Value) -#print("Att new:",att[3*RCU:3*RCU+3]) +print("Att new:",att[3*RCU:3*RCU+3]) disconnect() \ No newline at end of file diff --git a/scripts/LED.py b/scripts/LED.py index d1857ae8879599d05c32afecce64f161f5cba1ea..b2c7f906374f635b85733958259544b11f0fa688 100644 --- a/scripts/LED.py +++ b/scripts/LED.py @@ -1,18 +1,18 @@ from test_common import * name="RCU_LED0" -RCU=1; -LEDvalue="on"; +RCU=3; +LEDvalue=True; setRCUmask([RCU]) -#exit() + led=get_value(name+"_R") print("LED old:",led) led[RCU]=LEDvalue -print("LED changed:",led) - +#led[0]=False; +print("LED set:",led) set_value(name+"_RW",led) -time.sleep(0.1) +time.sleep(0.5) print("LED new:",get_value(name+"_R")) diff --git a/scripts/test1.py b/scripts/test1.py deleted file mode 100644 index a691a74530fd5645c34f885bb2fcc5b59e8a2355..0000000000000000000000000000000000000000 --- a/scripts/test1.py +++ /dev/null @@ -1,23 +0,0 @@ -from test_common import * - -name="RCU_LED0_RW" -#RCU=0; -#LEDvalue=0; - -#setRCUmask([RCU]) - -A=get_value(name) -print(A) -#A[0]=1.; -A[0]='on'; -print(A) -set_value(name,A) -#print("LED old:",led) -#led[RCU]=LEDvalue - -#set_value(name+"_RW",led) -#time.sleep(0.1) - -#print("LED new:",get_value(name+"_R")) - -disconnect() diff --git a/scripts/test_common.py b/scripts/test_common.py index f9e5b4273446be810256f18409c13ae1be6de240..a612569fc7c8f972fe05f26faaf48694ce2ece4e 100644 --- a/scripts/test_common.py +++ b/scripts/test_common.py @@ -1,5 +1,4 @@ -#Address="opc.tcp://odroidRCU2:4842/" -Address="opc.tcp://dop444:4840/" +Address="opc.tcp://localhost:4842/" #Address="opc.tcp://ltspi:4842/" import sys sys.path.insert(0, "..") @@ -28,13 +27,11 @@ def disconnect(): def get_value(name): var1 = root.get_child(["0:Objects", "2:PCC", "2:"+name]) -# return var1.get_value() - return var1.get_data_value() + return var1.get_value() def set_value(name,value): var1 = root.get_child(["0:Objects", "2:PCC", "2:"+name]) var1.set_value(value) -# var1.set_data_value(value,7) def setRCUmask(rcu=[]): name="RCU_mask_RW" @@ -42,7 +39,6 @@ def setRCUmask(rcu=[]): print(name," old:",M) M=[False for m in M] for r in rcu: -# M[r]=1 M[r]=True set_value(name,M) print(name," new:",get_value(name)) diff --git a/src/apsctl.schema.json b/src/apsctl.schema.json new file mode 100644 index 0000000000000000000000000000000000000000..07c6b82a4866a48c4d4f4b3166af321404950a95 --- /dev/null +++ b/src/apsctl.schema.json @@ -0,0 +1,83 @@ +{ + "$id": "http://git.astron.nl/lofar2.0/pypcc/apsctl.schema.json", + "$schema": "http://json-schema.org/draft-07/schema", + "title": "apsctl", + "description": "APSCTL yaml schema", + "type" : "object", + "properties": { + "version": {"type":"string"}, + "description":{"type":"string"}, + "drivers": { "type":"array", "items": { "$ref": "#/$defs/drivers"}}, + "device_registers":{ "type":"array", "items": { "$ref": "#/$defs/dev_regs"}}, + "variables":{ "type":"array", "items": { "$ref": "#/$defs/variables"}}, + "methods":{ "type":"array", "items": { "$ref": "#/$defs/methods"}} + }, + "additionalProperties" : false, + "$defs":{ + "drivers" : { + "type" : "object", + "properties": { + "name" : {"type":"string"}, + "type" : {"enum":["i2c","RCU_switch","UNB2_switch","i2c_devs","i2c_array","i2c_array2","hba1","i2cbitbang1","spibitbang1","spibitbang2"]}, + "parent" : {"type":"string"}, + "parameters" : {"type":"array","items":{"type":"integer"}} , + "devreg" : {"type":"array","items":{"type":"string"}} + }, + "additionalProperties" : false + }, + "dev_regs" : { + "type" : "object", + "properties": { + "name" : {"type":"string"}, + "dim" : {"type":"integer"}, + "description" : {}, + "address" : {"anyOf":[{"type":"integer"},{"type":"array","items":{"type":"integer"}}]}, + "device" : {}, + "driver" : {}, + "registers":{ "type":"array", "items": { "$ref": "#/$defs/registers"}} + }, + "additionalProperties" : false + }, + "registers" : { + "type" : "object", + "properties": { + "name" : {"type":"string"}, + "description" : {"type":"string"}, + "address" : {}, + "store" : {"type":"boolean"} + }, + "additionalProperties" : false + }, + "variables" : { + "type" : "object", + "properties": { + "name" : {"type":"string"}, + "description" : {"type":"string"}, + "dim" : {"type":"integer"}, + "dtype" : {"enum":["uint64","uint32","uint16","uint8","double","boolean","string"]}, + "driver" : {"type":"string"}, + "rw" : {"enum":["variable","rw","ro","hidden"]}, + "scale" : {"type":"number"}, + "bitoffset" : {}, + "width" : {"type":"integer"}, + "devreg" : {}, + "mask" : {"type":"string"} + }, + "additionalProperties" : false + }, + "methods" : { + "type" : "object", + "properties": { + "name" : {"type":"string"}, + "mask" : {"type":"string"}, + "instructions" : {"type":"array"}, + "rw" : {"enum":["visible","hidden"]} + }, + "additionalProperties" : false + } + + } + +} + + diff --git a/src/apsctl/CLK.h b/src/apsctl/CLK.h new file mode 100644 index 0000000000000000000000000000000000000000..488c488a49ccd9c6927ad4528a771f6160b5e9c7 --- /dev/null +++ b/src/apsctl/CLK.h @@ -0,0 +1,26 @@ +/*** Device Register Definitions ***/ +const t_devreg IO1_CONF1 {.address=32,.register_R=6,.register_W=6,.store=1,.driver=1}; +const t_devreg IO1_CONF2 {.address=32,.register_R=7,.register_W=7,.store=2,.driver=1}; +const t_devreg IO1_GPIO1 {.address=32,.register_R=0,.register_W=2,.store=3,.driver=1}; +const t_devreg IO1_GPIO2 {.address=32,.register_R=1,.register_W=3,.store=4,.driver=1}; +const t_devreg IO2_CONF1 {.address=32,.register_R=6,.register_W=6,.store=5,.driver=1}; +const t_devreg IO2_CONF2 {.address=32,.register_R=7,.register_W=7,.store=6,.driver=1}; +const t_devreg IO2_GPIO1 {.address=32,.register_R=0,.register_W=2,.store=7,.driver=1}; +const t_devreg IO2_GPIO2 {.address=32,.register_R=1,.register_W=3,.store=8,.driver=1}; +const t_devreg IO3_CONF1 {.address=32,.register_R=6,.register_W=6,.store=9,.driver=1}; +const t_devreg IO3_CONF2 {.address=32,.register_R=7,.register_W=7,.store=10,.driver=1}; +const t_devreg IO3_GPIO1 {.address=32,.register_R=0,.register_W=2,.store=11,.driver=1}; +const t_devreg IO3_GPIO2 {.address=32,.register_R=1,.register_W=3,.store=12,.driver=1}; +const t_devreg PLL_PLL_stat {.address=0,.register_R=0,.register_W=0,.store=0,.driver=2}; +#define NumberStoreReg 12 +/*** Variable Definitions ***/ +const t_variable CLK_IGNORE {.name="CLK_IGNORE",.dim=1,.dtype=dt_boolean,.driver=1,.rw=rw_variable,.bitoffset={0,0,0},.width=8,.scale=0,.devreg={0,0,0}}; +#define number_vars 1 +const t_variable variables[number_vars]={CLK_IGNORE,}; + +/*** Driver Definitions ***/ +#define number_drivers 3 +const t_driver I2C {.name="I2C",.type=drv_i2c,.parent=0,.parameters={1},.devreg={}}; +const t_driver I2C_CLK {.name="I2C_CLK",.type=drv_i2c_devs,.parent=0,.parameters={32},.devreg={}}; +const t_driver SPIbb1 {.name="SPIbb1",.type=drv_spibitbang2,.parent=1,.parameters={4,7,5,6},.devreg={IO3_GPIO1,IO3_GPIO1,IO3_GPIO1,IO3_GPIO1}}; +const t_driver driver_config[number_drivers]={I2C,I2C_CLK,SPIbb1,}; diff --git a/src/apsctl/CLK.yaml b/src/apsctl/CLK.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9edd498bfcd4b8bd13cf44b78ac2355d6ae79447 --- /dev/null +++ b/src/apsctl/CLK.yaml @@ -0,0 +1,58 @@ +version: "1.0" +description: "1234" + +drivers: + - name: I2C + type: i2c + parameters: [1] #I2C port number + - name: I2C_CLK + type: i2c_devs #I2C devices + parent: I2C + parameters: [32] #number of RCUs + - name: SPIbb1 + type: spibitbang2 #SPI bitbang via GPIO expander: CLK, SDI,SDO,CS + parent: I2C_CLK + devreg: [IO3.GPIO1,IO3.GPIO1,IO3.GPIO1,IO3.GPIO1] + parameters: [4,7,5,6] + +#This is the I2C devices in the RCU +device_registers: + - name: IO + dim: 3 + description: IO-Expander + address: 0x20 + device: TCA9539/TCA6416? + driver: I2C_CLK + registers: + - name: CONF1 + description: Direction of port1 + address: 6 + store: True + - name: CONF2 + description: Direction of port2 + address: 7 + store: True + - name: GPIO1 + description: Input/Ouput port 1 + address: [0,2] #Read / Write address different + store: True + - name: GPIO2 + description: Input/Ouput port 2 + address: [1,3] + store: True + + - name: PLL + driver: SPIbb1 + registers: + - name: PLL_stat + description: PLL locked status + address: 0x0 + + +variables: + - name: CLK_IGNORE + description: Only masked RF chains are updated + driver: I2C_CLK + rw: variable #server RW variable, not linked to IO + dtype: boolean + diff --git a/src/apsctl/RCU.yaml b/src/apsctl/RCU.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b0a544345ceb036d56f88f76992a42445418ab29 --- /dev/null +++ b/src/apsctl/RCU.yaml @@ -0,0 +1,358 @@ +version: "1.0" +description: "1234" + +drivers: + - name: I2C1 + type: RCU_switch + devreg: [SWITCH.MASK] + parameters: [1] #I2C port number + - name: I2C_RCU + type: i2c_array #An array of similar devices connected to an I2C switch + parent: I2C1 + parameters: [1,32] #start,number of RCUs + - name: I2C_RFCHAIN + type: i2c_array2 #Array of similar devices with different address on same I2C line e.g. 3 rf chains on 1 RCU + parameters: [3] #number of RCUs + parent: I2C_RCU + - name: I2C_HBAT + type: hba1 #Special driver to manage HBAT1s. + parent: I2C_RCU + - name: I2Cbb1 + type: i2cbitbang1 #I2C bitbang via GPIO expander + devreg: [IO1.GPIO1,IO2.GPIO2,IO2.CONF2] + parameters: [6,3,3] #pins + parent: I2C_RCU + - name: I2Cbb2 + type: i2cbitbang1 + devreg: [IO1.GPIO2,IO2.GPIO1,IO1.CONF1] + parameters: [7,7,7] + parent: I2C_RCU + - name: I2Cbb3 + type: i2cbitbang1 + devreg: [IO1.GPIO2,IO2.GPIO1,IO1.CONF1] + parameters: [7,7,7] + parent: I2C_RCU + - name: SPIbb1 + type: spibitbang1 #SPI bitbang via GPIO expander: CLK, SDIO, SDIOdir,CS + devreg: [IO3.GPIO1,IO3.GPIO1,IO3.CONF1,IO3.GPIO2] + parameters: [1,0,0,0] + parent: I2C_RCU + - name: SPIbb2 + type: spibitbang1 + devreg: [IO3.GPIO1,IO3.GPIO1,IO3.CONF1,IO3.GPIO2] + parameters: [3,2,2,1] + parent: I2C_RCU + - name: SPIbb3 + type: spibitbang1 + devreg: [IO3.GPIO1,IO3.GPIO1,IO3.CONF1,IO3.GPIO2] + parameters: [5,4,4,2] + parent: I2C_RCU + +#This is the I2C devices in the RCU +device_registers: + - name: IO + dim: 3 + description: [IO-Expander for filter selection,IO-Expander for ON/OFF, Band, BUFx2,IO-Expander for ADC control] + address: [0x75,0x76,0x20] + device: [TCA9539,TCA9539,TCA6416] + driver: I2C_RCU + registers: + - name: CONF1 + description: Direction of port1 + address: 6 + store: True + - name: CONF2 + description: Direction of port2 + address: 7 + store: True + - name: GPIO1 + description: Input/Ouput port 1 + address: [0,2] #Read / Write address different + store: True + - name: GPIO2 + description: Input/Ouput port 2 + address: [1,3] + store: True + + - name: SWITCH + description: RCU selection switch + address: 0x70 + device: TCA9548 + driver: I2C1 + registers: + - name: MASK + description: I2C select mask + + - name: ROM + description: IO-Expander for filter selection + address: 0x50 + driver: I2C_RCU + registers: + - name: ID + description: Random + address: 0xfc + - name: Version + description: Set in production + address: 0 + + - name: AN + description: Monitor ADC on RCU + address: 0x14 + device: LTC2495 + driver: I2C_RCU + registers: + - name: Ch0 + address: 0xB080 + - name: Ch1 + address: 0xB880 + - name: Ch2 + address: 0xB180 + - name: Ch3 + address: 0xB980 + - name: Ch4 + address: 0xB280 + - name: Ch5 + address: 0xBA80 + - name: Ch6 + address: 0xB380 + - name: Ch7 + address: 0xBB80 + - name: Temp + address: 0xA0C0 + +#This 'special' devices that uses I2C + + - name: HB_UC + description: RCU microcontroller + address: 0x40 + driver: I2C_RCU + registers: + - name: ID + description: Device ID + address: 0 + + - name: HBAT + dim: 3 + address: [0x41,0x42,0x43] + description: Virtual HBAT0 interface + driver: I2C_HBAT + registers: + - name: XY + address: 0x10 + description: XY delay register + - name: Version + address: 127 + description: HBAT server version + + - name: ADC + dim: 3 + description: ADC SPI control + device: AD9683 + driver: [SPIbb1,SPIbb2,SPIbb3] + registers: + - name: PLL_stat + description: PLL locked status + address: 0x0A + - name: JESD_control1 + description: JESD link control + address: 0x5F + - name: CML_adjust + description: CML output adjust + address: 0x15 + - name: Update + description: Global device uptate + address: 0xFF + + - name: DTH + dim: 3 + description: CW dither source + device: SI4012 + driver: [I2Cbb1,I2Cbb1,I2Cbb1] + address: 0x70 + registers: + - name: Freq + description: Frequency + address: [0x1140,0x1141] + - name: Property + description: Properties + address: [0x11,0x11] + - name: Start + description: Start CW + address: [0x62,0x62] + - name: Stop + description: Stop CW + address: [0x67,0x67] + + +variables: + - name: Ant_mask + description: Only masked RF chains are updated + driver: I2C_RFCHAIN + rw: variable #server RW variable, not linked to IO + dtype: boolean + dim: 96 + + - name: RCU_mask + description: Only masked RCUs are updated + driver: I2C_RCU + rw: variable #server RW variable, not linked to IO + dtype: boolean + dim: 32 + + - name: RCU_attenuator + description: Attenuator before ADC + driver: I2C_RFCHAIN + devreg: [IO1.GPIO1,IO1.GPIO2,IO2.GPIO1] + bitoffset: [0,0,0] + width: 5 + rw: rw + dtype: uint8 + dim: 96 + mask: Ant_mask + + - name: RCU_band + description: Band select switch 1=10MHz,2=30MHz + driver: I2C_RFCHAIN + devreg: [IO2.GPIO2,IO2.GPIO2,IO2.GPIO2] + bitoffset: [0,2,4] + width: 2 + rw: rw + dtype: uint8 + dim: 96 + mask: Ant_mask + + - name: RCU_LED0 + driver: I2C_RCU + description: LED on RCU + devreg: IO2.GPIO2 + bitoffset: 6 + width: 1 + rw: rw + dtype: boolean + dim: 32 + mask: RCU_mask + + - name: RCU_LED1 + driver: I2C_RCU + description: LED on RCU + devreg: IO2.GPIO2 + bitoffset: 7 + width: 1 + rw: rw + dtype: boolean + dim: 32 + mask: RCU_mask + + - name: RCU_temperature + description: Temperature sensor on RCU + driver: I2C_RCU + devreg: AN.Temp + width: 23 + scale: 4.21e-3 + rw: ro + dtype: double + dim: 32 + + - name: RCU_Pwr_dig + description: Enable LDOs + driver: I2C_RCU + devreg: IO2.GPIO1 + width: 1 + bitoffset: 6 + rw: ro + dtype: boolean + dim: 32 + mask: RCU_mask + + - name: HBA_element_beamformer_delays + description: Delays of each frontend + driver: I2C_HBAT + devreg: [HBAT1.XY,HBAT2.XY,HBAT3.XY] + bitoffset: [2,2,2] + width: 5 + rw: rw + dtype: uint8 + dim: 3072 + mask: Ant_mask + + - name: RCU_ID + description: Unique RCU ID + driver: I2C_RCU + devreg: ROM.ID + width: 32 + rw: ro + dtype: uint32 + dim: 32 + mask: RCU_mask + + - name: RCU_version + description: RCU version number + driver: I2C_RCU + devreg: ROM.Version + width: 80 #10 characters + rw: ro + dtype: string + dim: 32 + mask: RCU_mask + + - name: RCU_ADC_lock + description: 0x81=locked + driver: I2C_RFCHAIN + devreg: [ADC1.PLL_stat,ADC2.PLL_stat,ADC3.PLL_stat] + width: 8 + rw: ro + dtype: uint8 + dim: 96 + mask: Ant_mask + + - name: RCU_dth1_freq + driver: I2C_RFCHAIN + devreg: [DTH1.Freq,DTH2.Freq,DTH3.Freq] + width: 32 + rw: rw + dtype: uint32 + dim: 96 + mask: Ant_mask + +methods: + - name: RCU_on + mask: RCU_mask + instructions: + - IO2.CONF1: 0 #Set device register, can also specify a register adress direction e.g. OIO2.0: 0 + - IO2.GPIO1: 0x4A + - IO2.GPIO2: 0x55 + - IO3.GPIO1: 0x15 + - IO3.GPIO2: 0x47 + - IO1.GPIO1: 0xCA + - IO1.GPIO2: 0xCA + - IO2.CONF2: 0 + - IO3.CONF1: 0 + - IO3.CONF2: 0 + - IO1.CONF1: 0 + - IO1.CONF1: 0 + - RCU_attenuator: [10,10,10] #Set OPC-UA variable + - RCU_Pwr_dig: Update #Read value and update the OPC-UA variable + - WAIT: 500 #ms to wait + - ADC1_on: 0 #call another opc-ua method + - ADC2_on: 0 + - WAIT: 500 #ms to wait + - RCU_ADC_lock: Update + - name: ADC1_on + rw: hidden + instructions: + - ADC1.JESD_control1 : 0x14 +# - ADC1.SYNC_control: 1 #Setup ADCs +# - ADC1.CML_level: 0x7 + - ADC1.Update: 1 #Needed to update ADC registers + - name: ADC2_on + rw: hidden + instructions: + - ADC2.JESD_control1 : 0x14 +# - ADC2.SYNC_control: 1 #Setup ADCs +# - ADC2.CML_level: 0x7 + - ADC2.Update: 1 #Needed to update ADC registers + + - name: RCU_off + instructions: + - RCU_Pwr_dig: 0 #Switch power off + #todo, also make all GPIO pins (except power enables) inputs to remove all power from devices. \ No newline at end of file diff --git a/src/apsctl/UNB2.yaml b/src/apsctl/UNB2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e187ac81108168d9c823cbb708fb5460c79e4693 --- /dev/null +++ b/src/apsctl/UNB2.yaml @@ -0,0 +1,128 @@ +version: "0.0" +description: "UNB2 LTS" + +drivers: + - name: I2C1 + type: UNB2_switch #Special driver mapping internal i2c line address to the 3 switches. + #Address -> switch states -> array of i2c-devices + #00:2F -> [0:1][0:3][0:3,6:7] -> QSFP + #30:38 -> [0:1][0:3][4] -> DDR4 + #40:48 -> [0:1][0:3][5] -> FPGA_PS + #80:81 -> [0:1][4] -> PS + #A0:A1 -> [0:1][5] -> Front panel + devreg: [APSCT_SWITCH.MASK,UB2_SWITCH1.MASK,UB2_SWITCH2.MASK] + parameters: [1,0,0,0] #I2C port number, 3x switch reset pins + + - name: d_QSFP + type: i2c_array #An array of similar devices connected to an I2C switch + parent: I2C1 + parameters: [0,48] #start,number of QSFP (2 UB x 2 nodes * 6 QSFP) + - name: d_DDR4 + type: i2c_array + parent: I2C1 + parameters: [0x30,8] + - name: d_FPGA_PS + type: i2c_array + parent: I2C1 + parameters: [0x40,48] + - name: d_PS + type: i2c_array + parent: I2C1 + parameters: [0x80,2] + - name: d_front_panel + type: i2c_array + parent: I2C1 + parameters: [0xA0,2] +# - name: GPIO +# type: GPIO +# parameters: [1] #pin numbers + + +#This is the I2C devices in the RCU +device_registers: +- name: APSCT_SWITCH #not in LTS + description: Uniboard select switch on APSCT + address: 0x70 + device: TCA9548 + driver: I2C1 + registers: + - name: MASK +- name: UB2_SWITCH1 + description: UNB2 primary switch + address: 0x71 + device: TCA9548 + driver: I2C1 + registers: + - name: MASK +- name: UB2_SWITCH2 + description: UNB2 secondary switch + address: 0x72 + device: TCA9548 + driver: I2C1 + registers: + - name: MASK + +- name: FP_IO + description: IO-Expander for front panel + address: 0x41 + device: PCA9536 + driver: d_front_panel + registers: + - name: CONF #default 0xff = all input + description: Direction of GPIO + address: 3 + - name: GPIO + description: Input/Ouput port + address: [0,1] #Read / Write address different + store: True + +- name: POL_FPGA_CORE + address: 0x01 + driver: d_FPGA_PS + device: BMR4xx + registers: + - name: READ_VOUT + address: 0x8B + - name: READ_IOUT + address: 0x8C + - name: READ_TEMP + address: 0x8D + +variables: + - name: UNB2_mask + rw: variable #translator variable + dtype: boolean + dim: 2 + + - name: UNB2_Front_Panel_LED + description: LED on front panel + mask: UNB2_mask + devreg: FP_IO.GPIO + driver: d_front_panel + rw: rw + dtype: uint8 + bitoffset: 4 + width: 3 + dim: 2 + + - name: UNB2_POL_FPGA_CORE_VOUT + driver: d_FPGA_PS + devreg: POL_FPGA_CORE.READ_VOUT + width: 16 + rw: ro + dtype: double + scale: 1.2207e-4 #2^-13 + dim: 8 + mask: UNB2_node_mask + +methods: + - name: UNB2_on + mask: UNB2_mask + instructions: + - FP_IO.CONF: 0xff #TODO: setup correctly + - UNB2_Front_Panel_LED: 1 + + - name: UNB2_off + mask: UNB2_mask + instructions: + - UNB2_Front_Panel_LED: 2 diff --git a/src/apsctl/conf.cpp b/src/apsctl/conf.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ac5dc33262894022e2bf918c301158147d40aad3 --- /dev/null +++ b/src/apsctl/conf.cpp @@ -0,0 +1,39 @@ +#include "conf.h" +#include "../drivers/hba1.h" +#include "../drivers/RCU_switch.h" +#include "../drivers/spibitbang1.h" +#include "../drivers/i2cbitbang1.h" +#include "../drivers/i2c_array2.h" +#include "../drivers/i2c_array.h" +c_drivers::c_drivers() +{ + c_RCU_switch* i_I2C1=new c_RCU_switch(I2C1); + d[0]=i_I2C1; + c_i2c_array* i_I2C_RCU=new c_i2c_array(I2C_RCU); + d[1]=i_I2C_RCU; + c_i2c_array2* i_I2C_RFCHAIN=new c_i2c_array2(I2C_RFCHAIN); + d[2]=i_I2C_RFCHAIN; + c_hba1* i_I2C_HBAT=new c_hba1(I2C_HBAT); + d[3]=i_I2C_HBAT; + c_i2cbitbang1* i_I2Cbb1=new c_i2cbitbang1(I2Cbb1); + d[4]=i_I2Cbb1; + c_i2cbitbang1* i_I2Cbb2=new c_i2cbitbang1(I2Cbb2); + d[5]=i_I2Cbb2; + c_i2cbitbang1* i_I2Cbb3=new c_i2cbitbang1(I2Cbb3); + d[6]=i_I2Cbb3; + c_spibitbang1* i_SPIbb1=new c_spibitbang1(SPIbb1); + d[7]=i_SPIbb1; + c_spibitbang1* i_SPIbb2=new c_spibitbang1(SPIbb2); + d[8]=i_SPIbb2; + c_spibitbang1* i_SPIbb3=new c_spibitbang1(SPIbb3); + d[9]=i_SPIbb3; + i_I2C_RCU->parent=i_I2C1; + i_I2C_RFCHAIN->parent=i_I2C_RCU; + i_I2C_HBAT->parent=i_I2C_RCU; + i_I2Cbb1->parent=i_I2C_RCU; + i_I2Cbb2->parent=i_I2C_RCU; + i_I2Cbb3->parent=i_I2C_RCU; + i_SPIbb1->parent=i_I2C_RCU; + i_SPIbb2->parent=i_I2C_RCU; + i_SPIbb3->parent=i_I2C_RCU; +}; diff --git a/src/apsctl/conf.cpp.old b/src/apsctl/conf.cpp.old new file mode 100644 index 0000000000000000000000000000000000000000..efea9d58ea8f17a1ceb08bf7bd8204773e198b76 --- /dev/null +++ b/src/apsctl/conf.cpp.old @@ -0,0 +1,13 @@ +#include "conf.h" +#include "../drivers/i2c_switch.h" +#include "../drivers/i2c_array.h" + +c_drivers::c_drivers() +{ + c_i2c_switch* i_I2C1=new c_i2c_switch(I2C1); + d[0]=i_I2C1; + c_i2c_array* i_I2C_RCU=new c_i2c_array(I2C_RCU); + d[1]=i_I2C_RCU; + i_I2C_RCU->parent=i_I2C1; +}; + diff --git a/src/apsctl/conf.h b/src/apsctl/conf.h new file mode 100644 index 0000000000000000000000000000000000000000..48ab69d7177a5c63afdea70376e972da6f6cb761 --- /dev/null +++ b/src/apsctl/conf.h @@ -0,0 +1,141 @@ +#ifndef HWDEFS_H +#define HWDEFS_H +#include "../drivers/drvbase.h" +#include "../structs.h" + +/*** Device Register Definitions ***/ +const t_devreg IO1_CONF1 {.address=117,.register_R=6,.register_W=6,.store=1,.driver=1}; +const t_devreg IO1_CONF2 {.address=117,.register_R=7,.register_W=7,.store=2,.driver=1}; +const t_devreg IO1_GPIO1 {.address=117,.register_R=0,.register_W=2,.store=3,.driver=1}; +const t_devreg IO1_GPIO2 {.address=117,.register_R=1,.register_W=3,.store=4,.driver=1}; +const t_devreg IO2_CONF1 {.address=118,.register_R=6,.register_W=6,.store=5,.driver=1}; +const t_devreg IO2_CONF2 {.address=118,.register_R=7,.register_W=7,.store=6,.driver=1}; +const t_devreg IO2_GPIO1 {.address=118,.register_R=0,.register_W=2,.store=7,.driver=1}; +const t_devreg IO2_GPIO2 {.address=118,.register_R=1,.register_W=3,.store=8,.driver=1}; +const t_devreg IO3_CONF1 {.address=32,.register_R=6,.register_W=6,.store=9,.driver=1}; +const t_devreg IO3_CONF2 {.address=32,.register_R=7,.register_W=7,.store=10,.driver=1}; +const t_devreg IO3_GPIO1 {.address=32,.register_R=0,.register_W=2,.store=11,.driver=1}; +const t_devreg IO3_GPIO2 {.address=32,.register_R=1,.register_W=3,.store=12,.driver=1}; +const t_devreg SWITCH_MASK {.address=112,.register_R=0,.register_W=0,.store=0,.driver=0}; +const t_devreg ROM_ID {.address=80,.register_R=252,.register_W=252,.store=0,.driver=1}; +const t_devreg ROM_Version {.address=80,.register_R=0,.register_W=0,.store=0,.driver=1}; +const t_devreg AN_Ch0 {.address=20,.register_R=45184,.register_W=45184,.store=0,.driver=1}; +const t_devreg AN_Ch1 {.address=20,.register_R=47232,.register_W=47232,.store=0,.driver=1}; +const t_devreg AN_Ch2 {.address=20,.register_R=45440,.register_W=45440,.store=0,.driver=1}; +const t_devreg AN_Ch3 {.address=20,.register_R=47488,.register_W=47488,.store=0,.driver=1}; +const t_devreg AN_Ch4 {.address=20,.register_R=45696,.register_W=45696,.store=0,.driver=1}; +const t_devreg AN_Ch5 {.address=20,.register_R=47744,.register_W=47744,.store=0,.driver=1}; +const t_devreg AN_Ch6 {.address=20,.register_R=45952,.register_W=45952,.store=0,.driver=1}; +const t_devreg AN_Ch7 {.address=20,.register_R=48000,.register_W=48000,.store=0,.driver=1}; +const t_devreg AN_Temp {.address=20,.register_R=41152,.register_W=41152,.store=0,.driver=1}; +const t_devreg HB_UC_ID {.address=64,.register_R=0,.register_W=0,.store=0,.driver=1}; +const t_devreg HBAT1_XY {.address=65,.register_R=16,.register_W=16,.store=0,.driver=3}; +const t_devreg HBAT1_Version {.address=65,.register_R=127,.register_W=127,.store=0,.driver=3}; +const t_devreg HBAT2_XY {.address=66,.register_R=16,.register_W=16,.store=0,.driver=3}; +const t_devreg HBAT2_Version {.address=66,.register_R=127,.register_W=127,.store=0,.driver=3}; +const t_devreg HBAT3_XY {.address=67,.register_R=16,.register_W=16,.store=0,.driver=3}; +const t_devreg HBAT3_Version {.address=67,.register_R=127,.register_W=127,.store=0,.driver=3}; +const t_devreg ADC1_PLL_stat {.address=0,.register_R=10,.register_W=10,.store=0,.driver=7}; +const t_devreg ADC1_JESD_control1 {.address=0,.register_R=95,.register_W=95,.store=0,.driver=7}; +const t_devreg ADC1_CML_adjust {.address=0,.register_R=21,.register_W=21,.store=0,.driver=7}; +const t_devreg ADC1_Update {.address=0,.register_R=255,.register_W=255,.store=0,.driver=7}; +const t_devreg ADC2_PLL_stat {.address=0,.register_R=10,.register_W=10,.store=0,.driver=8}; +const t_devreg ADC2_JESD_control1 {.address=0,.register_R=95,.register_W=95,.store=0,.driver=8}; +const t_devreg ADC2_CML_adjust {.address=0,.register_R=21,.register_W=21,.store=0,.driver=8}; +const t_devreg ADC2_Update {.address=0,.register_R=255,.register_W=255,.store=0,.driver=8}; +const t_devreg ADC3_PLL_stat {.address=0,.register_R=10,.register_W=10,.store=0,.driver=9}; +const t_devreg ADC3_JESD_control1 {.address=0,.register_R=95,.register_W=95,.store=0,.driver=9}; +const t_devreg ADC3_CML_adjust {.address=0,.register_R=21,.register_W=21,.store=0,.driver=9}; +const t_devreg ADC3_Update {.address=0,.register_R=255,.register_W=255,.store=0,.driver=9}; +const t_devreg DTH1_Freq {.address=112,.register_R=4416,.register_W=4417,.store=0,.driver=4}; +const t_devreg DTH1_Property {.address=112,.register_R=17,.register_W=17,.store=0,.driver=4}; +const t_devreg DTH1_Start {.address=112,.register_R=98,.register_W=98,.store=0,.driver=4}; +const t_devreg DTH1_Stop {.address=112,.register_R=103,.register_W=103,.store=0,.driver=4}; +const t_devreg DTH2_Freq {.address=112,.register_R=4416,.register_W=4417,.store=0,.driver=4}; +const t_devreg DTH2_Property {.address=112,.register_R=17,.register_W=17,.store=0,.driver=4}; +const t_devreg DTH2_Start {.address=112,.register_R=98,.register_W=98,.store=0,.driver=4}; +const t_devreg DTH2_Stop {.address=112,.register_R=103,.register_W=103,.store=0,.driver=4}; +const t_devreg DTH3_Freq {.address=112,.register_R=4416,.register_W=4417,.store=0,.driver=4}; +const t_devreg DTH3_Property {.address=112,.register_R=17,.register_W=17,.store=0,.driver=4}; +const t_devreg DTH3_Start {.address=112,.register_R=98,.register_W=98,.store=0,.driver=4}; +const t_devreg DTH3_Stop {.address=112,.register_R=103,.register_W=103,.store=0,.driver=4}; +#define NumberStoreReg 12 +/*** Variable Definitions ***/ +const t_variable Ant_mask {.name="Ant_mask",.dim=96,.dtype=dt_boolean,.driver=2,.rw=rw_variable,.bitoffset={0,0,0},.width=8,.scale=0,.devreg={0,0,0}}; +const t_variable RCU_mask {.name="RCU_mask",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_variable,.bitoffset={0,0,0},.width=8,.scale=0,.devreg={0,0,0}}; +const t_variable RCU_attenuator {.name="RCU_attenuator",.dim=96,.dtype=dt_uint8,.driver=2,.rw=rw_rw,.bitoffset={0,0,0},.width=5,.scale=0,.devreg={IO1_GPIO1,IO1_GPIO2,IO2_GPIO1}}; +const t_variable RCU_band {.name="RCU_band",.dim=96,.dtype=dt_uint8,.driver=2,.rw=rw_rw,.bitoffset={0,2,4},.width=2,.scale=0,.devreg={IO2_GPIO2,IO2_GPIO2,IO2_GPIO2}}; +const t_variable RCU_LED0 {.name="RCU_LED0",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_rw,.bitoffset={6,6,6},.width=1,.scale=0,.devreg={IO2_GPIO2,IO2_GPIO2,IO2_GPIO2}}; +const t_variable RCU_LED1 {.name="RCU_LED1",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_rw,.bitoffset={7,7,7},.width=1,.scale=0,.devreg={IO2_GPIO2,IO2_GPIO2,IO2_GPIO2}}; +const t_variable RCU_temperature {.name="RCU_temperature",.dim=32,.dtype=dt_double,.driver=1,.rw=rw_ro,.bitoffset={0,0,0},.width=23,.scale=0.00421,.devreg={AN_Temp,AN_Temp,AN_Temp}}; +const t_variable RCU_Pwr_dig {.name="RCU_Pwr_dig",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_ro,.bitoffset={6,6,6},.width=1,.scale=0,.devreg={IO2_GPIO1,IO2_GPIO1,IO2_GPIO1}}; +const t_variable HBA_element_beamformer_delays {.name="HBA_element_beamformer_delays",.dim=3072,.dtype=dt_uint8,.driver=3,.rw=rw_rw,.bitoffset={2,2,2},.width=5,.scale=0,.devreg={HBAT1_XY,HBAT2_XY,HBAT3_XY}}; +const t_variable RCU_ID {.name="RCU_ID",.dim=32,.dtype=dt_uint32,.driver=1,.rw=rw_ro,.bitoffset={0,0,0},.width=32,.scale=0,.devreg={ROM_ID,ROM_ID,ROM_ID}}; +const t_variable RCU_version {.name="RCU_version",.dim=32,.dtype=dt_string,.driver=1,.rw=rw_ro,.bitoffset={0,0,0},.width=80,.scale=0,.devreg={ROM_Version,ROM_Version,ROM_Version}}; +const t_variable RCU_ADC_lock {.name="RCU_ADC_lock",.dim=96,.dtype=dt_uint8,.driver=2,.rw=rw_ro,.bitoffset={0,0,0},.width=8,.scale=0,.devreg={ADC1_PLL_stat,ADC2_PLL_stat,ADC3_PLL_stat}}; +const t_variable RCU_dth1_freq {.name="RCU_dth1_freq",.dim=96,.dtype=dt_uint32,.driver=2,.rw=rw_rw,.bitoffset={0,0,0},.width=32,.scale=0,.devreg={DTH1_Freq,DTH2_Freq,DTH3_Freq}}; +#define number_vars 13 +const t_variable variables[number_vars]={Ant_mask,RCU_mask,RCU_attenuator,RCU_band,RCU_LED0,RCU_LED1,RCU_temperature,RCU_Pwr_dig,HBA_element_beamformer_delays,RCU_ID,RCU_version,RCU_ADC_lock,RCU_dth1_freq,}; + +/*** Driver Definitions ***/ +#define number_drivers 10 +const t_driver I2C1 {.name="I2C1",.type=drv_RCU_switch,.parent=0,.parameters={1},.devreg={SWITCH_MASK}}; +const t_driver I2C_RCU {.name="I2C_RCU",.type=drv_i2c_array,.parent=0,.parameters={1,32},.devreg={}}; +const t_driver I2C_RFCHAIN {.name="I2C_RFCHAIN",.type=drv_i2c_array2,.parent=1,.parameters={3},.devreg={}}; +const t_driver I2C_HBAT {.name="I2C_HBAT",.type=drv_hba1,.parent=1,.parameters={},.devreg={}}; +const t_driver I2Cbb1 {.name="I2Cbb1",.type=drv_i2cbitbang1,.parent=1,.parameters={6,3,3},.devreg={IO1_GPIO1,IO2_GPIO2,IO2_CONF2}}; +const t_driver I2Cbb2 {.name="I2Cbb2",.type=drv_i2cbitbang1,.parent=1,.parameters={7,7,7},.devreg={IO1_GPIO2,IO2_GPIO1,IO1_CONF1}}; +const t_driver I2Cbb3 {.name="I2Cbb3",.type=drv_i2cbitbang1,.parent=1,.parameters={7,7,7},.devreg={IO1_GPIO2,IO2_GPIO1,IO1_CONF1}}; +const t_driver SPIbb1 {.name="SPIbb1",.type=drv_spibitbang1,.parent=1,.parameters={1,0,0,0},.devreg={IO3_GPIO1,IO3_GPIO1,IO3_CONF1,IO3_GPIO2}}; +const t_driver SPIbb2 {.name="SPIbb2",.type=drv_spibitbang1,.parent=1,.parameters={3,2,2,1},.devreg={IO3_GPIO1,IO3_GPIO1,IO3_CONF1,IO3_GPIO2}}; +const t_driver SPIbb3 {.name="SPIbb3",.type=drv_spibitbang1,.parent=1,.parameters={5,4,4,2},.devreg={IO3_GPIO1,IO3_GPIO1,IO3_CONF1,IO3_GPIO2}}; +//const t_driver driver_config[number_drivers]={I2C1,I2C_RCU,I2C_RFCHAIN,I2C_HBAT,I2Cbb1,I2Cbb2,I2Cbb3,SPIbb1,SPIbb2,SPIbb3,}; + +class c_drivers { + public: + c_drivers(); + drvbase* d[number_drivers]; +}; + +/*** Method Definitions ***/ +#define number_methods 4 +const t_instruction RCU_on_inst[19]={ + {.type=inst_devreg,.variable=0,.devreg=IO2_CONF1,.len=1,.data={0}}, + {.type=inst_devreg,.variable=0,.devreg=IO2_GPIO1,.len=1,.data={74}}, + {.type=inst_devreg,.variable=0,.devreg=IO2_GPIO2,.len=1,.data={85}}, + {.type=inst_devreg,.variable=0,.devreg=IO3_GPIO1,.len=1,.data={21}}, + {.type=inst_devreg,.variable=0,.devreg=IO3_GPIO2,.len=1,.data={71}}, + {.type=inst_devreg,.variable=0,.devreg=IO1_GPIO1,.len=1,.data={202}}, + {.type=inst_devreg,.variable=0,.devreg=IO1_GPIO2,.len=1,.data={202}}, + {.type=inst_devreg,.variable=0,.devreg=IO2_CONF2,.len=1,.data={0}}, + {.type=inst_devreg,.variable=0,.devreg=IO3_CONF1,.len=1,.data={0}}, + {.type=inst_devreg,.variable=0,.devreg=IO3_CONF2,.len=1,.data={0}}, + {.type=inst_devreg,.variable=0,.devreg=IO1_CONF1,.len=1,.data={0}}, + {.type=inst_devreg,.variable=0,.devreg=IO1_CONF1,.len=1,.data={0}}, + {.type=inst_setvar,.variable=2,.devreg={0},.len=3,.data={10,10,10,}}, + {.type=inst_getvarall,.variable=7,.devreg={0},.len=0,.data={}}, + {.type=inst_wait,.variable=0,.devreg={0},.len=1,.data={}}, + {.type=inst_method,.variable=1,.devreg={0},.len=0,.data={}}, + {.type=inst_method,.variable=2,.devreg={0},.len=0,.data={}}, + {.type=inst_wait,.variable=0,.devreg={0},.len=1,.data={}}, + {.type=inst_getvarall,.variable=11,.devreg={0},.len=0,.data={}}, + }; +const t_method RCU_on {.name="RCU_on",.len=19,.instructions=RCU_on_inst}; +const t_instruction ADC1_on_inst[2]={ + {.type=inst_devreg,.variable=0,.devreg=ADC1_JESD_control1,.len=1,.data={20}}, + {.type=inst_devreg,.variable=0,.devreg=ADC1_Update,.len=1,.data={1}}, + }; +const t_method ADC1_on {.name="ADC1_on",.len=2,.instructions=ADC1_on_inst}; +const t_instruction ADC2_on_inst[2]={ + {.type=inst_devreg,.variable=0,.devreg=ADC2_JESD_control1,.len=1,.data={20}}, + {.type=inst_devreg,.variable=0,.devreg=ADC2_Update,.len=1,.data={1}}, + }; +const t_method ADC2_on {.name="ADC2_on",.len=2,.instructions=ADC2_on_inst}; +const t_instruction RCU_off_inst[1]={ + {.type=inst_setvar,.variable=7,.devreg={0},.len=1,.data={0}}, + }; +const t_method RCU_off {.name="RCU_off",.len=1,.instructions=RCU_off_inst}; +const t_method method_config[number_methods]={RCU_on,ADC1_on,ADC2_on,RCU_off,}; + + +#endif diff --git a/src/apsctl/conf.h.old b/src/apsctl/conf.h.old new file mode 100644 index 0000000000000000000000000000000000000000..28945b2240d1135b65036884b63390f7a527a664 --- /dev/null +++ b/src/apsctl/conf.h.old @@ -0,0 +1,100 @@ +#ifndef HWDEFS_H +#define HWDEFS_H +#include "../drivers/drvbase.h" +#include "../structs.h" +/*** Device Register Definitions ***/ +const t_devreg IO1_CONF1 {.address=117,.register_R=6,.register_W=6,.store=1,.driver=1}; +const t_devreg IO1_CONF2 {.address=117,.register_R=7,.register_W=7,.store=2,.driver=1}; +const t_devreg IO1_GPIO1 {.address=117,.register_R=0,.register_W=2,.store=3,.driver=1}; +const t_devreg IO1_GPIO2 {.address=117,.register_R=1,.register_W=3,.store=4,.driver=1}; +const t_devreg IO2_CONF1 {.address=118,.register_R=6,.register_W=6,.store=5,.driver=1}; +const t_devreg IO2_CONF2 {.address=118,.register_R=7,.register_W=7,.store=6,.driver=1}; +const t_devreg IO2_GPIO1 {.address=118,.register_R=0,.register_W=2,.store=7,.driver=1}; +const t_devreg IO2_GPIO2 {.address=118,.register_R=1,.register_W=3,.store=8,.driver=1}; +const t_devreg IO3_CONF1 {.address=32,.register_R=6,.register_W=6,.store=9,.driver=1}; +const t_devreg IO3_CONF2 {.address=32,.register_R=7,.register_W=7,.store=10,.driver=1}; +const t_devreg IO3_GPIO1 {.address=32,.register_R=0,.register_W=2,.store=11,.driver=1}; +const t_devreg IO3_GPIO2 {.address=32,.register_R=1,.register_W=3,.store=12,.driver=1}; +const t_devreg SWITCH_MASK {.address=112,.register_R=0,.register_W=0,.store=0,.driver=0}; +const t_devreg ROM_ID {.address=80,.register_R=252,.register_W=252,.store=0,.driver=1}; +const t_devreg ROM_Version {.address=80,.register_R=0,.register_W=0,.store=0,.driver=1}; +const t_devreg AN_Ch0 {.address=20,.register_R=45184,.register_W=45184,.store=0,.driver=1}; +const t_devreg AN_Ch1 {.address=20,.register_R=47232,.register_W=47232,.store=0,.driver=1}; +const t_devreg AN_Ch2 {.address=20,.register_R=45440,.register_W=45440,.store=0,.driver=1}; +const t_devreg AN_Ch3 {.address=20,.register_R=47488,.register_W=47488,.store=0,.driver=1}; +const t_devreg AN_Ch4 {.address=20,.register_R=45696,.register_W=45696,.store=0,.driver=1}; +const t_devreg AN_Ch5 {.address=20,.register_R=47744,.register_W=47744,.store=0,.driver=1}; +const t_devreg AN_Ch6 {.address=20,.register_R=45952,.register_W=45952,.store=0,.driver=1}; +const t_devreg AN_Ch7 {.address=20,.register_R=48000,.register_W=48000,.store=0,.driver=1}; +const t_devreg AN_Temp {.address=20,.register_R=41152,.register_W=41152,.store=0,.driver=1}; +const t_devreg HB_UC_ID {.address=64,.register_R=0,.register_W=0,.store=0,.driver=1}; +const t_devreg HBAT1_XY {.address=65,.register_R=16,.register_W=16,.store=0,.driver=3}; +const t_devreg HBAT1_Version {.address=65,.register_R=127,.register_W=127,.store=0,.driver=3}; +const t_devreg HBAT2_XY {.address=66,.register_R=16,.register_W=16,.store=0,.driver=3}; +const t_devreg HBAT2_Version {.address=66,.register_R=127,.register_W=127,.store=0,.driver=3}; +const t_devreg HBAT3_XY {.address=67,.register_R=16,.register_W=16,.store=0,.driver=3}; +const t_devreg HBAT3_Version {.address=67,.register_R=127,.register_W=127,.store=0,.driver=3}; +const t_devreg ADC1_PLL_stat {.address=0,.register_R=10,.register_W=10,.store=0,.driver=7}; +const t_devreg ADC1_JESD_control1 {.address=0,.register_R=95,.register_W=95,.store=0,.driver=7}; +const t_devreg ADC1_CML_adjust {.address=0,.register_R=21,.register_W=21,.store=0,.driver=7}; +const t_devreg ADC1_Update {.address=0,.register_R=255,.register_W=255,.store=0,.driver=7}; +const t_devreg ADC2_PLL_stat {.address=0,.register_R=10,.register_W=10,.store=0,.driver=8}; +const t_devreg ADC2_JESD_control1 {.address=0,.register_R=95,.register_W=95,.store=0,.driver=8}; +const t_devreg ADC2_CML_adjust {.address=0,.register_R=21,.register_W=21,.store=0,.driver=8}; +const t_devreg ADC2_Update {.address=0,.register_R=255,.register_W=255,.store=0,.driver=8}; +const t_devreg ADC3_PLL_stat {.address=0,.register_R=10,.register_W=10,.store=0,.driver=9}; +const t_devreg ADC3_JESD_control1 {.address=0,.register_R=95,.register_W=95,.store=0,.driver=9}; +const t_devreg ADC3_CML_adjust {.address=0,.register_R=21,.register_W=21,.store=0,.driver=9}; +const t_devreg ADC3_Update {.address=0,.register_R=255,.register_W=255,.store=0,.driver=9}; +const t_devreg DTH1_Freq {.address=112,.register_R=4416,.register_W=4417,.store=0,.driver=4}; +const t_devreg DTH1_Property {.address=112,.register_R=17,.register_W=17,.store=0,.driver=4}; +const t_devreg DTH1_Start {.address=112,.register_R=98,.register_W=98,.store=0,.driver=4}; +const t_devreg DTH1_Stop {.address=112,.register_R=103,.register_W=103,.store=0,.driver=4}; +const t_devreg DTH2_Freq {.address=112,.register_R=4416,.register_W=4417,.store=0,.driver=4}; +const t_devreg DTH2_Property {.address=112,.register_R=17,.register_W=17,.store=0,.driver=4}; +const t_devreg DTH2_Start {.address=112,.register_R=98,.register_W=98,.store=0,.driver=4}; +const t_devreg DTH2_Stop {.address=112,.register_R=103,.register_W=103,.store=0,.driver=4}; +const t_devreg DTH3_Freq {.address=112,.register_R=4416,.register_W=4417,.store=0,.driver=4}; +const t_devreg DTH3_Property {.address=112,.register_R=17,.register_W=17,.store=0,.driver=4}; +const t_devreg DTH3_Start {.address=112,.register_R=98,.register_W=98,.store=0,.driver=4}; +const t_devreg DTH3_Stop {.address=112,.register_R=103,.register_W=103,.store=0,.driver=4}; +#define NumberStoreReg 12 +/*** Variable Definitions ***/ +const t_variable Ant_mask {.name="Ant_mask",.dim=96,.dtype=dt_boolean,.driver=2,.rw=rw_variable,.bitoffset={0,0,0},.width=8,.scale=0,.devreg={0,0,0}}; +const t_variable RCU_mask {.name="RCU_mask",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_variable,.bitoffset={0,0,0},.width=8,.scale=0,.devreg={0,0,0}}; +const t_variable RCU_attenuator {.name="RCU_attenuator",.dim=96,.dtype=dt_integer,.driver=2,.rw=rw_rw,.bitoffset={0,0,0},.width=5,.scale=0,.devreg={IO1_GPIO1,IO1_GPIO2,IO2_GPIO1}}; +const t_variable RCU_band {.name="RCU_band",.dim=96,.dtype=dt_integer,.driver=2,.rw=rw_rw,.bitoffset={0,2,4},.width=2,.scale=0,.devreg={IO2_GPIO2,IO2_GPIO2,IO2_GPIO2}}; +const t_variable RCU_LED0 {.name="RCU_LED0",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_rw,.bitoffset={6,6,6},.width=1,.scale=0,.devreg={IO2_GPIO2,IO2_GPIO2,IO2_GPIO2}}; +const t_variable RCU_LED1 {.name="RCU_LED1",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_rw,.bitoffset={7,7,7},.width=1,.scale=0,.devreg={IO2_GPIO2,IO2_GPIO2,IO2_GPIO2}}; +const t_variable RCU_temperature {.name="RCU_temperature",.dim=32,.dtype=dt_float,.driver=1,.rw=rw_ro,.bitoffset={0,0,0},.width=23,.scale=0.00421,.devreg={AN_Temp,AN_Temp,AN_Temp}}; +const t_variable RCU_Pwr_dig {.name="RCU_Pwr_dig",.dim=32,.dtype=dt_boolean,.driver=1,.rw=rw_ro,.bitoffset={6,6,6},.width=1,.scale=0,.devreg={IO2_GPIO1,IO2_GPIO1,IO2_GPIO1}}; +const t_variable HBA_element_beamformer_delays {.name="HBA_element_beamformer_delays",.dim=3072,.dtype=dt_integer,.driver=3,.rw=rw_rw,.bitoffset={2,2,2},.width=5,.scale=0,.devreg={HBAT1_XY,HBAT2_XY,HBAT3_XY}}; +const t_variable RCU_ID {.name="RCU_ID",.dim=32,.dtype=dt_integer,.driver=1,.rw=rw_ro,.bitoffset={0,0,0},.width=32,.scale=0,.devreg={ROM_ID,ROM_ID,ROM_ID}}; +const t_variable RCU_version {.name="RCU_version",.dim=32,.dtype=dt_string,.driver=1,.rw=rw_ro,.bitoffset={0,0,0},.width=80,.scale=0,.devreg={ROM_Version,ROM_Version,ROM_Version}}; +const t_variable RCU_ADC_lock {.name="RCU_ADC_lock",.dim=96,.dtype=dt_integer,.driver=2,.rw=rw_ro,.bitoffset={0,0,0},.width=8,.scale=0,.devreg={ADC1_PLL_stat,ADC2_PLL_stat,ADC3_PLL_stat}}; +const t_variable RCU_dth1_freq {.name="RCU_dth1_freq",.dim=96,.dtype=dt_integer,.driver=2,.rw=rw_rw,.bitoffset={0,0,0},.width=32,.scale=0,.devreg={DTH1_Freq,DTH2_Freq,DTH3_Freq}}; +#define number_vars 13 +const t_variable variables[number_vars]={Ant_mask,RCU_mask,RCU_attenuator,RCU_band,RCU_LED0,RCU_LED1,RCU_temperature,RCU_Pwr_dig,HBA_element_beamformer_delays,RCU_ID,RCU_version,RCU_ADC_lock,RCU_dth1_freq,}; + +/*** Driver Definitions ***/ +#define number_drivers 3 +const t_driver I2C1 {.name="I2C1",.type=drv_i2c_switch,.parent=0,.parameters={1},.devreg={SWITCH_MASK}}; +const t_driver I2C_RCU {.name="I2C_RCU",.type=drv_i2c_array,.parent=0,.parameters={1,32},.devreg={}}; +const t_driver I2C_RFCHAIN {.name="I2C_RFCHAIN",.type=drv_i2c_array2,.parent=1,.parameters={3},.devreg={}}; +const t_driver I2C_HBAT {.name="I2C_HBAT",.type=drv_hba1,.parent=1,.parameters={},.devreg={}}; +const t_driver I2Cbb1 {.name="I2Cbb1",.type=drv_i2cbitbang1,.parent=1,.parameters={6,3,3},.devreg={IO1_GPIO1,IO2_GPIO2,IO2_CONF2}}; +const t_driver I2Cbb2 {.name="I2Cbb2",.type=drv_i2cbitbang1,.parent=1,.parameters={7,7,7},.devreg={IO1_GPIO2,IO2_GPIO1,IO1_CONF1}}; +const t_driver I2Cbb3 {.name="I2Cbb3",.type=drv_i2cbitbang1,.parent=1,.parameters={7,7,7},.devreg={IO1_GPIO2,IO2_GPIO1,IO1_CONF1}}; +const t_driver SPIbb1 {.name="SPIbb1",.type=drv_spibitbang1,.parent=1,.parameters={1,0,0,0},.devreg={IO3_GPIO1,IO3_GPIO1,IO3_CONF1,IO3_GPIO2}}; +const t_driver SPIbb2 {.name="SPIbb2",.type=drv_spibitbang1,.parent=1,.parameters={3,2,2,1},.devreg={IO3_GPIO1,IO3_GPIO1,IO3_CONF1,IO3_GPIO2}}; +const t_driver SPIbb3 {.name="SPIbb3",.type=drv_spibitbang1,.parent=1,.parameters={5,4,4,2},.devreg={IO3_GPIO1,IO3_GPIO1,IO3_CONF1,IO3_GPIO2}}; +//const t_driver driver_config[number_drivers]={I2C1,I2C_RCU,I2C_RFCHAIN,I2C_HBAT,I2Cbb1,I2Cbb2,I2Cbb3,SPIbb1,SPIbb2,SPIbb3,}; + +class c_drivers { + public: + c_drivers(); + drvbase* d[number_drivers]; +}; + + +#endif diff --git a/src/apsctl/yaml2head.py b/src/apsctl/yaml2head.py new file mode 100644 index 0000000000000000000000000000000000000000..82da48d7fd28da1ec79497c78437a214ceef127b --- /dev/null +++ b/src/apsctl/yaml2head.py @@ -0,0 +1,267 @@ + +yamlfile='RCU' +#structfile='structs.h' +ydir='apsctl/' +cfile='conf' + +import yaml; +D=yaml.load(open(yamlfile+'.yaml')) + + +def GetField(D,name,dev_number,default=None): + X=D.get(name,default) + return X[dev_number] if isinstance(X,list) else X; + +def Find(L,name,value): + for x in L: + if x[name]==value: + return x; + return False; + + +for i,dev in enumerate(D['drivers']): + dev['drv_id']=i; + + + +hf=open(cfile+'.h','w'); +#sf=open(ydir+structfile,'w') +hf.write("#ifndef HWDEFS_H\n") +hf.write("#define HWDEFS_H\n") +hf.write('#include "../drivers/drvbase.h"\n') +hf.write('#include "../structs.h"\n\n') + +devreglist=[] +store=0; +hf.write("/*** Device Register Definitions ***/\n") +#sf.write("struct devreg {int addr,regR,regW,store,driver;};\n") +for dev in D['device_registers']: + N=dev.get('dim',1) + name=dev['name'] + + for n in range(N): + addr=GetField(dev,'address',n,0) + devtype=GetField(dev,'driver',n) + print(addr,devtype) + if devtype: + devtype=Find(D['drivers'],'name',devtype)['drv_id'] + else: devtype=0; + if N>1: name2=name+str(n+1) + else: name2=name; + for reg in dev['registers']: + regR=GetField(reg,'address',0,0) + regW=GetField(reg,'address',1,0) + if reg.get('store',False): + store+=1; + storex=store + else: + storex=0 +# hf.write("const devreg %s {%i,%i,%i,%i,%i};\n" % (name2+'_'+reg['name'],addr,regR,regW,storex,devtype) ) + devregname=name2+'_'+reg['name']; + devreglist.append(devregname); + hf.write("const t_devreg %s {.address=%i,.register_R=%i,.register_W=%i,.store=%i,.driver=%i};\n" % (devregname,addr,regR,regW,storex,devtype) ) +hf.write("#define NumberStoreReg %i"%store) + +# int dim; +# t_dtype dtype; +# int type; +# t_rw rw; +# int bitoffset[3]; +# int width; +# t_devreg devreg[3]; +# double scale; +hf.write("\n/*** Variable Definitions ***/\n") + +varlist=[] +varcount=0; +for dev in D['variables']: + name=dev['name']; + dev['id']=varcount; + varcount+=1; + varlist.append(name); + devtype=GetField(dev,'driver',0) + if devtype: + devtype=Find(D['drivers'],'name',devtype) + if not(devtype): print ("Can not find ",name,GetField(dev,'driver',0)) + devtype=devtype['drv_id'] + else: devtype=0; + dim=int(dev.get('dim',1)); + s='{'; + for x in range(3): s+=str(GetField(dev,'bitoffset',x,0))+',' + bitoffset=s[:-1]+'}'; + s='{'; + for x in range(3): s+=str(GetField(dev,'devreg',x,0))+',' + devreg=s[:-1]+'}'; + devreg=devreg.replace('.','_') + print(devreg) + hf.write('const t_variable %s {.name="%s",.dim=%i,.dtype=%s,.driver=%i,.rw=%s,.bitoffset=%s,.width=%i,.scale=%s,.devreg=%s};\n' % ( + name, + name, + dim, + "dt_"+dev.get('dtype','integer'), + devtype, + "rw_"+dev.get('rw','hidden'), + bitoffset, + int(dev.get('width',8)), + dev.get('scale',0), + devreg + )); + +hf.write("#define number_vars %i\n" % len(varlist)) +s=''; +for v in varlist: + s+=v+',' +hf.write("const t_variable variables[number_vars]={%s};\n" % s ) + +hf.write("\n/*** Driver Definitions ***/\n") +hf.write("#define number_drivers %i\n" % len(D['drivers'])) + + +#struct t_driver { +# char* name; +# t_drivers type; +#// int parent; +#// int* parameters; +#// const t_devreg* devreg; + # "name" : {"type":"string"}, + # "type" : {"enum":["i2c","i2c_array","i2c_array2","hba1","i2cbitbang1","spibitbang1"]}, + # "parent" : {"type":"string"}, + # "parameters" : {"type":"array","items":{"type":"integer"}} , + # "registers" :{} + + +drvlist=[] +for dev in D['drivers']: + name=dev['name']; + drvlist.append(name) + parent=GetField(dev,'parent',0) + if parent: + parent=Find(D['drivers'],'name',parent) + if not(parent): print ("Can not find ",name,GetField(dev,'parent',0)) + parent=parent['drv_id'] + else: parent=0; + parameters=dev.get("parameters"); + if parameters: + s='{' + for x in parameters: + s+=str(x)+',' + parameters=s[:-1]+'}'; + else: parameters={}; + devreg=dev.get("devreg"); + if devreg: + s='{'; + for x in devreg: s+=x+',' + devreg=s[:-1]+'}'; + devreg=devreg.replace('.','_') + else: devreg={} + print(devreg) + hf.write('const t_driver %s {.name="%s",.type=%s,.parent=%i,.parameters=%s,.devreg=%s};\n' % ( + name, + name, + "drv_"+dev.get("type","i2c"), + parent, + parameters, + devreg + )); + +s=''; +for v in drvlist: + s+=v+',' +hf.write("//const t_driver driver_config[number_drivers]={%s};\n\n" % s ) + +hf.write("class c_drivers {\n") +hf.write(" public:\n") +hf.write(" c_drivers();\n") +hf.write(" drvbase* d[number_drivers];\n") +hf.write("};\n") + +hf.write("\n/*** Method Definitions ***/\n") +for i,dev in enumerate(D['methods']): + dev['id']=i +hf.write("#define number_methods %i\n" % len(D['methods'])) + +methodlist=[] +for dev in D['methods']: + name=dev['name']; + methodlist.append(name) + + hf.write('const t_instruction %s[%i]={\n' % ( + name+'_inst', + len(dev['instructions']) + )) + for inst in dev['instructions']: + for key,value in inst.items(): + if isinstance(value,list): + len1=len(value) + data='{' + for v1 in value: data+=str(v1)+',' + data+='}' + else: + len1=1; + data='{'+str(value)+'}' + + if value=='Update': + var=Find(D['variables'],'name',key) + if not(var): + print('can not find var',key) + continue; + hf.write(' {.type=inst_getvarall,.variable=%i,.devreg={0},.len=0,.data={}},\n'%(var['id'])) + elif (key=='WAIT'): + hf.write(' {.type=inst_wait,.variable=0,.devreg={0},.len=1,.data={}},\n'); + elif (Find(D['variables'],'name',key)): + var=Find(D['variables'],'name',key) + hf.write(' {.type=inst_setvar,.variable=%i,.devreg={0},.len=%i,.data=%s},\n'%(var['id'],len1,data)) + elif (Find(D['methods'],'name',key)): + var=Find(D['methods'],'name',key) + hf.write(' {.type=inst_method,.variable=%i,.devreg={0},.len=0,.data={}},\n'%(var['id'])) + elif (key.replace('.','_') in devreglist): + var=(key.replace('.','_')) + hf.write(' {.type=inst_devreg,.variable=0,.devreg=%s,.len=%i,.data=%s},\n'%(var,len1,data)) + else: + print('can not find ',key) + hf.write(' };\n') + hf.write('const t_method %s {.name="%s",.len=%i,.instructions=%s};\n' % ( + name, + name, + len(dev['instructions']), + name+'_inst' + )) + +s=''; +for v in methodlist: + s+=v+',' +hf.write("const t_method method_config[number_methods]={%s};\n\n" % s ) + + +hf.write("\n#endif\n") +hf.close() + +hf=open(cfile+'.cpp','w'); +hf.write('#include "'+cfile+'.h"\n'); +drvtypes=set([dev['type'] for dev in D['drivers']]) +for s in drvtypes: + hf.write('#include "../drivers/'+s+'.h"\n') +#include "../drivers/i2c_array.h" +# +hf.write('c_drivers::c_drivers()\n') +hf.write('{\n') +for i,dev in enumerate(D['drivers']): + cname='i_'+dev['name'] + ctype='c_'+dev['type'] + hf.write(' %s* %s=new %s(%s);\n' % (ctype,cname,ctype,dev['name'])) + hf.write(' d[%i]=%s;\n' % (i,cname)) + +for i,dev in enumerate(D['drivers']): + pr=dev.get('parent') + if not(pr): continue; + pr=Find(D['drivers'],'name',pr) + cname='i_'+dev['name'] + pname='i_'+pr['name']; + hf.write(' %s->parent=%s;\n' % (cname,pname)) + +# i_I2C_RCU->parent=i_I2C1; +hf.write('};\n') + +#sf.close() +hf.close(); +exit() diff --git a/src/drivers/RCU_switch.cpp b/src/drivers/RCU_switch.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a91e43dc45977743c9251669be7c062f3f5c8e14 --- /dev/null +++ b/src/drivers/RCU_switch.cpp @@ -0,0 +1,29 @@ +#include "RCU_switch.h" +#include "../apsctl/conf.h" +#include <iostream> + +c_RCU_switch::c_RCU_switch(const t_driver config1) : c_i2c (config1){ + state=0; +}; + +bool c_RCU_switch::I2Csend_swreg(unsigned int swstate,int addr,int reg,int len,t_buffer* data) +{ + if (swstate!=state) { + state=t_buffer(swstate); + t_buffer SW1=state & 0xff; + if (!(c_i2c::I2Csend(config.devreg->address,1,&SW1))) return false; + } + return c_i2c::I2Csend_reg(addr,reg,len,data); +} + +bool c_RCU_switch::I2Cset_switch(unsigned int swstate) +{ + if (swstate!=state) { + std::cout << "state=" << swstate << "->" << int(state) <<"\n"; + state=(swstate); + t_buffer SW1=state & 0xff; + t_buffer SW2=(state>>8) & 0xff; //TODO: implemented for DTS + if (!(c_i2c::I2Csend(config.devreg->address,1,&SW1))) return false; + } + return true; +} diff --git a/src/drivers/RCU_switch.h b/src/drivers/RCU_switch.h new file mode 100644 index 0000000000000000000000000000000000000000..bae88d24abaf529bd53aa0f674a2a6c148812929 --- /dev/null +++ b/src/drivers/RCU_switch.h @@ -0,0 +1,19 @@ +#ifndef RCU_SWITCH_H +#define RCU_SWITCH_H +#include "../structs.h" +#include "drvbase.h" +#include "i2c.h" + +class c_RCU_switch : public c_i2c { + public: + c_RCU_switch(const t_driver config1); + bool I2Cset_switch(unsigned int swstate); + bool I2Csend_swreg(unsigned int swstate,int addr,int reg,int len,t_buffer* data); + + private: + t_devreg devreg; + unsigned int state; +}; + + +#endif \ No newline at end of file diff --git a/src/drivers/drvbase.cpp b/src/drivers/drvbase.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa739bb17cb7b444bda9e813e16c2bdf761160a0 --- /dev/null +++ b/src/drivers/drvbase.cpp @@ -0,0 +1,20 @@ +#include "drvbase.h" +#include <iostream> + +drvbase::drvbase(const t_driver config1) : config (config1){}; + + +int ApplyMask(int value,int width,int bitoffset,int old){ + t_buffer mask=(1<<width)-1; + value<<=bitoffset; + mask<<=bitoffset; + return (value & mask)+(old - (old & mask)); +} +int UnMask(int value,int width,int bitoffset){ + t_buffer mask=(1<<width)-1; + value>>=bitoffset; + return (value & mask); +} + + + diff --git a/src/drivers/drvbase.h b/src/drivers/drvbase.h new file mode 100644 index 0000000000000000000000000000000000000000..13b489c0d8c97c09c77035c3878d54e2bad6473f --- /dev/null +++ b/src/drivers/drvbase.h @@ -0,0 +1,18 @@ +#ifndef DRVBASE_H +#define DRVBASE_H +#include "../structs.h" + +int ApplyMask(int value,int width,int bitoffset,int old); +int UnMask(int value,int width,int bitoffset); + +class drvbase{ + public: + drvbase(const t_driver config1); +// drvbase* parent; + virtual bool setvar(int x,int len,t_buffer* buffer,int lenmask,bool* mask){}; + virtual int getvar(int x,t_buffer* buffer,int lenmask,bool* mask){return 0;}; + virtual bool setdevreg(t_devreg devreg,int len,t_buffer* buffer,int lenmask,bool* mask){}; +// protected: + const t_driver config; +}; +#endif \ No newline at end of file diff --git a/src/drivers/hba1.cpp b/src/drivers/hba1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..08d1b1138f219c3e870b7be6a11f89ce49fa3d6e --- /dev/null +++ b/src/drivers/hba1.cpp @@ -0,0 +1,9 @@ +#include "hba1.h" +#include "../apsctl/conf.h" +#include <iostream> + + +c_hba1::c_hba1(const t_driver config1) : drvbase (config1){}; + + + diff --git a/src/drivers/hba1.h b/src/drivers/hba1.h new file mode 100644 index 0000000000000000000000000000000000000000..e532745f5e319fa588f472bb0c2b811d055e8839 --- /dev/null +++ b/src/drivers/hba1.h @@ -0,0 +1,14 @@ +#ifndef HBA1_H +#define HBA1_H +#include "../structs.h" +#include "drvbase.h" +#include "i2c_array.h" + +class c_hba1 : public drvbase { + public: + c_hba1(const t_driver config1); + c_i2c_array* parent; + + private: +}; +#endif \ No newline at end of file diff --git a/src/drivers/i2c.cpp b/src/drivers/i2c.cpp new file mode 100644 index 0000000000000000000000000000000000000000..741431818c4740da24cb22f84c9a41543b402b6e --- /dev/null +++ b/src/drivers/i2c.cpp @@ -0,0 +1,81 @@ +#include "i2c.h" +#include <iostream> +#include <linux/i2c-dev.h> +#include <i2c/smbus.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/ioctl.h> +#include <linux/types.h> +/* +__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length, + const __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, I2C_SMBUS_BLOCK_DATA, &data); +} +__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length, + const __u8 *values) +{ + union i2c_smbus_data data; + int i; + if (length > I2C_SMBUS_BLOCK_MAX) + length = I2C_SMBUS_BLOCK_MAX; + for (i = 1; i <= length; i++) + data.block[i] = values[i-1]; + data.block[0] = length; + return i2c_smbus_access(file, I2C_SMBUS_WRITE, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); +} +__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length, + __u8 *values) +{ + union i2c_smbus_data data; + int i, err; + + data.block[0] = length; + + err = i2c_smbus_access(file, I2C_SMBUS_READ, command, I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (err < 0) + return false; + + for (i = 1; i <= data.block[0]; i++) + values[i-1] = data.block[i]; + return (data.block[0]==length); +} +*/ +c_i2c::c_i2c(const t_driver config1) : drvbase (config1){ + std::cout << config.name <<": i2c server, connecting to device " << config.parameters[0] << "\n"; + char filename[20]; + snprintf(filename, 19, "/dev/i2c-%d", config.parameters[0]); + file = open(filename, O_RDWR); + if (file < 0) { + std::cout << config.name <<": Error connecting!\n"; + exit(1); + } +}; + +bool c_i2c::I2Csend_reg(int addr,int reg,int len,t_buffer* data){ + std::cout << config.name <<": i2c send to addr="<<addr<<" reg="<<reg<<" len="<<len<<" value="<<int(data[0]) <<"\n"; + if (ioctl(file, I2C_SLAVE, addr)<0) return false; + return true; +// return (i2c_smbus_write_block_data(file,reg,len,data)>=0); +} + +bool c_i2c::I2Cget_reg(int addr,int reg,int len,t_buffer* data){ + std::cout << config.name <<": i2c get from addr="<<addr<<" reg="<<reg<<" len="<<len<<" value="<<int(data[0]) <<"\n"; + if (ioctl(file, I2C_SLAVE, addr)<0) return false; + return true; +// return i2c_smbus_read_i2c_block_data(file,reg,len,data); +} + +bool c_i2c::I2Csend(int addr,int len,t_buffer* data){ + std::cout << config.name <<": i2c send to addr="<<addr<<" len="<<len<<" value="<<int(data[0])<<"\n"; +} + + diff --git a/src/drivers/i2c.h b/src/drivers/i2c.h new file mode 100644 index 0000000000000000000000000000000000000000..df46dd1b5dc57259821257cfe7d89bcdced3486e --- /dev/null +++ b/src/drivers/i2c.h @@ -0,0 +1,15 @@ +#ifndef I2C_H +#define I2C_H +#include "../structs.h" +#include "drvbase.h" +class c_i2c : public drvbase { + public: + c_i2c(const t_driver config1); + + bool I2Csend_reg(int addr,int reg,int len,t_buffer* data); + bool I2Cget_reg(int addr,int reg,int len,t_buffer* data); + bool I2Csend(int addr,int len,t_buffer* data); + private: + int file; +}; +#endif \ No newline at end of file diff --git a/src/drivers/i2c_array.cpp b/src/drivers/i2c_array.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5a00d7ccdda7c6dc8fb82cd447fc76e95d7a53bf --- /dev/null +++ b/src/drivers/i2c_array.cpp @@ -0,0 +1,95 @@ +#include "i2c_array.h" +#include "../apsctl/conf.h" +#include <iostream> + + +c_i2c_array::c_i2c_array(const t_driver config1) : drvbase (config1){ + N=config.parameters[1]; + std::cout << config.name << ": i2c array, # devices " << N << "\n"; +}; + +bool c_i2c_array::setvar(int x,int len,t_buffer* buffer,int lenmask,bool* mask){ + std::cout << config.name << ": setvar " << variables[x].name << "\n"; + int stride=((variables[x].width+variables[x].bitoffset[0]-1)>>3)+1; //1..8 bits = 1 byte, 9..16 bits=2bytes etc. + if ((variables[x].dim*stride!=len) && (len!=stride)) { + std::cout << config.name <<": setvar: wrong length " << len << "!=" << variables[x].dim <<"x" << stride << "\n"; + return false; + } + if (variables[x].rw==rw_variable) return false; + if ((lenmask>0) && (lenmask<N)){ + std::cout << config.name <<": servar: wrong mask length\n"; + return false; + } + if (len==stride) return setvar2(variables[x],0,0 ,buffer,1,mask); + else return setvar2(variables[x],0,stride,buffer,1,mask); +}; + +bool c_i2c_array::setvar2(t_variable variable,int Ndev,int stepbuf,t_buffer* buffer,int stepmask,bool* mask){ + if (variable.devreg[Ndev].register_W==-1) return true; //We can not set it e.g. temperature + for (int rcui=0;rcui<N;rcui++){ + if ((stepmask>0) && (!mask[rcui*stepmask])) continue; + parent->I2Cset_switch(1<<rcui);//todo add offset + seti2c(rcui,variable.devreg[Ndev],variable.width,variable.bitoffset[Ndev],&(buffer[rcui*stepbuf])); + } +} + +int c_i2c_array::getvar(int x,t_buffer* buffer,int lenmask,bool* mask){ + std::cout << config.name << ": getvar " << variables[x].name << "\n"; + int stride=((variables[x].width+variables[x].bitoffset[0]-1)>>3)+1; //1..8 bits = 1 byte, 9..16 bits=2bytes etc. + for (int x=0;x<stride*N;x++) buffer[x]=0; + int stepmask=1; + if (lenmask==0) stepmask=0; + getvar2(variables[x],0,stride,buffer,stepmask,mask); + return stride*N; +}; + +int c_i2c_array::getvar2(t_variable variable,int Ndev,int stepbuf,t_buffer* buffer,int stepmask,bool* mask){ + for (int rcui=0;rcui<N;rcui++){ + if ((stepmask>0) && (!mask[rcui*stepmask])) continue; + parent->I2Cset_switch(1<<rcui);//todo add offset + geti2c(rcui,variable.devreg[Ndev],variable.width,variable.bitoffset[Ndev],&(buffer[rcui*stepbuf])); + } + return N; +}; + +bool c_i2c_array::setdevreg(t_devreg devreg,int len,t_buffer* buffer,int lenmask,bool* mask){ + if ((lenmask>0) && (lenmask<N)){ + std::cout << config.name <<": setdevreg: wrong mask length\n"; + return false; + } + int stride=len/N; + int width=stride*8; + if (width==0) width=8;//todo: make this a broadcast + for (int rcui=0;rcui<N;rcui++){ + if ((lenmask>0) && (!mask[rcui])) continue; + parent->I2Cset_switch(1<<rcui);//todo add offset + seti2c(rcui,devreg,width,0,&(buffer[rcui*stride])); + } +} + +void c_i2c_array::seti2c(int rcui,const t_devreg devreg,int width,int bitoffset,t_buffer* buffer){ + t_buffer oldvalue=0; + if (devreg.store>0) { + oldvalue=storedRegs[devreg.store-1][rcui]; + buffer[0]=ApplyMask(buffer[0],width,bitoffset,oldvalue); + storedRegs[devreg.store-1][rcui]=buffer[0]; + } + + int len2=((width+bitoffset-1)>>3)+1; //1..8 bits = 1 byte, 9..16 bits=2bytes etc. + parent->I2Csend_reg(devreg.address,devreg.register_W,len2,buffer); +} + +void c_i2c_array::geti2c(int rcui,const t_devreg devreg,int width,int bitoffset,t_buffer* buffer){ + int len2=((width+bitoffset-1)>>3)+1; //1..8 bits = 1 byte, 9..16 bits=2bytes etc. + parent->I2Cget_reg(devreg.address,devreg.register_W,len2,buffer); + if (devreg.store>0) { + std::cout << "DEBUG: USED stored value="<< int(buffer[0]) <<"\n"; + buffer[0]=storedRegs[devreg.store-1][rcui]; +// storedRegs[devreg.store-1][rcui]=buffer[0]; + buffer[0]=UnMask(buffer[0],width,bitoffset); + } + +} + + + diff --git a/src/drivers/i2c_array.h b/src/drivers/i2c_array.h new file mode 100644 index 0000000000000000000000000000000000000000..a2c094e4a175bee8da3cf07f0588b152ff916a35 --- /dev/null +++ b/src/drivers/i2c_array.h @@ -0,0 +1,28 @@ +#ifndef I2C_ARRAY_H +#define I2C_ARRAY_H +#include "../structs.h" +#include "drvbase.h" +#include "RCU_switch.h" +#include "../apsctl/conf.h" + +class c_i2c_array : public drvbase { + public: + c_i2c_array(const t_driver config1); + bool setvar(int x,int len,t_buffer* buffer,int lenmask,bool* mask); + int getvar(int x,t_buffer* buffer,int lenmask,bool* mask); + + bool setvar2(t_variable variable,int Ndev,int stepbuf,t_buffer* buffer,int stepmask,bool* mask); + int getvar2(t_variable variable,int Ndev,int stepbuf,t_buffer* buffer,int stepmask,bool* mask); + + void seti2c(int rcui,const t_devreg devreg,int width,int bitoffset,t_buffer* buffer); + void geti2c(int rcui,const t_devreg devreg,int width,int bitoffset,t_buffer* buffer); + bool setdevreg(t_devreg devreg,int len,t_buffer* buffer,int lenmask,bool* mask); + + c_RCU_switch* parent; + + int N; //number of devices + private: + int switch_dev; + t_buffer storedRegs[NumberStoreReg][32]; //Todo: use N instead of 32 +}; +#endif \ No newline at end of file diff --git a/src/drivers/i2c_array2.cpp b/src/drivers/i2c_array2.cpp new file mode 100644 index 0000000000000000000000000000000000000000..5977d56291427e436e81b88e879f34e90625310c --- /dev/null +++ b/src/drivers/i2c_array2.cpp @@ -0,0 +1,41 @@ +#include "i2c_array2.h" +#include "../apsctl/conf.h" +#include <iostream> + + +c_i2c_array2::c_i2c_array2(const t_driver config1) : drvbase (config1){ + N2=config.parameters[0]; + std::cout << config.name << ": i2c array2, # devices " << N2 << "\n"; +}; + +bool c_i2c_array2::setvar(int x,int len,t_buffer* buffer,int lenmask,bool* mask){ + std::cout << config.name << ": setvar " << variables[x].name << " lenbuff=" << len << " lenmask=" << lenmask << "\n"; + int stride=(((variables[x].width+variables[x].bitoffset[0]-1)>>3)+1); //1..8 bits = 1 byte, 9..16 bits=2bytes etc. + //Todo check mask&data length! + if (len==N2){//All the same from method call TODO: make faster + for (int y=0;y<N2;y++) + parent->setvar2(variables[x],y,0,&(buffer[y]),1,mask); + } else { + for (int y=0;y<N2;y++) + parent->setvar2(variables[x],y,stride*N2,&(buffer[y]),N2,&(mask[y])); + } +} + +int c_i2c_array2::getvar(int x,t_buffer* buffer,int lenmask,bool* mask){ + int stride=((variables[x].width+variables[x].bitoffset[0]-1)>>3)+1; //1..8 bits = 1 byte, 9..16 bits=2bytes etc. +// for (int x=0;x<stride*N;x++) buffer[x]=0; + std::cout << config.name << ": getvar " << variables[x].name << " lenmask=" << lenmask << "\n"; + int stepmask=N2; + if (lenmask==0) stepmask=0; + int N=0; + if (lenmask==parent->N) + for (int y=0;y<N2;y++) + N=parent->getvar2(variables[x],y,stride*N2,&(buffer[y*stride]),1,mask); + else + for (int y=0;y<N2;y++) + N=parent->getvar2(variables[x],y,stride*N2,&(buffer[y*stride]),stepmask,&(mask[y])); + return stride*N*N2; +}; + + + diff --git a/src/drivers/i2c_array2.h b/src/drivers/i2c_array2.h new file mode 100644 index 0000000000000000000000000000000000000000..ad3027473005c47deb2ea07644ce1a5231b49fa9 --- /dev/null +++ b/src/drivers/i2c_array2.h @@ -0,0 +1,18 @@ +#ifndef I2C_ARRAY2_H +#define I2C_ARRAY2_H +#include "../structs.h" +#include "drvbase.h" +#include "i2c_array.h" + +class c_i2c_array2 : public drvbase { + public: + c_i2c_array2(const t_driver config1); + c_i2c_array* parent; + + bool setvar(int x,int len,t_buffer* buffer,int lenmask,bool* mask); + int getvar(int x,t_buffer* buffer,int lenmask,bool* mask); + + private: + int N2; +}; +#endif \ No newline at end of file diff --git a/src/drivers/i2cbitbang1.cpp b/src/drivers/i2cbitbang1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..91fcd5fbe4c36cec0390ddc791b844846792ae66 --- /dev/null +++ b/src/drivers/i2cbitbang1.cpp @@ -0,0 +1,9 @@ +#include "i2cbitbang1.h" +#include "../apsctl/conf.h" +#include <iostream> + + +c_i2cbitbang1::c_i2cbitbang1(const t_driver config1) : drvbase (config1){}; + + + diff --git a/src/drivers/i2cbitbang1.h b/src/drivers/i2cbitbang1.h new file mode 100644 index 0000000000000000000000000000000000000000..92a3bb6969fc86db77e489598123e5bf33c8c418 --- /dev/null +++ b/src/drivers/i2cbitbang1.h @@ -0,0 +1,14 @@ +#ifndef i2cbitbang1_H +#define i2cbitbang1_H +#include "../structs.h" +#include "drvbase.h" +#include "i2c_array.h" + +class c_i2cbitbang1 : public drvbase { + public: + c_i2cbitbang1(const t_driver config1); + c_i2c_array* parent; + + private: +}; +#endif \ No newline at end of file diff --git a/src/drivers/spibitbang1.cpp b/src/drivers/spibitbang1.cpp new file mode 100644 index 0000000000000000000000000000000000000000..f144883f6f716db31167b34735f454a746c8a0a7 --- /dev/null +++ b/src/drivers/spibitbang1.cpp @@ -0,0 +1,9 @@ +#include "spibitbang1.h" +#include "../apsctl/conf.h" +#include <iostream> + + +c_spibitbang1::c_spibitbang1(const t_driver config1) : drvbase (config1){}; + + + diff --git a/src/drivers/spibitbang1.h b/src/drivers/spibitbang1.h new file mode 100644 index 0000000000000000000000000000000000000000..baa0748ba1c3156800deb59af0edc5b79f7db633 --- /dev/null +++ b/src/drivers/spibitbang1.h @@ -0,0 +1,14 @@ +#ifndef spibitbang1_H +#define spibitbang1_H +#include "../structs.h" +#include "drvbase.h" +#include "i2c_array.h" + +class c_spibitbang1 : public drvbase { + public: + c_spibitbang1(const t_driver config1); + c_i2c_array* parent; + + private: +}; +#endif \ No newline at end of file diff --git a/src/interface/pypcc.capnp b/src/interface/pypcc.capnp new file mode 100644 index 0000000000000000000000000000000000000000..8486fe7b70647b2988d05590248ca69d6ff89573 --- /dev/null +++ b/src/interface/pypcc.capnp @@ -0,0 +1,14 @@ +@0x9f2c99de8c7edd7f; + +enum InstType { + varSet @0; + varRead @1; + method @2; +} + +struct OPCUAset { + id @0: UInt8; + type @1: InstType; + data @2: List(UInt8); + mask @3: List(Bool); +} diff --git a/src/interface/pypcc.capnp.c++ b/src/interface/pypcc.capnp.c++ new file mode 100644 index 0000000000000000000000000000000000000000..0747af5de3fe1071f73b7ab211f1370cc98fb16d --- /dev/null +++ b/src/interface/pypcc.capnp.c++ @@ -0,0 +1,162 @@ +// Generated by Cap'n Proto compiler, DO NOT EDIT +// source: pypcc.capnp + +#include "pypcc.capnp.h" + +namespace capnp { +namespace schemas { +static const ::capnp::_::AlignedData<29> b_b1dfe08305a4b99c = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 156, 185, 164, 5, 131, 224, 223, 177, + 12, 0, 0, 0, 2, 0, 0, 0, + 127, 221, 126, 140, 222, 153, 44, 159, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 170, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 79, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 121, 112, 99, 99, 46, 99, 97, + 112, 110, 112, 58, 73, 110, 115, 116, + 84, 121, 112, 101, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 12, 0, 0, 0, 1, 0, 2, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 29, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 66, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 13, 0, 0, 0, 58, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 118, 97, 114, 83, 101, 116, 0, 0, + 118, 97, 114, 82, 101, 97, 100, 0, + 109, 101, 116, 104, 111, 100, 0, 0, } +}; +::capnp::word const* const bp_b1dfe08305a4b99c = b_b1dfe08305a4b99c.words; +#if !CAPNP_LITE +static const uint16_t m_b1dfe08305a4b99c[] = {2, 1, 0}; +const ::capnp::_::RawSchema s_b1dfe08305a4b99c = { + 0xb1dfe08305a4b99c, b_b1dfe08305a4b99c.words, 29, nullptr, m_b1dfe08305a4b99c, + 0, 3, nullptr, nullptr, nullptr, { &s_b1dfe08305a4b99c, nullptr, nullptr, 0, 0, nullptr } +}; +#endif // !CAPNP_LITE +CAPNP_DEFINE_ENUM(InstType_b1dfe08305a4b99c, b1dfe08305a4b99c); +static const ::capnp::_::AlignedData<85> b_aaca83afea5f387e = { + { 0, 0, 0, 0, 5, 0, 6, 0, + 126, 56, 95, 234, 175, 131, 202, 170, + 12, 0, 0, 0, 1, 0, 1, 0, + 127, 221, 126, 140, 222, 153, 44, 159, + 2, 0, 7, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 21, 0, 0, 0, 170, 0, 0, 0, + 29, 0, 0, 0, 7, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 25, 0, 0, 0, 231, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 112, 121, 112, 99, 99, 46, 99, 97, + 112, 110, 112, 58, 79, 80, 67, 85, + 65, 115, 101, 116, 0, 0, 0, 0, + 0, 0, 0, 0, 1, 0, 1, 0, + 16, 0, 0, 0, 3, 0, 4, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 97, 0, 0, 0, 26, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 92, 0, 0, 0, 3, 0, 1, 0, + 104, 0, 0, 0, 2, 0, 1, 0, + 1, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 101, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 96, 0, 0, 0, 3, 0, 1, 0, + 108, 0, 0, 0, 2, 0, 1, 0, + 2, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 105, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 0, 0, 0, 3, 0, 1, 0, + 128, 0, 0, 0, 2, 0, 1, 0, + 3, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 1, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 125, 0, 0, 0, 42, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 120, 0, 0, 0, 3, 0, 1, 0, + 148, 0, 0, 0, 2, 0, 1, 0, + 105, 100, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 116, 121, 112, 101, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, + 156, 185, 164, 5, 131, 224, 223, 177, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 15, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 100, 97, 116, 97, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 6, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 109, 97, 115, 107, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 1, 0, + 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 14, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, } +}; +::capnp::word const* const bp_aaca83afea5f387e = b_aaca83afea5f387e.words; +#if !CAPNP_LITE +static const ::capnp::_::RawSchema* const d_aaca83afea5f387e[] = { + &s_b1dfe08305a4b99c, +}; +static const uint16_t m_aaca83afea5f387e[] = {2, 0, 3, 1}; +static const uint16_t i_aaca83afea5f387e[] = {0, 1, 2, 3}; +const ::capnp::_::RawSchema s_aaca83afea5f387e = { + 0xaaca83afea5f387e, b_aaca83afea5f387e.words, 85, d_aaca83afea5f387e, m_aaca83afea5f387e, + 1, 4, i_aaca83afea5f387e, nullptr, nullptr, { &s_aaca83afea5f387e, nullptr, nullptr, 0, 0, nullptr } +}; +#endif // !CAPNP_LITE +} // namespace schemas +} // namespace capnp + +// ======================================================================================= + + +// OPCUAset +constexpr uint16_t OPCUAset::_capnpPrivate::dataWordSize; +constexpr uint16_t OPCUAset::_capnpPrivate::pointerCount; +#if !CAPNP_LITE +constexpr ::capnp::Kind OPCUAset::_capnpPrivate::kind; +constexpr ::capnp::_::RawSchema const* OPCUAset::_capnpPrivate::schema; +#endif // !CAPNP_LITE + + + diff --git a/src/interface/pypcc.capnp.h b/src/interface/pypcc.capnp.h new file mode 100644 index 0000000000000000000000000000000000000000..9e968c2970b023977d2afcbe8bdb575db56635d6 --- /dev/null +++ b/src/interface/pypcc.capnp.h @@ -0,0 +1,259 @@ +// Generated by Cap'n Proto compiler, DO NOT EDIT +// source: pypcc.capnp + +#ifndef CAPNP_INCLUDED_9f2c99de8c7edd7f_ +#define CAPNP_INCLUDED_9f2c99de8c7edd7f_ + +#include <capnp/generated-header-support.h> + +#if CAPNP_VERSION != 6001 +#error "Version mismatch between generated code and library headers. You must use the same version of the Cap'n Proto compiler and library." +#endif + + +namespace capnp { +namespace schemas { + +CAPNP_DECLARE_SCHEMA(b1dfe08305a4b99c); +enum class InstType_b1dfe08305a4b99c: uint16_t { + VAR_SET, + VAR_READ, + METHOD, +}; +CAPNP_DECLARE_ENUM(InstType, b1dfe08305a4b99c); +CAPNP_DECLARE_SCHEMA(aaca83afea5f387e); + +} // namespace schemas +} // namespace capnp + + +typedef ::capnp::schemas::InstType_b1dfe08305a4b99c InstType; + +struct OPCUAset { + OPCUAset() = delete; + + class Reader; + class Builder; + class Pipeline; + + struct _capnpPrivate { + CAPNP_DECLARE_STRUCT_HEADER(aaca83afea5f387e, 1, 2) + #if !CAPNP_LITE + static constexpr ::capnp::_::RawBrandedSchema const* brand() { return &schema->defaultBrand; } + #endif // !CAPNP_LITE + }; +}; + +// ======================================================================================= + +class OPCUAset::Reader { +public: + typedef OPCUAset Reads; + + Reader() = default; + inline explicit Reader(::capnp::_::StructReader base): _reader(base) {} + + inline ::capnp::MessageSize totalSize() const { + return _reader.totalSize().asPublic(); + } + +#if !CAPNP_LITE + inline ::kj::StringTree toString() const { + return ::capnp::_::structString(_reader, *_capnpPrivate::brand()); + } +#endif // !CAPNP_LITE + + inline ::uint8_t getId() const; + + inline ::InstType getType() const; + + inline bool hasData() const; + inline ::capnp::List< ::uint8_t>::Reader getData() const; + + inline bool hasMask() const; + inline ::capnp::List<bool>::Reader getMask() const; + +private: + ::capnp::_::StructReader _reader; + template <typename, ::capnp::Kind> + friend struct ::capnp::ToDynamic_; + template <typename, ::capnp::Kind> + friend struct ::capnp::_::PointerHelpers; + template <typename, ::capnp::Kind> + friend struct ::capnp::List; + friend class ::capnp::MessageBuilder; + friend class ::capnp::Orphanage; +}; + +class OPCUAset::Builder { +public: + typedef OPCUAset Builds; + + Builder() = delete; // Deleted to discourage incorrect usage. + // You can explicitly initialize to nullptr instead. + inline Builder(decltype(nullptr)) {} + inline explicit Builder(::capnp::_::StructBuilder base): _builder(base) {} + inline operator Reader() const { return Reader(_builder.asReader()); } + inline Reader asReader() const { return *this; } + + inline ::capnp::MessageSize totalSize() const { return asReader().totalSize(); } +#if !CAPNP_LITE + inline ::kj::StringTree toString() const { return asReader().toString(); } +#endif // !CAPNP_LITE + + inline ::uint8_t getId(); + inline void setId( ::uint8_t value); + + inline ::InstType getType(); + inline void setType( ::InstType value); + + inline bool hasData(); + inline ::capnp::List< ::uint8_t>::Builder getData(); + inline void setData( ::capnp::List< ::uint8_t>::Reader value); + inline void setData(::kj::ArrayPtr<const ::uint8_t> value); + inline ::capnp::List< ::uint8_t>::Builder initData(unsigned int size); + inline void adoptData(::capnp::Orphan< ::capnp::List< ::uint8_t>>&& value); + inline ::capnp::Orphan< ::capnp::List< ::uint8_t>> disownData(); + + inline bool hasMask(); + inline ::capnp::List<bool>::Builder getMask(); + inline void setMask( ::capnp::List<bool>::Reader value); + inline void setMask(::kj::ArrayPtr<const bool> value); + inline ::capnp::List<bool>::Builder initMask(unsigned int size); + inline void adoptMask(::capnp::Orphan< ::capnp::List<bool>>&& value); + inline ::capnp::Orphan< ::capnp::List<bool>> disownMask(); + +private: + ::capnp::_::StructBuilder _builder; + template <typename, ::capnp::Kind> + friend struct ::capnp::ToDynamic_; + friend class ::capnp::Orphanage; + template <typename, ::capnp::Kind> + friend struct ::capnp::_::PointerHelpers; +}; + +#if !CAPNP_LITE +class OPCUAset::Pipeline { +public: + typedef OPCUAset Pipelines; + + inline Pipeline(decltype(nullptr)): _typeless(nullptr) {} + inline explicit Pipeline(::capnp::AnyPointer::Pipeline&& typeless) + : _typeless(kj::mv(typeless)) {} + +private: + ::capnp::AnyPointer::Pipeline _typeless; + friend class ::capnp::PipelineHook; + template <typename, ::capnp::Kind> + friend struct ::capnp::ToDynamic_; +}; +#endif // !CAPNP_LITE + +// ======================================================================================= + +inline ::uint8_t OPCUAset::Reader::getId() const { + return _reader.getDataField< ::uint8_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} + +inline ::uint8_t OPCUAset::Builder::getId() { + return _builder.getDataField< ::uint8_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS); +} +inline void OPCUAset::Builder::setId( ::uint8_t value) { + _builder.setDataField< ::uint8_t>( + ::capnp::bounded<0>() * ::capnp::ELEMENTS, value); +} + +inline ::InstType OPCUAset::Reader::getType() const { + return _reader.getDataField< ::InstType>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} + +inline ::InstType OPCUAset::Builder::getType() { + return _builder.getDataField< ::InstType>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS); +} +inline void OPCUAset::Builder::setType( ::InstType value) { + _builder.setDataField< ::InstType>( + ::capnp::bounded<1>() * ::capnp::ELEMENTS, value); +} + +inline bool OPCUAset::Reader::hasData() const { + return !_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline bool OPCUAset::Builder::hasData() { + return !_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List< ::uint8_t>::Reader OPCUAset::Reader::getData() const { + return ::capnp::_::PointerHelpers< ::capnp::List< ::uint8_t>>::get(_reader.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline ::capnp::List< ::uint8_t>::Builder OPCUAset::Builder::getData() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::uint8_t>>::get(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} +inline void OPCUAset::Builder::setData( ::capnp::List< ::uint8_t>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::uint8_t>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline void OPCUAset::Builder::setData(::kj::ArrayPtr<const ::uint8_t> value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::uint8_t>>::set(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), value); +} +inline ::capnp::List< ::uint8_t>::Builder OPCUAset::Builder::initData(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List< ::uint8_t>>::init(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), size); +} +inline void OPCUAset::Builder::adoptData( + ::capnp::Orphan< ::capnp::List< ::uint8_t>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List< ::uint8_t>>::adopt(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List< ::uint8_t>> OPCUAset::Builder::disownData() { + return ::capnp::_::PointerHelpers< ::capnp::List< ::uint8_t>>::disown(_builder.getPointerField( + ::capnp::bounded<0>() * ::capnp::POINTERS)); +} + +inline bool OPCUAset::Reader::hasMask() const { + return !_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline bool OPCUAset::Builder::hasMask() { + return !_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS).isNull(); +} +inline ::capnp::List<bool>::Reader OPCUAset::Reader::getMask() const { + return ::capnp::_::PointerHelpers< ::capnp::List<bool>>::get(_reader.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline ::capnp::List<bool>::Builder OPCUAset::Builder::getMask() { + return ::capnp::_::PointerHelpers< ::capnp::List<bool>>::get(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} +inline void OPCUAset::Builder::setMask( ::capnp::List<bool>::Reader value) { + ::capnp::_::PointerHelpers< ::capnp::List<bool>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline void OPCUAset::Builder::setMask(::kj::ArrayPtr<const bool> value) { + ::capnp::_::PointerHelpers< ::capnp::List<bool>>::set(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), value); +} +inline ::capnp::List<bool>::Builder OPCUAset::Builder::initMask(unsigned int size) { + return ::capnp::_::PointerHelpers< ::capnp::List<bool>>::init(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), size); +} +inline void OPCUAset::Builder::adoptMask( + ::capnp::Orphan< ::capnp::List<bool>>&& value) { + ::capnp::_::PointerHelpers< ::capnp::List<bool>>::adopt(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS), kj::mv(value)); +} +inline ::capnp::Orphan< ::capnp::List<bool>> OPCUAset::Builder::disownMask() { + return ::capnp::_::PointerHelpers< ::capnp::List<bool>>::disown(_builder.getPointerField( + ::capnp::bounded<1>() * ::capnp::POINTERS)); +} + + +#endif // CAPNP_INCLUDED_9f2c99de8c7edd7f_ diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c5af4e72149a06623d94bff6b1b2c1549a1621f3 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,135 @@ +#include <iostream> +#include "apsctl/conf.h" +//#include "structs.h" +#include "drivers/drvbase.h" + +#include <capnp/message.h> +#include <capnp/serialize-packed.h> +#include "interface/pypcc.capnp.h" +#include <fcntl.h> + +c_drivers drivers1; +t_buffer buffer[3072]; +bool mask[96]; +int fd_out; + +void SetResult(int id,int lenbuffer,int lenmask){ + std::cout << "Set Result lenbuf="<<lenbuffer<<" lenmask="<<lenmask<<"\n"; + ::capnp::MallocMessageBuilder message; + OPCUAset::Builder result = message.initRoot<OPCUAset>(); + result.setId(id); + result.setType(InstType::VAR_SET); + ::capnp::List<uint8_t>::Builder buf2= result.initData(lenbuffer); + for (int x=0;x<lenbuffer;x++) buf2.set(x,buffer[x]); + ::capnp::List<bool>::Builder mask2= result.initMask(lenmask); + for (int x=0;x<lenmask;x++) mask2.set(x,mask[x]); + std::cout << "Send result id=" << id << "\n"; + writePackedMessageToFd(fd_out,message); +}; + +void getvar(int varid,int lenmask){ + if ((varid<0) || (varid>number_vars)){ + std::cout << "get var: Invalid variable id!\n"; + return; + }; + int drvnum=variables[varid].driver; + std::cout << "getvar: id=" << varid << " name=" << variables[varid].name << " driver=" << drvnum << "\n"; + int lenbuffer=drivers1.d[drvnum]->getvar(varid,buffer,lenmask,mask); + SetResult(varid,lenbuffer,lenmask); +} + +void setvar(int varid,int lenbuffer,int lenmask){ + if ((varid<0) || (varid>number_vars)){ + std::cout << "Set var: Invalid variable id!\n"; + return; + }; + int drvnum=variables[varid].driver; + std::cout << "set variable call: Inst id=" << varid <<"=" << variables[varid].name << " len="<<lenbuffer<<"\n"; + //std::cout << "Mask=" << lenmask << "," << mask[0] << "," << mask[1] <<"\n"; +// std::cout << "Driver " << drvnum << " lenbuffer=" << lenbuffer << " len mask" << lenmask <<"\n"; + drivers1.d[drvnum]->setvar(varid,lenbuffer,buffer,lenmask,mask); +} + +void setdev(t_devreg devreg,int lenbuffer,int lenmask){ + std::cout << "setdev " << devreg.driver << ":"<<devreg.address <<":"<<devreg.register_W<<"\n"; + drivers1.d[devreg.driver]->setdevreg(devreg,lenbuffer,buffer,lenmask,mask); +} + +void methodcall(int varid,int lenmask) +{ + if ((varid<0) || (varid>number_methods)){ + std::cout << "Set var: Invalid method id!\n"; + return; + }; + t_method method=method_config[varid]; + for (int x=0;x<method.len;x++) + { t_instruction I=method.instructions[x]; + switch (I.type){ + case inst_setvar: + for (int x=0;x<I.len;x++) buffer[x]=I.data[x]; + setvar(I.variable,I.len,lenmask); + getvar(I.variable,lenmask); + break; + case inst_getvar: + getvar(I.variable,lenmask); + break; + case inst_getvarall: + getvar(I.variable,0); + break; + case inst_wait: + std::cout << "Sleep not implemented yet!!\n"; + break; + case inst_devreg: + for (int x=0;x<I.len;x++) buffer[x]=I.data[x]; + setdev(I.devreg,I.len,lenmask); + break; + case inst_method: + methodcall(I.variable,lenmask); + break; + } + } +} + + +int main(int argc, char *argv[]) +{ +// driver +// std::cout << drivers1.d[0]->config.name << "\n"; +// std::cout << drivers1.d[1]->config.name << "\n"; +// std::cout << drivers1.d[1]->parent->config.name << "\n"; +// c_i2c i2c1(I2C1); +// u_char buffer[32]; +// for (int x=0;x<32;x++) buffer[x]=0; +// for (int x=0;x<3;x++) buffer[x]=1; +// buffer[2]=1; +// drivers1.d[1]->setvar(1,32,buffer); +// for (int x=0;x<3;x++) buffer[x]=x; +// drivers1.d[1]->setvar(4,32,buffer); +// for (int x=0;x<number_vars;x++) +// std::cout << variables[x].name << "\n"; + std::cout << "Open read pipe\n"; + int fd_in=open("serv_to_RCU",O_RDONLY); + if (fd_in<0) return false; + fd_out=open("RCU_to_serv",O_WRONLY); + if (fd_out<0) return false; + while (1) { + ::capnp::PackedFdMessageReader message(fd_in); +// ::capnp::StreamFdMessageReader message(fd_in); + OPCUAset::Reader Inst=message.getRoot<OPCUAset>(); + // int encoded_array=capnp::messageToFlatArray(Inst); + int lenbuffer=0; + for (uint8_t value: Inst.getData()) buffer[lenbuffer++]=value; + int lenmask=0; + for (bool value: Inst.getMask()) mask[lenmask++]=value; + int varid=Inst.getId(); + if (Inst.getType()==InstType::METHOD){ + std::cout << "Method call: Inst id=" << int(Inst.getId()) <<"\n"; + methodcall(varid,lenmask); + continue; + } + if (Inst.getType()==InstType::VAR_SET) setvar(varid,lenbuffer,lenmask); + getvar(varid,lenmask); + + }; +// fclose(fd); +}; \ No newline at end of file diff --git a/src/structs.h b/src/structs.h new file mode 100644 index 0000000000000000000000000000000000000000..3ba69331d14bb595675720ad2d4cb05b32f02ff0 --- /dev/null +++ b/src/structs.h @@ -0,0 +1,43 @@ +#ifndef STRUCTS_H +#define STRUCTS_H +typedef unsigned char t_buffer; +struct t_devreg {int address,register_R,register_W,store,driver;}; +enum t_dtype {dt_double,dt_boolean,dt_string,dt_uint8,dt_uint16,dt_uint32,dt_uint64}; +enum t_rw {rw_variable,rw_rw,rw_ro,rw_hidden}; + +enum t_drivers {drv_i2c,drv_RCU_switch,drv_i2c_devs,drv_i2c_array,drv_i2c_array2,drv_hba1,drv_i2cbitbang1,drv_spibitbang1,drv_spibitbang2}; + +struct t_variable { + char* name; + int dim; + t_dtype dtype; + int driver; + t_rw rw; + int bitoffset[3]; + int width; + double scale; + const t_devreg devreg[3]; +}; +struct t_driver { + char* name; + t_drivers type; + int parent; + int parameters[4]; + const t_devreg devreg[4]; +}; +enum t_inst_type {inst_setvar,inst_getvar,inst_getvarall,inst_wait,inst_devreg,inst_method}; +struct t_instruction { + t_inst_type type; + int variable; //or method number + t_devreg devreg; + int len; + t_buffer data[8]; +}; + +struct t_method { + char* name; + int len; + const t_instruction* instructions; +}; + +#endif \ No newline at end of file