/* * @brief Writes data into the specified accelerometer register. * * @param addr specifies where the register is * @param data to be written into the register * @returns void */ void accelerometer_write_register(uint8 addr, uint8 data) { uint32 buffer; SPISelectDevice(SPI_ACCELEROMETER); MAP_SSIDataPut(SSI0_BASE, ACCEL_WRITE_BIT | (addr & 0x3F)); MAP_SSIDataGet(SSI0_BASE, &buffer); MAP_SSIDataPut(SSI0_BASE, data); MAP_SSIDataGet(SSI0_BASE, &buffer); SPIDeselect(); }
/* * @brief Reads the accelerometer register from the specified address. * * @param addr specifies where the register is * @returns the data contained in the register */ uint8 accelerometer_read_register(uint8 addr) { uint32 buffer; SPISelectDevice(SPI_ACCELEROMETER); MAP_SSIDataPut(SSI0_BASE, ACCEL_READ_BIT | (addr & 0x3F)); MAP_SSIDataGet(SSI0_BASE, &buffer); MAP_SSIDataPut(SSI0_BASE, 0x00);//dummy read MAP_SSIDataGet(SSI0_BASE, &buffer); SPIDeselect(); return (uint8) buffer; }
//***************************************************************************** // // Internal helper function that sends a buffer of data to the TRF79x0, used // by all the functions that need to send bytes. // //***************************************************************************** void SSITRF79x0GenericWrite(unsigned char const *pucBuffer, unsigned int uiLength) { uint32_t ulDummyData; while(uiLength > 0) { // // Write address/command/data and clear SSI register of dummy data. // MAP_SSIDataPut(TRF79X0_SSI_BASE, (unsigned long)*pucBuffer); // // Wait until the SSI Module is completed sending uiLength bytes to the SSI module. // while(SSIBusy(TRF79X0_SSI_BASE) == true); MAP_SSIDataGet(TRF79X0_SSI_BASE, &ulDummyData); // // Post increment counters. // pucBuffer++; uiLength--; } }
//***************************************************************************** // // Internal helper function that receives a buffer of data from the TRF79x0, // used by all the functions that need to read bytes. // //***************************************************************************** static void SSITRF79x0GenericRead(unsigned char *pucBuffer, unsigned int uiLength) { uint32_t ulData; while(uiLength > 0) { // // Write dummy data for SSI clock and read data from SSI register. // MAP_SSIDataPut(TRF79X0_SSI_BASE, (unsigned long)SSI_NO_DATA); // // Wait until the SSI Module is completed sending uiLength bytes to the SSI module. // while(SSIBusy(TRF79X0_SSI_BASE) == true); MAP_SSIDataGet(TRF79X0_SSI_BASE, &ulData); // SSIDataGet(TRF79X0_SSI_BASE, &ulData); // // Read data into buffers and post increment counters. // *pucBuffer++ = (unsigned char)ulData; uiLength--; } }
inline uint16_t enc28_SPISend(uint16_t ui16_rw) { uint32_t ui32_rx_val; MAP_SSIDataPut(ui32_SSIx, ui16_rw); while(MAP_SSIBusy(SSI0_BASE)); MAP_SSIDataGet(ui32_SSIx, &ui32_rx_val); return (uint16_t)ui32_rx_val; }
/* * @brief Reset the top board by transmitting a reset message to bottom board. * @return void */ void hardReset() { uint32 data, i; uint8 MSP430MessageOut[MSP430_MSG_LENGTH]; // Set up bottomboard SPI channel SPIConfigureDevice(SPI_MSP430); SPISelectDeviceISR(SPI_MSP430); // Pack reset message for (i = 0; i < MSP430_CODE_LENGTH; i++) { MSP430MessageOut[i] = MSP430Code[i]; } for (i = MSP430_CODE_LENGTH; i < MSP430_MSG_LENGTH; i ++) { MSP430MessageOut[i] = 0; } MSP430MessageOut[MSP430_CMD_COMMAND_IDX] = MSP430_CMD_COMMAND_RESET; MSP430MessageOut[MSP430_CMD_CHECKSUM_IDX] = MSP430_CMD_COMMAND_RESET; // Send reset message. Syncing is done on the bottomboard side while (1) { for (i = 0; i < MSP430_MSG_LENGTH; i++) { MAP_SSIDataPutNonBlocking(SSI0_BASE, (uint32)MSP430MessageOut[i]); MAP_SSIDataGet(SSI0_BASE, &data); systemDelay(1); } } }
uint8_t spiTransfer(uint8_t data) { uint32_t ret; MAP_SSIDataPut(SSI2_BASE, data); MAP_SSIDataGet(SSI2_BASE, &ret); return (uint8_t) (ret & 0xFF); }
uint8_t spi_transferByte(uint8_t data){ unsigned long rxdata; MAP_SSIDataPut(SSI0_BASE,data); MAP_SSIDataGet(SSI0_BASE,&rxdata); return (rxdata&0xFF); }
/* * private function */ int32 accelerometer_read_register_16(uint8 addr) { uint32 data_low; uint32 data_high; int32 value; SPISelectDevice(SPI_ACCELEROMETER); MAP_SSIDataPut(SSI0_BASE, ACCEL_READ_BIT | ACCEL_ADDR_INC_BIT | (addr & 0x3F)); MAP_SSIDataGet(SSI0_BASE, &data_low); MAP_SSIDataPut(SSI0_BASE, 0x00); MAP_SSIDataGet(SSI0_BASE, &data_low); MAP_SSIDataPut(SSI0_BASE, 0x00); MAP_SSIDataGet(SSI0_BASE, &data_high); SPIDeselect(); value = (int32)((int16)((uint16)data_high << 8) | ((uint16)data_low)); // need to manually sign extend because this stupid complier does not if (value & 0x8000) { value |= 0xFFFF0000; } return value; }
/* * @brief Cancels all selections. Then immediately sends a byte of 0xFF. * * Makes all SPI devices inactive. Then immediately sends a byte of 0xFF. * @returns void */ void SPIDeselectSynchronous(void) { // do the actual deselect SPIDeselectISR(); //Send a 0xFF byte //Load up the data and send it uint32 rcvdat; MAP_SSIDataPut(SSI0_BASE, 0xFF); /* Write the data to the tx fifo */ MAP_SSIDataGet(SSI0_BASE, &rcvdat); /* flush data read during the write */ // wait until the last transfer is finished volatile uint16 i = 0; while (MAP_SSIBusy(SSI0_BASE)) { i++; if (i > SPI_MAX_XFER_IRQ_DELAY) { return; } } }
uint8_t spi_send(uint8_t c) { unsigned long val; MAP_SSIDataPut(SSI2_BASE, c); MAP_SSIDataGet(SSI2_BASE, &val); return (uint8_t)val; }
spi_data_type platform_spi_send_recv( unsigned id, spi_data_type data ) { MAP_SSIDataPut( spi_base[ id ], data ); MAP_SSIDataGet( spi_base[ id ], &data ); return data; }
/* * @brief MSP430 Boot Loader Handler * * This method sends bytes periodically to the MSP430 to handle the boot loader function * It transmits bytes about every 32us, which is about as fast as the MSP430 can Handle * @returns void */ void msp430BSLHandler(){ uint32 data; // clear the timer interrupt for the next time TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT); if(spiState == SPI_STATE_DESELECT){ SPIDeselectISR(); spiState = SPI_STATE_XMIT; MAP_TimerLoadSet(TIMER1_BASE, TIMER_B, MSP430_BSL_BYTE_PERIOD); MAP_TimerEnable(TIMER1_BASE, TIMER_B); } else if(spiState == SPI_STATE_XMIT){ //get ready to transmit and set spiState to deselect soon SPISelectDeviceISR(SPI_MSP430); spiState = SPI_STATE_DESELECT; MAP_TimerLoadSet(TIMER1_BASE, TIMER_B, MSP430_BSL_DESELECT_PERIOD); MAP_TimerEnable(TIMER1_BASE, TIMER_B); switch(armState){ case ARM_STATE_SYNC: { uint32 i; // short delay to make sure the bottomboard is ready for (i = 0; i < 10000; i++); // Send a ready message and wait for a response that the MSP is also ready armMessage = (ARM_MSG_VALID_MSG_BITS | ARM_MSG_READY_BIT); MAP_SSIDataPutNonBlocking(SSI0_BASE, (uint32)armMessage); MAP_SSIDataGet(SSI0_BASE, &data); if((uint8)data == (MSP430_MSG_VALID_MSG_BITS | MSP430_MSG_READY_BIT)) { armState = ARM_STATE_INIT_TRANSMISSION_1; } else { // Failure this time, try again armState = ARM_STATE_SYNC; } break; } case ARM_STATE_INIT_TRANSMISSION_1: // Send the message that we want to start armMessage = (ARM_MSG_VALID_MSG_BITS | ARM_MSG_NEW_TRANS_BIT); MAP_SSIDataPutNonBlocking(SSI0_BASE, (uint32)armMessage); MAP_SSIDataGet(SSI0_BASE, &data); // Get the response armState = ARM_STATE_INIT_TRANSMISSION_2; break; case ARM_STATE_INIT_TRANSMISSION_2: // Get the response back, data that is sent is junk armMessage = (ARM_MSG_VALID_MSG_BITS | ARM_MSG_READY_BIT); MAP_SSIDataPutNonBlocking(SSI0_BASE, (uint32)armMessage); MAP_SSIDataGet(SSI0_BASE, &data); if((uint8)data == (MSP430_MSG_VALID_MSG_BITS | MSP430_MSG_CONFIRM_BIT)){ // Toggle the Blinky LED blinkyLEDToggleState = !blinkyLEDToggleState; blinkyLedSet(blinkyLEDToggleState); //the last transmission was validated. We need to set up a new section of data for TX if(transmissionState == BSL_VALID_TRANSMISSION){ if(dataIndex == MSP430_PROGRAM[currentSection].MSP430_SECTION_SIZE){ // the previous data transmission included the last portion of the previous data section // so we need to increment the currentSection variable to indicate we are now on the next // data section currentSection++; dataStartAddress = MSP430_PROGRAM[currentSection].MSP430_SECTION_ADDRESS; dataIndex = 0; } else { //The previous data transmission left off somewhere in the middle of a large chunk of data. dataStartAddress = MSP430_PROGRAM[currentSection].MSP430_SECTION_ADDRESS + dataIndex; } } else if(transmissionState == BSL_INVALID_TRANSMISSION){ //last section of data failed validation. Bring dataIndex back to the starting address //of previous section for retransmission dataIndex = 0; transmissionState = BSL_VALID_TRANSMISSION; } // Calculate the length of the data to send if((dataIndex + 64) > MSP430_PROGRAM[currentSection].MSP430_SECTION_SIZE){ //we cannot construct another transmission of 64 bytes so we need to make the message //end at the end of section of data. dataLength = MSP430_PROGRAM[currentSection].MSP430_SECTION_SIZE - dataIndex; } else { dataLength = 64; } // Set up the data fields setupData[0] = dataLength; setupData[1] = (uint8)(dataStartAddress >> 8); setupData[2] = (uint8)(dataStartAddress); checksum = calcMessageChecksum(setupData, 0, 3); setupData[3] = (uint8)(checksum >> 8); setupData[4] = (uint8)checksum; setupIndex = 0; armState = ARM_STATE_SETUP_TRANSMISSION; } else {
/* * @brief Expansion0 MSP430 board ISR * * @returns void */ uint8 expand0BoardISR() { uint32 data, i; uint32 timerLoadPeriod; uint8 checksum; long val; static uint8 gripperData = 0; TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT); // Multiplex outputs (gripper/radio), set delay if (MSPSPIState == MSPSPI_STATE_XMIT_BYTE) { radioIntDisable(); SPISelectDeviceISR(SPI_EXPAND0); timerLoadPeriod = MSP430_SPI_DESELECT_PERIOD; } else if (MSPSPIState == MSPSPI_STATE_DESELECT_SPI) { SPIDeselectISR(); radioIntEnable(); timerLoadPeriod = (MSP430_SPI_BYTE_PERIOD); } MAP_TimerLoadSet(TIMER1_BASE, TIMER_B, timerLoadPeriod); MAP_TimerEnable(TIMER1_BASE, TIMER_B); // Transmit a byte or just switch state if (MSPSPIState == MSPSPI_STATE_XMIT_BYTE) { // Pack message if (expand0MessageIdx == 0) { // Grab next message from buffer if (!expand0MessageOutBufLock) { memcpy(expand0MessageOut, expand0MessageOutBuf, EXPAND0_MSG_LENGTH); } } // Rotate received buffer shiftBuffer(expand0MessageIn, EXPAND0_MSG_LENGTH); // Put data into the transmit buffer val = MAP_SSIDataPutNonBlocking(SSI0_BASE, (uint32)expand0MessageOut[expand0MessageIdx]); // Retrieve the received byte MAP_SSIDataGet(SSI0_BASE, &data); // Put byte the the end of the received buffer expand0MessageIn[EXPAND0_MSG_LENGTH - 1] = data; //Integrity checking if (expand0MessageIdx == 0) { // Checkcode for (i = 0; i < EXPAND0_CODE_LENGTH; i++) { if (expand0MessageIn[i] != expand0Code[i]) break; } if (i == EXPAND0_CODE_LENGTH) { // Checksum checksum = messageChecksum(expand0MessageIn, EXPAND0_CODE_LENGTH, EXPAND0_MSG_LENGTH); if (checksum == expand0MessageIn[EXPAND0_MSG_LENGTH - 1]) { // Avoid loading from buffer if the buffer is updating if (!expand0MessageInBufLock) { memcpy(expand0MessageInBuf, expand0MessageIn, EXPAND0_MSG_LENGTH); } } else { // Fail checksum if (showError) {cprintf("Gsum ");} } } else { // Fail checkcode if (showError) {cprintf("Gcod ");} } // Toggle MSP boards, regardless of result MSPSelect = MSP_BOTTOM_BOARD_SEL; } // Increment index, wrap back to 0 if it exceeds the range expand0MessageIdx++; if (expand0MessageIdx >= EXPAND0_MSG_LENGTH) { expand0MessageIdx = 0; } // Toggle states MSPSPIState = MSPSPI_STATE_DESELECT_SPI; } else if (MSPSPIState == MSPSPI_STATE_DESELECT_SPI) { // Toggle states MSPSPIState = MSPSPI_STATE_XMIT_BYTE; } return 0; }
uint8 bottomBoardISR() { uint32 data, i; uint32 timerLoadPeriod; uint8 checksum; long val; TimerIntClear(TIMER1_BASE, TIMER_TIMB_TIMEOUT); // Multiplex SPI (bottomboard/radio) if (MSPSPIState == MSPSPI_STATE_XMIT_BYTE) { radioIntDisable(); SPISelectDeviceISR(SPI_MSP430); timerLoadPeriod = MSP430_SPI_DESELECT_PERIOD; } else if (MSPSPIState == MSPSPI_STATE_DESELECT_SPI) { SPIDeselectISR(); radioIntEnable(); if (bootloaderSet && MSP430MessageIdx == 0) { // Deselect but then set the boot-loader to operate. msp430BSLInit(); bootloaderSet = FALSE; } else { timerLoadPeriod = MSP430_SPI_BYTE_PERIOD; } } // Set delay MAP_TimerLoadSet(TIMER1_BASE, TIMER_B, timerLoadPeriod); MAP_TimerEnable(TIMER1_BASE, TIMER_B); // Transmit message to bottomboard if (MSPSPIState == MSPSPI_STATE_XMIT_BYTE) { // Pack new message at the beginning of each cycle if (MSP430MessageIdx == 0) { // Pack code for (i = 0; i < MSP430_CODE_LENGTH; i++) { MSP430MessageOut[i] = MSP430Code[i]; } // Build and pack payload switch (msp430SystemGetCommandMessage()) { case MSP430_CMD_COMMAND_NORMAL: blinkySystemBuildMessage(&MSP430MessageOut[MSP430_CMD_SYSTEM_LED_IDX]); buttonsBuildMessage(&MSP430MessageOut[MSP430_CMD_BUTTONS_IDX]); ledsBuildMessage(&MSP430MessageOut[MSP430_CMD_LED_IDX]); break; case MSP430_CMD_COMMAND_REPROGRAM: bootloaderSet = TRUE; break; default: // Do nothing for shutdown or reset break; } msp430SystemCommandBuildMessage(&MSP430MessageOut[MSP430_CMD_COMMAND_IDX]); MSP430MessageOut[MSP430_CMD_CHECKSUM_IDX] = messageChecksum(MSP430MessageOut, MSP430_CODE_LENGTH, MSP430_MSG_LENGTH); } // Shift receive buffer shiftBuffer(MSP430MessageIn, MSP430_MSG_LENGTH); // Put data into the transmit buffer val = MAP_SSIDataPutNonBlocking(SSI0_BASE, (uint32)MSP430MessageOut[MSP430MessageIdx]); if (val == 0) { SPIBusError_SSIDataPutNonBlocking = 1; } // Retrieve the received byte MAP_SSIDataGet(SSI0_BASE, &data); // Put byte the the end of the receive buffer MSP430MessageIn[MSP430_MSG_LENGTH - 1] = data; // Check to see if we have a complete message, with correct code and checksum if (MSP430MessageIdx == 0) { // Checkcode for (i = 0; i < MSP430_CODE_LENGTH; i++) { if (MSP430MessageIn[i] != MSP430Code[i]) break; } if (i == MSP430_CODE_LENGTH) { // Checksum checksum = messageChecksum(MSP430MessageIn, MSP430_CODE_LENGTH, MSP430_MSG_LENGTH); if (checksum == MSP430MessageIn[MSP430_MSG_LENGTH - 1]) { // Process incoming message bumpSensorsUpdate(MSP430MessageIn[MSP430_MSG_BUMPER_IDX]); accelerometerUpdate(&MSP430MessageIn[MSP430_MSG_ACCEL_START_IDX]); gyroUpdate(&MSP430MessageIn[MSP430_MSG_GYRO_START_IDX]); systemBatteryVoltageUpdate(MSP430MessageIn[MSP430_MSG_VBAT_IDX]); systemUSBVoltageUpdate(MSP430MessageIn[MSP430_MSG_VUSB_IDX]); systemPowerButtonUpdate(MSP430MessageIn[MSP430_MSG_POWER_BUTTON_IDX]); systemMSPVersionUpdate(MSP430MessageIn[MSP430_MSG_VERSION_IDX]); reflectiveSensorsUpdate(&MSP430MessageIn[MSP430_MSG_REFLECT_START_IDX]); if((MSP430MessageIn[MSP430_MSG_VERSION_IDX] != 0) && (!systemMSP430CommsValid)) { systemMSP430CommsValid = TRUE; } } else { checksumFailure++; // Fail checksum if (showError) {cprintf("Bsum ");} } } else { // Fail checkcode if (showError) {cprintf("Bcod ");} } // Toggle MSP boards, regardless of result if (expand0En) { MSPSelect = MSP_EXPAND0_BOARD_SEL; } } // Increment index, wrap back to 0 if it exceeds the range MSP430MessageIdx++; if (MSP430MessageIdx >= MSP430_MSG_LENGTH) { MSP430MessageIdx = 0; } // Toggle states MSPSPIState = MSPSPI_STATE_DESELECT_SPI; } else if (MSPSPIState == MSPSPI_STATE_DESELECT_SPI) { // Toggle states MSPSPIState = MSPSPI_STATE_XMIT_BYTE; } return 0; }