/******************************************************************************* * rc_spi.c * * Functions for interfacing with SPI1 on the beaglebone and Robotics Cape *******************************************************************************/ #include "libraries/roboticscape.h" #include "libraries/rc_defs.h" #include "libraries/mmap/rc_mmap_gpio_adc.h" // for toggling gpio pins #include #include #include #include // for memset #include #include #include #include #include "rc_spi_mod.h" #define SPI10_PATH "/dev/spidev1.0" #define SPI11_PATH "/dev/spidev1.1" #define SPI_MAX_SPEED 24000000 // 24mhz #define SPI_MIN_SPEED 1000 // 1khz #define SPI_BITS_PER_WORD 8 #define SPI_BUF_SIZE 2 int fd[2]; // file descriptor for SPI1_PATH device cs0, cs1 int initialized[2]; // set to 1 after successful initialization int gpio_ss[4]; // holds gpio pins for slave select lines struct spi_ioc_transfer xfer[2]; // ioctl transfer structs for tx & rx char tx_buf[SPI_BUF_SIZE]; char rx_buf[SPI_BUF_SIZE]; /******************************************************************************* * @ int rc_spi_init_mod(ss_mode_t ss_mode, int spi_mode, int speed_hz, int slave) * * Functions for interfacing with SPI1 on the beaglebone and Robotics Cape * choose either slave=1 or slave=2. it won't matter since data lines are shared * use ss_mode = SS_MODE_MANUAL to manually control SS over GPIO *******************************************************************************/ int rc_spi_init_mod(ss_mode_t ss_mode, int spi_mode, int speed_hz, int slave){ int bits = SPI_BITS_PER_WORD; int mode_proper; int i = 0; // sanity checks if(speed_hz>SPI_MAX_SPEED || speed_hz=1\n"); return -1; } // fill in ioctl xfer struct. speed and bits were already set in initialize xfer[0].rx_buf = 0; xfer[0].tx_buf = (unsigned long) data; xfer[0].len = bytes; // send ret = ioctl(fd[slave-1], SPI_IOC_MESSAGE(1), xfer); if(ret<0){ printf("ERROR: SPI_IOC_MESSAGE_FAILED\n"); return -1; } return ret; } */ /******************************************************************************* * int rc_spi_read_bytes(char* data, int bytes, int slave) * * Like rc_uart_read_bytes, this lets you read a byte sequence without sending. *******************************************************************************/ /* int rc_spi_read_bytes(char* data, int bytes, int slave){ int ret; // sanity checks if(slave!=1 && slave!=2){ printf("ERROR: SPI slave must be 1 or 2\n"); return -1; } if(initialized[slave-1]==0){ printf("ERROR: SPI slave %d not yet initialized\n", slave); return -1; } if(bytes<1){ printf("ERROR: rc_spi_read_bytes, bytes to read must be >=1\n"); return -1; } // fill in ioctl xfer struct. speed and bits were already set in initialize xfer[0].rx_buf = (unsigned long) data;; xfer[0].tx_buf = 0; xfer[0].len = bytes; // receive ret=ioctl(fd[slave-1], SPI_IOC_MESSAGE(1), xfer); if(ret<0){ printf("ERROR: SPI_IOC_MESSAGE_FAILED\n"); return -1; } return ret; } */ /******************************************************************************* * @ int rc_spi_transfer(char* tx_data, int tx_bytes, char* rx_data, int slave) * * This is a generic wrapper for the ioctl spi transfer function. It lets the * user send any sequence of bytes and read the response. The return value is * the number of bytes received or -1 on error. *******************************************************************************/ /* int rc_spi_transfer(char* tx_data, int tx_bytes, char* rx_data, int slave){ int ret; // sanity checks if(slave!=1 && slave!=2){ printf("ERROR: SPI slave must be 1 or 2\n"); return -1; } if(initialized[slave-1]==0){ printf("ERROR: SPI slave %d not yet initialized\n", slave); return -1; } if(tx_bytes<1){ printf("ERROR: spi1_transfer, bytes must be >=1\n"); } // fill in send struct xfer[0].tx_buf = (unsigned long) tx_data; xfer[0].rx_buf = (unsigned long) rx_data; xfer[0].len = tx_bytes; ret=ioctl(fd[slave-1], SPI_IOC_MESSAGE(1), xfer); if(ret<0){ printf("SPI_IOC_MESSAGE_FAILED\n"); return -1; } return ret; } */ /******************************************************************************* * int rc_spi_write_reg_byte(char reg_addr, char data, int slave) * * Used for writing a byte value to a register. This sends in order the address * and byte to be written. It also sets the MSB of the register to 1 which * indicates a write operation on many ICs. If you do not want this particular * functionality, use spi1_send_bytes() to send a byte string of your choosing. *******************************************************************************/ /* int rc_spi_write_reg_byte(char reg_addr, char data, int slave){ // sanity checks if(slave!=1 && slave!=2){ printf("ERROR: SPI slave must be 1 or 2\n"); return -1; } if(initialized[slave-1]==0){ printf("ERROR: SPI slave %d not yet initialized\n", slave); return -1; } //wipe TX buffer and fill in register address and data memset(tx_buf, 0, sizeof tx_buf); tx_buf[0] = reg_addr | 0x80; /// set MSBit = 1 to indicate it's a write tx_buf[1] = data; // fill in ioctl zfer struct. speed and bits were already set in initialize xfer[0].tx_buf = (unsigned long) tx_buf; xfer[0].len = 2; // send if(ioctl(fd[slave-1], SPI_IOC_MESSAGE(1), xfer)<0){ printf("ERROR: SPI_IOC_MESSAGE_FAILED\n"); return -1; } return 0; } */ /******************************************************************************* * char rc_spi_read_reg_byte(char reg_addr, int slave) * * Reads a single character located at address reg_addr. This is accomplished * by sending the reg_addr with the MSB set to 0 indicating a read on many * ICs. *******************************************************************************/ /* char rc_spi_read_reg_byte(char reg_addr, int slave){ // sanity checks if(slave!=1 && slave!=2){ printf("ERROR: SPI slave must be 1 or 2\n"); return -1; } if(initialized[slave-1]==0){ printf("ERROR: SPI slave %d not yet initialized\n", slave); return -1; } // wipe buffers memset(tx_buf, 0, sizeof tx_buf); memset(rx_buf, 0, sizeof rx_buf); // fill in xfer struct tx_buf[0] = reg_addr & 0x7f; // MSBit = 0 to indicate it's a read xfer[0].tx_buf = (unsigned long) tx_buf; xfer[0].rx_buf = (unsigned long) rx_buf; xfer[0].len = 1; if(ioctl(fd[slave-1], SPI_IOC_MESSAGE(1), xfer)<0){ printf("SPI_IOC_MESSAGE_FAILED\n"); return -1; } return rx_buf[0]; } */ /******************************************************************************* * int rc_spi_read_reg_bytes(char reg_addr, char* data, int bytes, int slave) * * Reads multiple bytes located at address reg_addr. This is accomplished * by sending the reg_addr with the MSB set to 0 indicating a read on many * ICs. *******************************************************************************/ /* int rc_spi_read_reg_bytes(char reg_addr, char* data, int bytes, int slave){ int ret; // sanity checks if(slave!=1 && slave!=2){ printf("ERROR: SPI slave must be 1 or 2\n"); return -1; } if(initialized[slave-1]==0){ printf("ERROR: SPI slave %d not yet initialized\n", slave); return -1; } if(bytes<1){ printf("ERROR: spi1_read_reg_bytes, bytes must be >=1\n"); } // wipe buffers memset(tx_buf, 0, sizeof tx_buf); memset(data, 0, bytes); // fill in send struct tx_buf[0] = reg_addr & 0x7f; // MSBit = 0 to indicate it's a read xfer[0].tx_buf = (unsigned long) tx_buf; xfer[0].rx_buf = 0; xfer[0].len = 1; // fill in receive struct xfer[1].tx_buf = 0; xfer[1].rx_buf = (unsigned long) data; xfer[1].len = bytes; ret=ioctl(fd[slave-1], SPI_IOC_MESSAGE(2), xfer); if (ret<0){ printf("SPI_IOC_MESSAGE_FAILED\n"); return -1; } return 0; } */