Commit 2b2068c6 authored by RollMan's avatar RollMan
Browse files

wip: implementing spi

I'm wondering how duplex I/F will be. Is the rx 1 byte? Then it goes
easy.
parent 66b705c2
Loading
Loading
Loading
Loading
+176 −0
Changes for src/hsp3/linux/hsp3gr_linux.cpp: 176 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -144,7 +144,163 @@ static int I2C_WriteByte( int ch, int value, int length )

	return 0;
}
#endif

/*----------------------------------------------------------*/
//					Raspberry Pi SPI support
/*----------------------------------------------------------*/
#ifdef HSPRASPBIAN
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>

#define HSPSPI_CHMAX 16
#define HSPSPI_DEVNAME "/dev/spidev.0."

static int spifd_ch[HSPSPI_CHMAX];

static void SPI_Init( void )
{
	int i;
	for(i=0;i<HSPSPI_CHMAX;i++) {
		spifd_ch[i] = 0;
	}
}

static void SPI_Close( int ch )
{
	if ( ( ch<0 )||( ch>=HSPSPI_CHMAX ) ) return;
	if ( spifd_ch[ch] == 0 ) return;

	close( spifd_ch[ch] );
	spifd_ch[ch] = 0;
}

static void SPI_Term( void )
{
	int i;
	for(i=0;i<HSPSPI_CHMAX;i++) {
		SPI_Close(i);
	}
}

static int SPI_Open( int ch, int ss )
{
	int fd;
  char ss_char[2];
  char devname[128] = HSPSPI_DEVNAME;

  if(ss >= 10) return -2;   // FIXME: you need `itoa()`.

	if ( ( ch<0 )||( ch>=HSPSPI_CHMAX ) ) return -1;
	if ( spifd_ch[ch] ) SPI_Close( ch );

  ss_char[0] = ss + '0';
  ss_char[1] = '\0';

  strcat(devname, ss_char);

	if((fd = open( devname, O_RDWR )) < 0){
        return 1;
    }

  uint8_t spimode = SPI_MODE_0;
  uint8_t msbfirst = 0;
  // Set read mode 0
  if (ioctl(fd, SPI_IOC_RD_MODE, &spimode) < 0) {
    close( fd );
    return 2;
  }

  // Set write mode 0
  if (ioctl(fd, SPI_IOC_WR_MODE, &spimode) < 0) {
    close( fd );
    return 2;
  }

  // Set MSB first
  if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &msbfirst) < 0) {
    close( fd );
    return 2;
  }
  if (ioctl(fd, SPI_IOC_WR_LSB_FIRST, &msbfirst) < 0) {
    close( fd );
    return 2;
  }

	spifd_ch[ch] = fd;
	return 0;
}

static int SPI_ReadByte( int ch )
{
	int res;
	unsigned char data[8];

	if ( ( ch<0 )||( ch>=HSPSPI_CHMAX ) ) return -1;
	if ( spifd_ch[ch] == 0 ) return -1;

	res = read( spifd_ch[ch], data, 1 );
	if ( res < 0 ) return -1;

	res = (int)data[0];
	return res;
}

static int SPI_ReadWord( int ch )
{
	int res;
	unsigned char data[8];

	if ( ( ch<0 )||( ch>=HSPSPI_CHMAX ) ) return -1;
	if ( spifd_ch[ch] == 0 ) return -1;

	res = read( spifd_ch[ch], data, 2 );
	if ( res < 0 ) return -1;

	res = ((int)data[1]) << 8;
	res += (int)data[0];
	return res;
}

static int SPI_WriteByte( int ch, int value, int length )
{
	int res;
	int len;
	unsigned char *data;

	if ( ( ch<0 )||( ch>=HSPSPI_CHMAX ) ) return -1;
	if ( spifd_ch[ch] == 0 ) return -1;
	if ( ( length<0 )||( length>4 ) ) return -1;

	len = length;
	if ( len == 0 ) len = 1;
	data = (unsigned char *)(&value);
	res = write( spifd_ch[ch], data, len );
	if ( res < 0 ) return -1;

	return 0;
}

static int SPI_FullDuplexByte(int ch, int* tx, int* rx, size_t size){
  int res;
  struct spi_ioc_transfer tr;

	if ( ( ch<0 )||( ch>=HSPSPI_CHMAX ) ) return -1;
  if(spifd_ch[ch] == 0) return -1;

  tr.tx_buf = (unsigned long)tx;
  tr.rx_buf = (unsigned long)rx;
  tr.len = size;
  tr.delay_usecs = 0;
  tr.bits_per_word = 8;
  tr.cs_change = 0;

  if(ioctl(spifd_ch[ch], SPI_IOC_MESSAGE(1), &tr) < 1){
    return -2;
  }

  return 0;
}
#endif

/*----------------------------------------------------------*/
@@ -421,6 +577,26 @@ static int devcontrol( char *cmd, int p1, int p2, int p3 )
		I2C_Close( p1 );
		return 0;
	}
	if (( strcmp( cmd, "spireadw" )==0 )||( strcmp( cmd, "SPIREADW" )==0 )) {
		return SPI_ReadWord( p1 );
	}
	if (( strcmp( cmd, "spiread" )==0 )||( strcmp( cmd, "SPIREAD" )==0 )) {
		return SPI_ReadByte( p1 );
	}
	if (( strcmp( cmd, "spiwrite" )==0 )||( strcmp( cmd, "SPIWRITE" )==0 )) {
		return SPI_WRITEByte( p3, p1, p2 );
	}
	if (( strcmp( cmd, "spiopen" )==0 )||( strcmp( cmd, "SPIOPEN" )==0 )) {
		return SPI_WRITEByte( p2, p1 );
	}
	if (( strcmp( cmd, "spiclose" )==0 )||( strcmp( cmd, "SPICLOSE" )==0 )) {
		SPI_Close( p1 );
    return 0;
	}
	if (( strcmp( cmd, "spifullduplex" )==0 )||( strcmp( cmd, "SPIFULLDUPLEX" )==0 )) {
    // TODO
    return 0;
	}
	return -1;
}