From a13422fe2b044b26b667f4e045ce8cfedd6ec647 Mon Sep 17 00:00:00 2001
From: kruger <kruger@astron.nl>
Date: Thu, 18 Mar 2021 12:12:05 +0100
Subject: [PATCH] spi bitbang add

---
 src/apsctl/RCU.yaml         | 26 +++++++++---------
 src/drivers/RCU_switch.cpp  |  6 ++---
 src/drivers/drvbase.cpp     |  4 +++
 src/drivers/drvbase.h       |  3 +++
 src/drivers/i2c.cpp         | 17 +++++++++---
 src/drivers/i2c.h           |  4 ++-
 src/drivers/i2c_array.cpp   | 29 ++++++++++++--------
 src/drivers/i2c_array.h     |  5 ++--
 src/drivers/i2cbitbang1.cpp |  1 -
 src/drivers/i2cbitbang1.h   |  3 +++
 src/drivers/spibitbang1.cpp | 53 ++++++++++++++++++++++++++++++++++++-
 src/drivers/spibitbang1.h   |  7 +++++
 src/main.cpp                |  1 +
 13 files changed, 123 insertions(+), 36 deletions(-)

diff --git a/src/apsctl/RCU.yaml b/src/apsctl/RCU.yaml
index b0a5443..fda46ea 100644
--- a/src/apsctl/RCU.yaml
+++ b/src/apsctl/RCU.yaml
@@ -55,7 +55,7 @@ device_registers:
    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
+   driver: I2C1
    registers:
    - name: CONF1
      description: Direction of port1
@@ -86,7 +86,7 @@ device_registers:
  - name: ROM
    description: IO-Expander for filter selection
    address: 0x50
-   driver: I2C_RCU
+   driver: I2C1
    registers:
    - name: ID
      description: Random
@@ -99,23 +99,23 @@ device_registers:
    description: Monitor ADC on RCU
    address: 0x14
    device: LTC2495
-   driver: I2C_RCU
+   driver: I2C1
    registers:
-   - name: Ch0
+   - name: V_1v8
      address: 0xB080
-   - name: Ch1
+   - name: V_2v5
      address: 0xB880
-   - name: Ch2
+   - name: V_3v3
      address: 0xB180
-   - name: Ch3
+   - name: I_Ant0
      address: 0xB980
-   - name: Ch4
+   - name: I_Ant1
      address: 0xB280
-   - name: Ch5
+   - name: I_Ant2
      address: 0xBA80
-   - name: Ch6
+   - name: V_Ant0
      address: 0xB380
-   - name: Ch7
+   - name: V_Ant1
      address: 0xBB80
    - name: Temp
      address: 0xA0C0
@@ -125,7 +125,7 @@ device_registers:
  - name: HB_UC
    description: RCU microcontroller 
    address: 0x40
-   driver: I2C_RCU
+   driver: I2C1
    registers:
    - name: ID
      description: Device ID
@@ -135,7 +135,7 @@ device_registers:
    dim: 3
    address: [0x41,0x42,0x43]
    description: Virtual HBAT0 interface
-   driver: I2C_HBAT
+   driver: I2C1
    registers:
    - name: XY
      address: 0x10
diff --git a/src/drivers/RCU_switch.cpp b/src/drivers/RCU_switch.cpp
index a91e43d..c5f8aac 100644
--- a/src/drivers/RCU_switch.cpp
+++ b/src/drivers/RCU_switch.cpp
@@ -11,7 +11,7 @@ bool c_RCU_switch::I2Csend_swreg(unsigned int swstate,int addr,int reg,int len,t
   if (swstate!=state) {
     state=t_buffer(swstate);
     t_buffer SW1=state & 0xff;
-    if (!(c_i2c::I2Csend(config.devreg->address,1,&SW1))) return false;
+    if (!(c_i2c::I2Csend_noreg(config.devreg->address,1,&SW1))) return false;
   }
   return c_i2c::I2Csend_reg(addr,reg,len,data);
 }
@@ -19,11 +19,11 @@ bool c_RCU_switch::I2Csend_swreg(unsigned int swstate,int addr,int reg,int len,t
 bool c_RCU_switch::I2Cset_switch(unsigned int swstate)
 {
   if (swstate!=state) {
-    std::cout << "state=" << swstate << "->" << int(state) <<"\n";
+//    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;
+    if (!(c_i2c::I2Csend_noreg(config.devreg->address,1,&SW1))) return false;
   }
   return true;
 }
diff --git a/src/drivers/drvbase.cpp b/src/drivers/drvbase.cpp
index aa739bb..365a1ed 100644
--- a/src/drivers/drvbase.cpp
+++ b/src/drivers/drvbase.cpp
@@ -2,6 +2,10 @@
 #include <iostream>
 
 drvbase::drvbase(const t_driver config1) : config (config1){};
+bool drvbase::I2Csend(int addr,int reg,int len,t_buffer* data,int direction){
+        std::cout << "I2Csend "<<config.name <<" not implemented!\n";
+        return false;
+};
 
 
 int ApplyMask(int value,int width,int bitoffset,int old){
diff --git a/src/drivers/drvbase.h b/src/drivers/drvbase.h
index 13b489c..90b50e7 100644
--- a/src/drivers/drvbase.h
+++ b/src/drivers/drvbase.h
@@ -12,7 +12,10 @@ class drvbase{
     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){};
+    virtual bool I2Csend(int addr,int reg,int len,t_buffer* data,int direction);
+
 //    protected:
     const t_driver config;
+    drvbase** drivers;
 };
 #endif
\ No newline at end of file
diff --git a/src/drivers/i2c.cpp b/src/drivers/i2c.cpp
index 76b2a30..cd79120 100644
--- a/src/drivers/i2c.cpp
+++ b/src/drivers/i2c.cpp
@@ -23,8 +23,17 @@ c_i2c::c_i2c(const t_driver config1) : drvbase (config1){
   }
 };
 
+bool c_i2c::I2Csend(int addr,int reg,int len,t_buffer* data,int direction){
+  if (direction==0) { //send
+    if (reg>=0) I2Csend_reg(addr,reg,len,data);
+    else I2Csend_noreg(addr,len,data);
+  } else {
+     I2Cget_reg(addr,reg,len,data);
+  }
+}
+
 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";
+//  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);
@@ -35,15 +44,15 @@ bool c_i2c::I2Cget_reg(int addr,int reg,int len,t_buffer* data){
   if (ioctl(file, I2C_SLAVE, addr)<0) return false;
 //  return true;
   int result=i2c_smbus_read_i2c_block_data(file,reg,len,data);
-  std::cout << config.name <<": i2c get from addr="<<addr<<" reg="<<reg<<" len="<<len<<" value="<<int(data[0]) <<" result" << result<<"\n";
+//  std::cout << config.name <<": i2c get from addr="<<addr<<" reg="<<reg<<" len="<<len<<" value="<<int(data[0]) <<" result" << result<<"\n";
   return (result==len);
 }
 
-bool c_i2c::I2Csend(int addr,int len,t_buffer* data){
+bool c_i2c::I2Csend_noreg(int addr,int len,t_buffer* data){
 //  std::cout << config.name <<": i2c send to addr="<<addr<<" len="<<len<<" value="<<int(data[0])<<"\n";
   if (ioctl(file, I2C_SLAVE, addr)<0) return false;
   int result=write(file,data,len);
-  std::cout << config.name <<": i2c send to addr="<<addr<<" len="<<len<<" value="<<int(data[0])<<" result" << result<<"\n";
+//  std::cout << config.name <<": i2c send to addr="<<addr<<" len="<<len<<" value="<<int(data[0])<<" result" << result<<"\n";
   return (result>=0);
 }
 
diff --git a/src/drivers/i2c.h b/src/drivers/i2c.h
index df46dd1..711d771 100644
--- a/src/drivers/i2c.h
+++ b/src/drivers/i2c.h
@@ -6,9 +6,11 @@ class c_i2c : public drvbase {
     public:
     c_i2c(const t_driver config1);
 
+    bool I2Csend(int addr,int reg,int len,t_buffer* data,int direction);
+
     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);
+    bool I2Csend_noreg(int addr,int len,t_buffer* data);
     private:
     int file;
 };
diff --git a/src/drivers/i2c_array.cpp b/src/drivers/i2c_array.cpp
index 9883c30..afa4b25 100644
--- a/src/drivers/i2c_array.cpp
+++ b/src/drivers/i2c_array.cpp
@@ -29,7 +29,8 @@ bool c_i2c_array::setvar2(t_variable variable,int Ndev,int stepbuf,t_buffer* buf
   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]));
+    selectedRCU=rcui; 
+    seti2c(variable.devreg[Ndev],variable.width,variable.bitoffset[Ndev],&(buffer[rcui*stepbuf]));
   }
 }
 
@@ -47,7 +48,8 @@ int c_i2c_array::getvar2(t_variable variable,int Ndev,int stepbuf,t_buffer* buff
   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]));
+    selectedRCU=rcui; 
+    geti2c(variable.devreg[Ndev],variable.width,variable.bitoffset[Ndev],&(buffer[rcui*stepbuf]));
   }
   return N;
 };
@@ -62,30 +64,35 @@ bool c_i2c_array::setdevreg(t_devreg devreg,int len,t_buffer* buffer,int lenmask
   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]));
+    parent->I2Cset_switch(1<<rcui);//todo add offset
+    selectedRCU=rcui; 
+    seti2c(devreg,width,0,&(buffer[rcui*stride]));
   }
 }
 
-void c_i2c_array::seti2c(int rcui,const t_devreg devreg,int width,int bitoffset,t_buffer* buffer){
+void c_i2c_array::seti2c(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];
+      oldvalue=storedRegs[devreg.store-1][selectedRCU];
       buffer[0]=ApplyMask(buffer[0],width,bitoffset,oldvalue);
-      storedRegs[devreg.store-1][rcui]=buffer[0];
+      storedRegs[devreg.store-1][selectedRCU]=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);
+//    std::cout << "seti2c" << drivers[devreg.driver]->config.name << "\n";
+    drivers[devreg.driver]->I2Csend(devreg.address,devreg.register_W,len2,buffer,0); 
+//    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){
+void c_i2c_array::geti2c(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_R,len2,buffer);
+//    parent->I2Cget_reg(devreg.address,devreg.register_R,len2,buffer);
+//    std::cout << "geti2c" << devreg.driver << " " << drivers[devreg.driver]->config.name << "\n";
+    drivers[devreg.driver]->I2Csend(devreg.address,devreg.register_R,len2,buffer,1); 
     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];
+      storedRegs[devreg.store-1][selectedRCU]=buffer[0];
       buffer[0]=UnMask(buffer[0],width,bitoffset);
     }
 
diff --git a/src/drivers/i2c_array.h b/src/drivers/i2c_array.h
index a2c094e..beff261 100644
--- a/src/drivers/i2c_array.h
+++ b/src/drivers/i2c_array.h
@@ -14,8 +14,8 @@ class c_i2c_array : public drvbase {
     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);
+    void seti2c(const t_devreg devreg,int width,int bitoffset,t_buffer* buffer);
+    void geti2c(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;
@@ -23,6 +23,7 @@ class c_i2c_array : public drvbase {
     int N;  //number of devices
     private:
     int switch_dev;
+    int selectedRCU;
     t_buffer storedRegs[NumberStoreReg][32];  //Todo: use N instead of 32
 };
 #endif
\ No newline at end of file
diff --git a/src/drivers/i2cbitbang1.cpp b/src/drivers/i2cbitbang1.cpp
index 91fcd5f..c25bc6d 100644
--- a/src/drivers/i2cbitbang1.cpp
+++ b/src/drivers/i2cbitbang1.cpp
@@ -6,4 +6,3 @@
 c_i2cbitbang1::c_i2cbitbang1(const t_driver config1) : drvbase (config1){};
 
 
-
diff --git a/src/drivers/i2cbitbang1.h b/src/drivers/i2cbitbang1.h
index 92a3bb6..ffafa41 100644
--- a/src/drivers/i2cbitbang1.h
+++ b/src/drivers/i2cbitbang1.h
@@ -9,6 +9,9 @@ class c_i2cbitbang1 : public drvbase {
     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
index f144883..2edb3c2 100644
--- a/src/drivers/spibitbang1.cpp
+++ b/src/drivers/spibitbang1.cpp
@@ -3,7 +3,58 @@
 #include <iostream>
 
 
-c_spibitbang1::c_spibitbang1(const t_driver config1) : drvbase (config1){};
+c_spibitbang1::c_spibitbang1(const t_driver config1) : drvbase (config1){
+  CLK=config1.devreg[0];
+  SDIO=config1.devreg[1];
+  SDIOdir=config1.devreg[2];
+  CS=config1.devreg[3];
+  CLKpin=config1.parameters[0];
+  SDIOpin=config1.parameters[1];
+  CSpin=config1.parameters[2];
+};
 
+bool c_spibitbang1::I2Csend(int addr,int reg,int len,t_buffer* data,int direction){
+  t_buffer bit[1]={0};
+  if (direction==0) {  //Send
+    int data2 = ( 0x00 << 23 ) + ( 0x00 << 21 ) + ( reg << 8 ) + data[0];
+    std::cout << "SPI send" << data2 << "\n";          
+    bit[0]={0};parent->seti2c(CS,1,CSpin,bit);
+    for (int x=0;x<32;x++)
+    {
+      bit[0]=(data2>>(31-x)) & 1;  //Not that efficient, but works
+      parent->seti2c(SDIO,1,SDIOpin,bit);
+      bit[0]={1};parent->seti2c(CLK,1,CLKpin,bit);
+      bit[0]={0};parent->seti2c(CLK,1,CLKpin,bit);
+    }
+    bit[0]={1};parent->seti2c(CS,1,CSpin,bit);
+    bit[0]={1};parent->seti2c(SDIO,1,SDIOpin,bit);
+  } else {
+    int data2 = ( 0x01 << 15) + ( 0x00 << 13 ) + reg;
+    bit[0]={0};parent->seti2c(CLK,1,CLKpin,bit);
+    bit[0]={0};parent->seti2c(CS,1,CSpin,bit);//enable
+    for (int x=0;x<16;x++){
+      bit[0]={0};parent->seti2c(CLK,1,CLKpin,bit);
+      bit[0]=(data2>>(15-x)) & 1;  //Not that efficient, but works
+      parent->seti2c(SDIO,1,SDIOpin,bit);
+      bit[0]={1};parent->seti2c(CLK,1,CLKpin,bit);
+    }
+    bit[0]=1;parent->seti2c(SDIOdir,1,SDIOpin,bit);
+    bit[0]=0;parent->seti2c(CLK,1,CLKpin,bit);
 
+    data2=0;
+    for (int x=0;x<8;x++){
+        parent->geti2c(SDIO,1,SDIOpin,bit);
+        data2<<=2;
+        data2+=bit[0];
+        bit[0]=1;parent->seti2c(CLK,1,CLKpin,bit);
+        bit[0]=0;parent->seti2c(CLK,1,CLKpin,bit);
+      }
+
+    bit[0]=1;parent->seti2c(CS,1,CSpin,bit);//disable
+    bit[0]=1;parent->seti2c(SDIO,1,SDIOpin,bit);
+    bit[0]=0;parent->seti2c(SDIOdir,1,SDIOpin,bit);
+
+  }
+  return true;
+}
 
diff --git a/src/drivers/spibitbang1.h b/src/drivers/spibitbang1.h
index baa0748..6f8bf2f 100644
--- a/src/drivers/spibitbang1.h
+++ b/src/drivers/spibitbang1.h
@@ -8,7 +8,14 @@ class c_spibitbang1 : public drvbase {
     public:
     c_spibitbang1(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);
+    bool I2Csend(int addr,int reg,int len,t_buffer* data,int direction);
 
     private:
+      t_devreg CLK,SDIO,SDIOdir,CS;
+      int CLKpin,SDIOpin,CSpin;
+      int setpin(int mask,t_devreg reg,int pin,int value);
+
 };
 #endif
\ No newline at end of file
diff --git a/src/main.cpp b/src/main.cpp
index c5af4e7..7717d13 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -107,6 +107,7 @@ int main(int argc, char *argv[])
 //  drivers1.d[1]->setvar(4,32,buffer);
 //  for (int x=0;x<number_vars;x++)
 //    std::cout << variables[x].name << "\n";
+ for (int x=0;x<number_drivers;x++) drivers1.d[x]->drivers=drivers1.d;
  std::cout << "Open read pipe\n";
  int fd_in=open("serv_to_RCU",O_RDONLY);
  if (fd_in<0) return false;
-- 
GitLab