/*-----------------------------------------------------------------------------*/ /* */ /* Copyright (c) James Pearman */ /* 2013 */ /* All Rights Reserved */ /* */ /*-----------------------------------------------------------------------------*/ /* */ /* Module: vexspi.c */ /* Author: James Pearman */ /* Created: 7 May 2013 */ /* */ /* Revisions: */ /* V1.00 4 July 2013 - Initial release */ /* */ /*-----------------------------------------------------------------------------*/ /* */ /* This file is part of ConVEX. */ /* */ /* The author is supplying this software for use with the VEX cortex */ /* control system. ConVEX is free software; you can redistribute it */ /* and/or modify it under the terms of the GNU General Public License */ /* as published by the Free Software Foundation; either version 3 of */ /* the License, or (at your option) any later version. */ /* */ /* ConVEX is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ /* GNU General Public License for more details. */ /* */ /* You should have received a copy of the GNU General Public License */ /* along with this program. If not, see . */ /* */ /* A special exception to the GPL can be applied should you wish to */ /* distribute a combined work that includes ConVEX, without being obliged */ /* to provide the source code for any proprietary components. */ /* See the file exception.txt for full details of how and when the */ /* exception can be applied. */ /* */ /* The author can be contacted on the vex forums as jpearman */ /* or electronic mail using jbpearman_at_mac_dot_com */ /* Mentor for team 8888 RoboLancers, Pasadena CA. */ /* */ /*-----------------------------------------------------------------------------*/ #include "ch.h" // needs for all ChibiOS programs #include "hal.h" // hardware abstraction layer header #include #include SpiData vexSpiData; // externed in main.cpp constexpr GPTDriver *spiGpt = &GPTD2; constexpr const char *spiTeamName = CONVEX_TEAM_NAME; static thread_t *spiThread = nullptr; static SPIConfig spicfg = { nullptr, /* HW dependent part.*/ VEX_SPI_CS_PORT, VEX_SPI_CS_PIN, SPI_CR1_DFF | SPI_CR1_BR_2 | SPI_CR1_CPHA }; static void _vspi_gpt_cb(GPTDriver *); static const GPTConfig vexSpiGpt = { 1000000, /* 1MHz timer clock.*/ _vspi_gpt_cb, /* Timer callback.*/ 0, /* DIER = 0, version 2.6.1.and on */ 0 }; static const unsigned char txInitData[32] = { 0x17, 0xC9, 0x02, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00 }; static void _vspi_gpt_cb(GPTDriver *gptp) { (void)gptp; chSysLockFromISR(); if (spiThread != nullptr) { chSchReadyI(spiThread); spiThread = nullptr; } chSysUnlockFromISR(); } void vexSpiTickDelay(int ticks) { chSysLock(); spiThread = chThdGetSelfX(); gptStartOneShotI(spiGpt, ticks); chSchGoSleepS(CH_STATE_SUSPENDED); chSysUnlock(); } namespace spi { void init(void) { memncpy(&vexSpiData.txdata, txInitData, 32); vexSpiData.online = 0; spiStart(&SPID1, &spicfg); gptStart(spiGpt, &vexSpiGpt); } void update(void) { auto txbuf = reinterpret_cast(vexSpiData.txdata.data); auto rxbuf = reinterpret_cast(vexSpiData.rxdata_t.data); // configure team name if (vexSpiData.txdata.pak.state == 0x03) { // let spi know what we're sending vexSpiData.txdata.pak.type = 0x55; strncpy(reinterpret_cast(vexSpiData.txdata.data + 6), spiTeamName, 8); } // Set handshake to indicate new spi message palSetPad(VEX_SPI_ENABLE_PORT, VEX_SPI_ENABLE_PIN); for (int i = 0; i < 16; i++) { // exchange word (int) spiSelectI(&SPID1); rxbuf[i] = spi_lld_polled_exchange( &SPID1, txbuf[i] ); spiUnselectI(&SPID1); if (((i%4) == 3) && (i != 15)) { // long delay between each group of 4 words vexSpiTickDelay(73); // After 4 words negate handshake pin palClearPad(VEX_SPI_ENABLE_PORT, VEX_SPI_ENABLE_PIN); } else { vexSpiTickDelay(8); } } // increase id for next message vexSpiData.txdata.pak.id++; // check integrity of received data if( (vexSpiData.rxdata_t.data[0] == 0x17 ) && (vexSpiData.rxdata_t.data[1] == 0xC9 )) { // copy temporary data for(int i=0;i<32;i++) vexSpiData.rxdata.data[i] = vexSpiData.rxdata_t.data[i]; // Set online status if valid data status set if( (vexSpiData.rxdata.pak.status & 0x0F) == 0x08 ) vexSpiData.online = 1; // If in configuration initialize state (0x02 or 0x03) if( (vexSpiData.txdata.pak.state & 0x0E) == 0x02 ) { // check for configure request if( (vexSpiData.rxdata.pak.status & 0x0F) == 0x02 ) vexSpiData.txdata.pak.state = 0x03; // check for configure and acknowledge if( (vexSpiData.rxdata.pak.status & 0x0F) == 0x03 ) { vexSpiData.txdata.pak.state = 0x08; vexSpiData.txdata.pak.type = 0; } // Either good or bad data force to normal transmission // status will either be 0x04 or 0x08 if( (vexSpiData.rxdata.pak.status & 0x0C) != 0x00 ) { vexSpiData.txdata.pak.state = 0x08; vexSpiData.txdata.pak.type = 0; } } } else vexSpiData.errors++; } void setMotors(uint8_t *data) { memncpy(data, vexSpiData.txdata.pak.motor, 8); } const jsdata& getJoystick(int num) { return (num == 2) ? vexSpiData.rxdata.pak.js_2 : vexSpiData.rxdata.pak.js_1; } int getBatteryMain(void) { return vexSpiData.rxdata.pak.batt1 * 59; // in mV } int getBatteryBackup(void) { return vexSpiData.rxdata.pak.batt2 * 59; } int getState(void) { return vexSpiData.rxdata.pak.ctl; } }