bool Adafruit_BluefruitLE_SPI::sendPacket(uint16_t command, const uint8_t* buf, uint8_t count, uint8_t more_data) { // flush old response before sending the new command if (more_data == 0) flush(); sdepMsgCommand_t msgCmd; msgCmd.header.msg_type = SDEP_MSGTYPE_COMMAND; msgCmd.header.cmd_id_high = highByte(command); msgCmd.header.cmd_id_low = lowByte(command); msgCmd.header.length = count; msgCmd.header.more_data = (count == SDEP_MAX_PACKETSIZE) ? more_data : 0; // Copy payload if ( buf != NULL && count > 0) memcpy(msgCmd.payload, buf, count); // Starting SPI transaction if (m_sck_pin == -1) SPI.beginTransaction(bluefruitSPI); SPI_CS_ENABLE(); TimeoutTimer tt(_timeout); // Bluefruit may not be ready while ( ( spixfer(msgCmd.header.msg_type) == SPI_IGNORED_BYTE ) && !tt.expired() ) { // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself SPI_CS_DISABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_ENABLE(); } bool result = !tt.expired(); if ( result ) { // transfer the rest of the data spixfer((void*) (((uint8_t*)&msgCmd) +1), sizeof(sdepMsgHeader_t)+count-1); } SPI_CS_DISABLE(); if (m_sck_pin == -1) SPI.endTransaction(); return result; }
Adafruit_SharpMem::Adafruit_SharpMem(int8_t ss) : Adafruit_GFX(SHARPMEM_LCDWIDTH, SHARPMEM_LCDHEIGHT) { _ss = ss; _mosi = _clk = -1; // Set pin state before direction to make sure they start this way (no glitching) SPI_CS_DISABLE(); pinMode(_ss, OUTPUT); // Set the vcom bit to a defined state _sharpmem_vcom = SHARPMEM_BIT_VCOM; }
void Adafruit_SharpMem::toggleVcom(void) { if (_clk == -1) SPI.beginTransaction(sharpmemSPI); SPI_CS_ENABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); sendbyte(SHARPMEM_BIT_WRITECMD | _sharpmem_vcom); TOGGLE_VCOM; sendbyte(SHARPMEM_BIT_DUMMY); delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_DISABLE(); if (_clk == -1) SPI.endTransaction(); }
void Adafruit_SharpMem::refresh(void) { uint16_t i, totalbytes, currentline, oldline; totalbytes = (SHARPMEM_LCDWIDTH * SHARPMEM_LCDHEIGHT) / 8; if (_clk == -1) SPI.beginTransaction(sharpmemSPI); // Send the write command SPI_CS_ENABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); sendbyte(SHARPMEM_BIT_WRITECMD | _sharpmem_vcom); TOGGLE_VCOM; // Send the address for line 1 oldline = currentline = 1; sendbyte(currentline); // Send image buffer for (i=0; i<totalbytes; i++) { sendbyte(sharpmem_buffer[i]); currentline = ((i+1)/(SHARPMEM_LCDWIDTH/8)) + 1; if(currentline != oldline) { // Send end of line and address bytes sendbyte(SHARPMEM_BIT_DUMMY); if (currentline <= SHARPMEM_LCDHEIGHT) { sendbyte(currentline); } oldline = currentline; } } // Send another trailing 8 bits for the last line sendbyte(SHARPMEM_BIT_DUMMY); delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_DISABLE(); if (_clk == -1) SPI.endTransaction(); }
void Adafruit_SharpMem::clearDisplay(void) { memset(sharpmem_buffer, 0xff, (SHARPMEM_LCDWIDTH * SHARPMEM_LCDHEIGHT) / 8); if (_clk == -1) SPI.beginTransaction(sharpmemSPI); // Send the clear screen command rather than doing a HW refresh (quicker) SPI_CS_ENABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); sendbyte(_sharpmem_vcom | SHARPMEM_BIT_CLEAR); sendbyte(SHARPMEM_BIT_DUMMY); TOGGLE_VCOM; delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_DISABLE(); if (_clk == -1) SPI.endTransaction(); }
bool Adafruit_BluefruitLE_SPI::getPacket(sdepMsgResponse_t* p_response) { sdepMsgHeader_t* p_header = &p_response->header; if (m_sck_pin == -1) SPI.beginTransaction(bluefruitSPI); SPI_CS_ENABLE(); TimeoutTimer tt(_timeout); // Bluefruit may not be ready while ( ( (p_header->msg_type = spixfer(0xff)) == SPI_IGNORED_BYTE ) && !tt.expired() ) { // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself SPI_CS_DISABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_ENABLE(); } bool result=false; // Not a loop, just a way to avoid goto with error handling do { if ( tt.expired() ) break; // Look for the header while ( p_header->msg_type != SDEP_MSGTYPE_RESPONSE && p_header->msg_type != SDEP_MSGTYPE_ERROR ) { p_header->msg_type = spixfer(0xff); } memset( (&p_header->msg_type)+1, 0xff, sizeof(sdepMsgHeader_t) - 1); spixfer((&p_header->msg_type)+1, sizeof(sdepMsgHeader_t) - 1); // Command is 16-bit at odd address, may have alignment issue with 32-bit chip uint16_t cmd_id = word(p_header->cmd_id_high, p_header->cmd_id_low); // Error Message Response if ( p_header->msg_type == SDEP_MSGTYPE_ERROR ) break; // Invalid command if (!(cmd_id == SDEP_CMDTYPE_AT_WRAPPER || cmd_id == SDEP_CMDTYPE_BLE_UARTTX || cmd_id == SDEP_CMDTYPE_BLE_UARTRX) ) { break; } // Invalid length if(p_header->length > SDEP_MAX_PACKETSIZE) break; // read payload memset(p_response->payload, 0xff, p_header->length); spixfer(p_response->payload, p_header->length); result = true; } while(0); SPI_CS_DISABLE(); if (m_sck_pin == -1) SPI.endTransaction(); return result; }
bool Adafruit_BluefruitLE_SPI::getPacket(sdepMsgResponse_t* p_response) { // Wait until IRQ is asserted, double timeout since some commands take long time to start responding TimeoutTimer tt(2*_timeout); while ( !digitalRead(m_irq_pin) ) { if (tt.expired()) return false; } sdepMsgHeader_t* p_header = &p_response->header; if (m_sck_pin == -1) SPI.beginTransaction(bluefruitSPI); SPI_CS_ENABLE(); tt.set(_timeout); do { if ( tt.expired() ) break; p_header->msg_type = spixfer(0xff); if (p_header->msg_type == SPI_IGNORED_BYTE) { // Bluefruit may not be ready // Disable & Re-enable CS with a bit of delay for Bluefruit to ready itself SPI_CS_DISABLE(); delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_ENABLE(); } else if (p_header->msg_type == SPI_OVERREAD_BYTE) { // IRQ may not be pulled down by Bluefruit when returning all data in previous transfer. // This could happen when Arduino MCU is running at fast rate comparing to Bluefruit's MCU, // causing an SPI_OVERREAD_BYTE to be returned at stage. // // Walkaround: Disable & Re-enable CS with a bit of delay and keep waiting // TODO IRQ is supposed to be OFF then ON, it is better to use GPIO trigger interrupt. SPI_CS_DISABLE(); // wait for the clock to be enabled.. // while (!digitalRead(m_irq_pin)) { // if ( tt.expired() ) break; // } // if (!digitalRead(m_irq_pin)) break; delayMicroseconds(SPI_DEFAULT_DELAY_US); SPI_CS_ENABLE(); } } while (p_header->msg_type == SPI_IGNORED_BYTE || p_header->msg_type == SPI_OVERREAD_BYTE); bool result=false; // Not a loop, just a way to avoid goto with error handling do { // Look for the header // note that we should always get the right header at this point, and not doing so will really mess up things. // This whole loop isn't needed with my fix above.. while ( p_header->msg_type != SDEP_MSGTYPE_RESPONSE && p_header->msg_type != SDEP_MSGTYPE_ERROR && !tt.expired() ) { p_header->msg_type = spixfer(0xff); } if ( tt.expired() ) break; memset( (&p_header->msg_type)+1, 0xff, sizeof(sdepMsgHeader_t) - 1); spixfer((&p_header->msg_type)+1, sizeof(sdepMsgHeader_t) - 1); // Command is 16-bit at odd address, may have alignment issue with 32-bit chip uint16_t cmd_id = word(p_header->cmd_id_high, p_header->cmd_id_low); // Error Message Response if ( p_header->msg_type == SDEP_MSGTYPE_ERROR ) break; // Invalid command if (!(cmd_id == SDEP_CMDTYPE_AT_WRAPPER || cmd_id == SDEP_CMDTYPE_BLE_UARTTX || cmd_id == SDEP_CMDTYPE_BLE_UARTRX) ) { break; } // Invalid length if(p_header->length > SDEP_MAX_PACKETSIZE) break; // read payload memset(p_response->payload, 0xff, p_header->length); spixfer(p_response->payload, p_header->length); result = true; }while(0); SPI_CS_DISABLE(); if (m_sck_pin == -1) SPI.endTransaction(); return result; }