Line data Source code
1 : /* 2 : This program is free software: you can redistribute it and/or modify 3 : it under the terms of the GNU General Public License as published by 4 : the Free Software Foundation, either version 3 of the License, or 5 : (at your option) any later version. 6 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : /* 16 : Simulated spi buses and devices 17 : */ 18 : 19 : 20 : #include <GCS_MAVLink/GCS.h> 21 : #include <SITL/SITL.h> 22 : 23 : #include "SIM_SPI.h" 24 : #include "SIM_SPIDevice.h" 25 : 26 : #include "SIM_RAMTRON_FM25V02.h" 27 : #include "SIM_JEDEC_MX25L3206E.h" 28 : 29 : #include <signal.h> 30 : 31 : using namespace SITL; 32 : 33 : #if AP_SIM_RAMTRON_FM25V02_ENABLED 34 : static RAMTRON_FM25V02 ramtron_FM25V02; // 32kB 2-byte-addressing 35 : #endif 36 : #if AP_SIM_JEDEC_MX25L3206E_ENABLED 37 : static JEDEC_MX25L3206E jedec_MX25L3206E; 38 : #endif 39 : 40 : struct spi_device_at_cs_pin { 41 : uint8_t bus; 42 : uint8_t cs_pin; 43 : SPIDevice &device; 44 : } spi_devices[] { 45 : #if AP_SIM_RAMTRON_FM25V02_ENABLED 46 : { 0, 0, ramtron_FM25V02 }, 47 : #endif 48 : #if AP_SIM_JEDEC_MX25L3206E_ENABLED 49 : { 1, 0, jedec_MX25L3206E }, 50 : #endif 51 : }; 52 : 53 0 : void SPI::init() 54 : { 55 0 : for (auto &i : spi_devices) { 56 0 : i.device.init(); 57 : } 58 : 59 : // sanity check the spi_devices structure to ensure we don't have 60 : // two devices at the same address on the same bus: 61 0 : for (uint8_t i=0; i<ARRAY_SIZE(spi_devices)-1; i++) { 62 0 : const auto &dev_i = spi_devices[i]; 63 0 : for (uint8_t j=i+1; j<ARRAY_SIZE(spi_devices); j++) { 64 0 : const auto &dev_j = spi_devices[j]; 65 0 : if (dev_i.bus == dev_j.bus && 66 0 : dev_i.cs_pin == dev_j.cs_pin) { 67 0 : AP_HAL::panic("Two devices on the same cs_pin on the same bus"); 68 : } 69 : } 70 : } 71 0 : } 72 : 73 0 : void SPI::update(const class Aircraft &aircraft) 74 : { 75 0 : for (auto daa : spi_devices) { 76 0 : daa.device.update(aircraft); 77 : } 78 0 : } 79 : 80 263095 : int SPI::ioctl_transaction(uint8_t bus, uint8_t cs_pin, uint8_t count, spi_ioc_transfer *data) 81 : { 82 524616 : for (auto &dev_at_cs_pin : spi_devices) { 83 524616 : if (dev_at_cs_pin.cs_pin != cs_pin) { 84 0 : continue; 85 : } 86 524616 : if (dev_at_cs_pin.bus != bus) { 87 261521 : continue; 88 : } 89 263095 : return dev_at_cs_pin.device.rdwr(count, data); 90 : } 91 0 : GCS_SEND_TEXT(MAV_SEVERITY_WARNING, "Unhandled spi message: bus=%u cs_pin=%u", bus, cs_pin); 92 0 : return -1; 93 : } 94 : 95 263095 : int SPI::ioctl(uint8_t bus, uint8_t cs_pin, uint8_t ioctl_type, void *data) 96 : { 97 : uint8_t count; 98 263095 : switch (ioctl_type) { 99 190082 : case SPI_TRANSACTION_1LONG: 100 190082 : count = 1; 101 190082 : break; 102 73013 : case SPI_TRANSACTION_2LONG: 103 73013 : count = 2; 104 73013 : break; 105 0 : default: 106 0 : AP_HAL::panic("Bad transaction type"); 107 : } 108 : 109 263095 : return ioctl_transaction(bus, cs_pin, count, (spi_ioc_transfer*)data); 110 : }