/** @brief Read a Data Byte from the RFM01 FIFO over SPI The RF01 has two modes of reading the FIFO. If the FIFO level is set to 1 then FIFO data available is read out from a dedicated pin, and the FIFO bit(s) can be read from the SDO pin. Alternatively a status read bit 1 will indicate the FIFO threshold exceeded and data can be read out following the remainder of the status word. The latter mode is used here to allow bytewise reception. A status command (all zeros) is sent to the RFM01 to initiate a databyte read. The first 16 bits read out are status bits, followed by some data bits. When the FIFO fills to the trigger point FIFO_TRIGGER, the top status bit (first one transmitted) of the status word is set and can be tested. The data is available before the SCK pulse, and is read first. Normally FIFO_TRIGGER should be 8 to retrieve a single byte. It should not be close to 16 which is the maximum limit of the FIFO buffer. If FIFO_TRIGGER is less than 8 then only FIFO_TRIGGER bits are retrieved. Data is read MSB first. Return: Full status word if no data ready, or received data byte in lower byte along with upper byte of status word. */ uint16_t readDataByte() { uint8_t n = 16; uint16_t rfm01Status = 0; /* Holds the RF01 status word */ uint16_t result = 0; /* Holds the received data and status */ cbi(CS_PORT,nSEL); /* Set CS LOW */ while(n--) /* Start reading in the status word */ { rfm01Status <<= 1; /* Shift left for next bit received */ rfm01Status |= ((inb(SPI_PIN) >> SDO) & 1); /* add received bit to status */ writeSPI(0); /* Write 0 via SPI for status command */ } lastRfm01Status = rfm01Status; if ((rfm01Status & 0x8000) != 0) /* Check if FFIT is activated */ { n = FIFO_TRIGGER; if (n > 8) n = 8; /* Limit number read to a byte */ while(n--) /* Continue to send zeros to get data */ { result <<= 1; /* Shift left for next bit received */ result |= ((inb(SPI_PIN) >> SDO) & 1); /* add received bit to result */ writeSPI(0); /* Write 0 via SPI for status command */ } result |= (rfm01Status & 0xFF00); /* return upper byte of status word with result */ }
int sendSDCmd ( unsigned char c, unsigned a) // c command code // a bte address of data block { int i, r; //enable SD card enableSD(); // send a command packet (6 bytes) writeSPI( c | 0x40); //send command writeSPI( a>>24); //msb of the address writeSPI( a>>16); writeSPI( a>>8); writeSPI( a); //lsb writeSPI(0x95); //send CMD0 CRC // now wait for a response, allow to 8 bytes delay for( i=0; i<8; i++) { r=readSPI(); if ( r != 0xFF) break; } return ( r); // NOTE SDCS is still low! } // sendSDCmd
void UniversalAdapter::setCursor(uint8_t col, uint8_t row) { SPIFrame sf(this); // asserts cs on entry and deasserts on exit wait_until_ready(); uint8_t cmd = SET_CURSOR | 1; uint8_t rc = (row << 5) | (col & 0x1F); writeSPI(cmd); writeSPI(rc); }
// a LBA of sector requested // p pointer to sector buffer // returns TRUE if successful int writeSECTOR(LBA a, char *p) { unsigned r, i; // 0. check Write Protect if (getWP()) return FAIL; // 1. send WRITE command r = sendSDCmd(WRITE_SINGLE, (a << 9)); if (r == 0) // check if command was accepted { // 2. send data writeSPI(DATA_START); // send 512 bytes of data for(i=0; i<512; i++) writeSPI(*p++); // 3. send dummy CRC clockSPI(); clockSPI(); // 4. check if data accepted r = readSPI(); if ((r & 0xf) == DATA_ACCEPT) { #ifdef WRITE_LED digitalwrite(WRITE_LED, 0); #endif // 5. wait for write completion for(i=0; i<W_TIMEOUT; i++) { r = readSPI(); if (r != 0 ) break; } #ifdef WRITE_LED digitalwrite(WRITE_LED, 1); #endif } // accepted else { r = FAIL; } } // command accepted // 6. disable the card disableSD(); return (r); // return TRUE if successful } // writeSECTOR
void UniversalAdapter::write(const char *line, int len) { SPIFrame sf(this); // asserts cs on entry and deasserts on exit wait_until_ready(); if(len > 31) { // this is the limit the UPA can handle in one frame (31 bytes) len = 31; } uint8_t cmd = LCD_WRITE | (len & 0x1F); writeSPI(cmd); for (int i = 0; i < len; ++i) { writeSPI(*line++); } }
int writeDAC(float voltage){ float vref = 3.3; short hex; //xil_printf("\nValue2 = %f", voltage); // saturate voltage at -10V and +10V if(voltage > 10){ voltage = 10; }else if(voltage < -10){ voltage = -10; } //------------------------------------------------- // scale voltage from -10V --- +10V to 0V --- +3.3V voltage /= 6.0; // gain of op amp voltage += 1.65; // offset voltage; if(voltage > 3.2){ voltage = 3.2; }else if(voltage <0){ voltage = 0; } //------------------------------------------------- // convert voltage to hex hex = (voltage/vref) * 4096; hex |= DAC_CONFIG_BITS; // add configuration bits //------------------------------------------------- //xil_printf("\nDAC Value = %x", hex); writeSPI(SPI_MODE_DAC_16, hex, DAC); // write to DAC and change DAC chip select return (hex & (~0xF000)); }
void UniversalAdapter::wait_until_ready() { while(this->busy_pin->get() != 0) { // poll adapter for more room wait_ms(100); writeSPI(POLL); } }
/** @brief Write a Command to the RFM01 over SPI A command is clocked out to the RFM01 one bit at a time. All RF01 commands are 16 bit but the second parameter is kept for code compatibility with the other RF chips. At the same time a result is clocked back in one bit at a time. The result is returned as a 16 bit word. Each bit of output status is available before the clock pulse. After the last clock pulse the first FIFO data is presented. For the RFM01 receiver module the returned result is meaningless except for the status read command which is 16 bits. Parameter: 16 or 8 bit command Parameter: length of command (8 or 16) Return: Value returned from the SPI interface */ uint16_t writeCMD(uint16_t command, uint8_t n) { if (n < 16) /* For 8 bit commands */ command <<= (16-n); /* Shift command byte to upper byte */ uint16_t result = 0; /* Holds the received SDI */ cbi(CS_PORT,nSEL); /* Set CS LOW */ while(n--) /* Send All Bits MSB First */ { result <<= 1; /* Shift left for next bit to receive */ result |= ((inb(SPI_PIN) >> SDO) & 1); /* add received bit to result */ if (command & 0x8000) writeSPI(1); /* Write 1 via SDI */ else writeSPI(0); /* Write 0 via SDI */ command <<= 1; /* Shift left for next bit to send */ } sbi(CS_PORT,nSEL); /* CS HIGH - Finished Sending Command */ return result; }
void UniversalAdapter::init() { { SPIFrame sf(this); // asserts cs on entry and deasserts on exit // send an init command writeSPI(INIT_ADAPTER); } // give adapter time to init wait_ms(100); }
// c command code // a byte address of data block int sendSDCmd(unsigned char c, unsigned a) { int i, r; // enable SD card // CS low enableSD(); // send a comand packet (6 bytes) writeSPI(c | 0x40); // send command writeSPI(a>>24); // msb of the address writeSPI(a>>16); writeSPI(a>>8); writeSPI(a); // lsb writeSPI(0x95); // send CMD0 CRC // now wait for a response, allow for up to 8 bytes delay for(i=0; i<8; i++) { r = readSPI(); if (r != 0xFF) break; } return (r); /* return response FF - timeout 00 - command accepted 01 - command received, card in idle state after RESET other codes: bit 0 = Idle state bit 1 = Erase Reset bit 2 = Illegal command bit 3 = Communication CRC error bit 4 = Erase sequence error bit 5 = Address error bit 6 = Parameter error bit 7 = Always 0 */ // NOTE CSCD is still low! } // sendSDCmd
// Sets the indicator leds void UniversalAdapter::setLed(int led, bool onoff) { SPIFrame sf(this); // asserts cs on entry and deasserts on exit if(onoff) { switch(led) { case LED_FAN_ON: ledBits |= 1; break; // on case LED_HOTEND_ON: ledBits |= 2; break; // on case LED_BED_ON: ledBits |= 4; break; // on } } else { switch(led) { case LED_FAN_ON: ledBits &= ~1; break; // off case LED_HOTEND_ON: ledBits &= ~2; break; // off case LED_BED_ON: ledBits &= ~4; break; // off } } uint8_t cmd = SET_LEDS | 1; wait_until_ready(); writeSPI(cmd); writeSPI(ledBits); }
/** * Reads a single Databyte from the SPI Interface. */ uint8_t readSPI(void) { writeSPI(0xFF); return SPDR; }
unsigned char transferSPI(unsigned char data) { writeSPI(data); //write data and wait and of transmit return readSPI(); //get the data from SPI }
void writeDAC(unsigned int a) { writeSPI((a)&0x0FFF); DAC_LOAD = 0; Nop();Nop(); DAC_LOAD = 1; }
uint8_t readSPI_xx(USART_t & src) { writeSPI(src, 0xff); // Write clock return src.DATA; // Read received data }
void UniversalAdapter::clear() { SPIFrame sf(this); // asserts cs on entry and deasserts on exit wait_until_ready(); writeSPI(LCD_CLEAR); }
// cycle the buzzer pin at a certain frequency (hz) for a certain duration (ms) void UniversalAdapter::buzz(long duration, uint16_t freq) { SPIFrame sf(this); // asserts cs on entry and deasserts on exit wait_until_ready(); writeSPI(BUZZ); }
uint8_t UniversalAdapter::sendReadCmd(uint8_t cmd) { writeSPI(cmd); return writeSPI(0); }
int main() { //Step 1: Enable the SSI module using the RCGCSSI register [pg. 321] //I am using SSI2 SYSCTL->RCGCSSI = (1<<2); //Step 2: Enable the clock to the appropriate GPIO module via the RCGCGPIO register [pg. 315] //I am using Port B which is represented by bit 1 SYSCTL->RCGCGPIO = (1<<1); //Step 3: Set the GPIO AFSEL bits for the appropriate pins [pg. 632] //I am using PB 4,5,6,7 //GPIOB->AFSEL |= (1<<4)|(1<<6)|(1<<7)|(1<<5); GPIOB->AFSEL |= (1<<4)|(1<<6)|(1<<7); //To take control of the CS pin. First disable the alternate function of the pin GPIOB->AFSEL &= ~(1<<5); //Step 4: Configure the PMCn fields in the GPIOPCTL register to assign the SSI signals to the appropriate pins //A pin may have several alternate functions, here I select which alternate function I need //The SSI2 functions for pin PB 4,5,6,7 are located at 2 see Table 21-5 [pg. 1143] GPIOB->PCTL |= (2<<16)|(2<<20)|(2<<24)|(2<<28); //Pins will be used as digital pins => I must enable them. SSI IS A DIGITAL SIGNAL GPIOB->DEN |= (1<<4)|(1<<6)|(1<<7)|(1<<5); GPIOB->DIR |= (1<<5); //For each of the fram formats, the SSI is configured using the following steps: //Step 1: Ensure that the SSE bit in the SSICR1 register is clear before making any configuration changes. SSI2->CR1 &= ~(1<<1); //Step 2: Select whether the SSI is a master or slave SSI2->CR1 = 0x00000000; //Step 3: Configure the SSI clock source by writing to the SSICC register SSI2->CC =0x00; //Step 4: Configure the clock prescale divisor by writing the SSICPSR register SSI2->CPSR = 10; //WHY 1.6mHZ //Step 5: Write the SSICR0 register with the following configuration SSI2->CR0 = (0x7<<0); //BOTTOM TWO LINES ARE FOR MODE 1,1. REMOVE THEM IF YOU WANT TO CHOOSE MODE 0,0 //SSI2->CR0 |= (1<<6); //SSI2->CR0 |= (1<<7); //Step 6: Optionally, configure the uDMA channel and enable the DMA options(s) in the SSIDMACTL register //Step 7: Enalbe the SSI by setting the SSE bit in the SSICR1 register SSI2->CR1 |= (1<<1); GPIOB->DATA |= (1<<5); GPIOB->DATA &= ~(1<<5); // SS/CS low, begin transmission writeSPI(0x40); //slave addrss. Here I also mention that I want to write writeSPI(0x00); //IODIR address writeSPI(0x00); //LEDs are off for(int i = 0; i < 60; i++); GPIOB->DATA |= (1<<5); // SS/CS high, end transmission while(1) { GPIOB->DATA &= ~(1<<5); // SS/CS Low, begin transmission writeSPI(0x40); //slave addrss. Here I also mention that I want to write writeSPI(0x09); //GPIO address writeSPI(leds++); //set pins as outputs for(int i = 0; i < 60; i++); GPIOB->DATA |= (1<<5); // SS/CS High, end transmission for(int i = 0; i < 100000; i++); } return 0; }