Skip to content
Snippets Groups Projects
Forked from Berkeley Lab / labRemote
332 commits behind the upstream repository.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
SPIDevCom.cpp 3.29 KiB
#include "SPIDevCom.h"

#include <linux/spi/spidev.h>

#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <cstring>

#include "ComIOException.h"

SPIDevCom::SPIDevCom(const std::string& spidev)
  : SPICom()
{
  m_fh = open(spidev.c_str(), O_RDWR);
  if(m_fh<0)
    throw ComIOException(std::string("SPIDevCom open failed: ")+std::strerror(errno));
}

SPIDevCom::~SPIDevCom()
{ }

void SPIDevCom::write_reg32(uint32_t address, uint32_t data)
{
  write_block(address,
	      {static_cast<uint8_t>((data>>24)&0xFF),
		  static_cast<uint8_t>((data>>16)&0xFF),
		  static_cast<uint8_t>((data>> 8)&0xFF),
		  static_cast<uint8_t>((data>> 0)&0xFF)});
}

void SPIDevCom::write_reg16(uint32_t address, uint16_t data)
{
  write_block(address,
	      {static_cast<uint8_t>((data>> 8)&0xFF),
		  static_cast<uint8_t>((data>> 0)&0xFF)});
}

void SPIDevCom::write_reg8 (uint32_t address, uint8_t  data)
{
  write_block(address,{data});
}

void SPIDevCom::write_reg32(uint32_t data)
{
  write_block({static_cast<uint8_t>((data>>24)&0xFF),
  	static_cast<uint8_t>((data>>16)&0xFF),
  	static_cast<uint8_t>((data>> 8)&0xFF),
  	static_cast<uint8_t>((data>> 0)&0xFF)});
}

void SPIDevCom::write_reg16(uint16_t data)
{
  write_block({static_cast<uint8_t>((data>> 8)&0xFF),
	static_cast<uint8_t>((data>> 0)&0xFF)});
}

void SPIDevCom::write_reg8 (uint8_t  data)
{
  write_block({data});
}

void SPIDevCom::write_block(uint32_t address, const std::vector<uint8_t>& data)
{
  std::vector<uint8_t> inbuf=data;
  inbuf.insert(inbuf.begin(),static_cast<uint8_t>(address&0xFF));

  write_block(inbuf);
}

void SPIDevCom::write_block(const std::vector<uint8_t>& data)
{
  struct spi_ioc_transfer msgs[1];
  memset(msgs, 0, sizeof msgs);

  msgs[0].tx_buf = (unsigned long)&data[0];
  msgs[0].len = data.size();

  if (ioctl(m_fh, SPI_IOC_MESSAGE(1), &msgs) < 0)
    throw ComIOException(std::string("SPIDevCom write_block failed: ")+std::strerror(errno));
}

uint32_t SPIDevCom::read_reg32(uint32_t address)
{
  write_reg8(address&0xFF);
  return read_reg32();
}

uint32_t SPIDevCom::read_reg24(uint32_t address)
{
  write_reg8(address&0xFF);
  return read_reg24();
}

uint16_t SPIDevCom::read_reg16(uint32_t address)
{
  write_reg8(address&0xFF);
  return read_reg16();
}

uint8_t  SPIDevCom::read_reg8 (uint32_t address)
{
  write_reg8(address&0xFF);
  return read_reg8();
}

uint32_t SPIDevCom::read_reg32()
{
  std::vector<uint8_t> data(4);
  read_block(data);
  return (data[0]<<24|data[1]<<16|data[2]<<8|data[3]);
}

uint32_t SPIDevCom::read_reg24()
{
  std::vector<uint8_t> data(3);
  read_block(data);
  return (data[0]<<16|data[1]<<8|data[2]);
}

uint16_t SPIDevCom::read_reg16()
{
  std::vector<uint8_t> data(2);
  read_block(data);
  return (data[0]<<8|data[1]);
}

uint8_t  SPIDevCom::read_reg8 ()
{
  std::vector<uint8_t> data(1);
  read_block(data);
  return data[0];
}

void SPIDevCom::read_block(uint32_t address, std::vector<uint8_t>& data)
{
  write_reg8(address&0xFF);
  read_block(data);
}

void SPIDevCom::read_block(std::vector<uint8_t>& data)
{
  struct spi_ioc_transfer msgs[1];
  memset(msgs, 0, sizeof msgs);

  msgs[0].rx_buf =(unsigned long)&data[0];
  msgs[0].len = data.size();

  if (ioctl(m_fh, SPI_IOC_MESSAGE(1), &msgs) < 0)
    throw ComIOException(std::string("SPIDevCom read_block failed: ")+std::strerror(errno));
}