Future Electronics
/
sequana-ble-lab-base
This is a basic code to be used for Sequana BLE Lab exercises.
source/Kmx65.cpp@4:44690f4495ef, 2019-03-22 (annotated)
- Committer:
- lru
- Date:
- Fri Mar 22 10:11:59 2019 +0000
- Revision:
- 4:44690f4495ef
- Parent:
- 2:06e62a299a74
Initialized properly device name characteristic and changed type of advertising MAC address used to guarantee uniqueness.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
lru | 0:ff033dfc838b | 1 | /* |
lru | 0:ff033dfc838b | 2 | * Copyright (c) 2017-2019 Future Electronics |
lru | 0:ff033dfc838b | 3 | * |
lru | 0:ff033dfc838b | 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
lru | 0:ff033dfc838b | 5 | * you may not use this file except in compliance with the License. |
lru | 0:ff033dfc838b | 6 | * You may obtain a copy of the License at |
lru | 0:ff033dfc838b | 7 | * |
lru | 0:ff033dfc838b | 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
lru | 0:ff033dfc838b | 9 | * |
lru | 0:ff033dfc838b | 10 | * Unless required by applicable law or agreed to in writing, software |
lru | 0:ff033dfc838b | 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
lru | 0:ff033dfc838b | 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
lru | 0:ff033dfc838b | 13 | * See the License for the specific language governing permissions and |
lru | 0:ff033dfc838b | 14 | * limitations under the License. |
lru | 0:ff033dfc838b | 15 | */ |
lru | 0:ff033dfc838b | 16 | |
lru | 0:ff033dfc838b | 17 | #include <mbed.h> |
lru | 2:06e62a299a74 | 18 | #include "Kmx65.h" |
lru | 0:ff033dfc838b | 19 | |
lru | 0:ff033dfc838b | 20 | |
lru | 2:06e62a299a74 | 21 | Kmx65Driver::Kmx65Driver(SPI& bus, PinName cs) : _spi(bus), _chip_select(cs) |
lru | 0:ff033dfc838b | 22 | { |
lru | 0:ff033dfc838b | 23 | _chip_select = 1; |
lru | 0:ff033dfc838b | 24 | }; |
lru | 0:ff033dfc838b | 25 | |
lru | 0:ff033dfc838b | 26 | |
lru | 0:ff033dfc838b | 27 | // For each 8-bit register access must first send register address. |
lru | 2:06e62a299a74 | 28 | uint8_t Kmx65Driver::spi_transaction(uint8_t address, uint8_t data) { |
lru | 0:ff033dfc838b | 29 | _chip_select = 0; |
lru | 0:ff033dfc838b | 30 | |
lru | 0:ff033dfc838b | 31 | _tx_buffer[0] = address; |
lru | 0:ff033dfc838b | 32 | _tx_buffer[1] = data; |
lru | 0:ff033dfc838b | 33 | |
lru | 0:ff033dfc838b | 34 | _spi.write(_tx_buffer, 2, _rx_buffer, 2); |
lru | 0:ff033dfc838b | 35 | _chip_select = 1; |
lru | 0:ff033dfc838b | 36 | // SSEL needs to be set inactive for at least 100ns. |
lru | 0:ff033dfc838b | 37 | for (uint32_t j = 0; j < 16; ++j) { |
lru | 0:ff033dfc838b | 38 | volatile uint32_t tmp = 0; |
lru | 0:ff033dfc838b | 39 | } |
lru | 0:ff033dfc838b | 40 | return _rx_buffer[1]; |
lru | 0:ff033dfc838b | 41 | } |
lru | 0:ff033dfc838b | 42 | |
lru | 2:06e62a299a74 | 43 | /** Read multiple bytes/registers from KMX chip. |
lru | 0:ff033dfc838b | 44 | * The tricky part here is that the first byte read corresponds to address write |
lru | 0:ff033dfc838b | 45 | * and is always 0, so it should be ignored and the count should be 1 more than |
lru | 0:ff033dfc838b | 46 | * the really required data. |
lru | 0:ff033dfc838b | 47 | */ |
lru | 2:06e62a299a74 | 48 | void Kmx65Driver::spi_read_multiple(uint8_t reg_address, uint8_t *data, uint32_t count) { |
lru | 0:ff033dfc838b | 49 | _chip_select = 0; |
lru | 0:ff033dfc838b | 50 | |
lru | 0:ff033dfc838b | 51 | _tx_buffer[0] = reg_address | READ_MASK; |
lru | 0:ff033dfc838b | 52 | |
lru | 0:ff033dfc838b | 53 | _spi.write(_tx_buffer, 1, (char*)data, count); |
lru | 0:ff033dfc838b | 54 | _chip_select = 1; |
lru | 0:ff033dfc838b | 55 | // SSEL needs to be set inactive for at least 100ns. |
lru | 0:ff033dfc838b | 56 | for (uint32_t j = 0; j < 16; ++j) { |
lru | 0:ff033dfc838b | 57 | volatile uint32_t tmp = 0; |
lru | 0:ff033dfc838b | 58 | } |
lru | 0:ff033dfc838b | 59 | } |
lru | 0:ff033dfc838b | 60 | |
lru | 0:ff033dfc838b | 61 | |
lru | 0:ff033dfc838b | 62 | #define AccScale(x) (int16_t)(((int32_t)(x) * 2 * 16000) >> 16) |
lru | 0:ff033dfc838b | 63 | #define MagScale(x) (int16_t)((((int32_t)(x)) * 2 * 12000) >> 16) |
lru | 0:ff033dfc838b | 64 | |
lru | 2:06e62a299a74 | 65 | Kmx65Driver::Status Kmx65Driver::read(Kmx65Value& value) |
lru | 0:ff033dfc838b | 66 | { |
lru | 0:ff033dfc838b | 67 | uint8_t buffer[14]; |
lru | 0:ff033dfc838b | 68 | // uint8_t status[3]; |
lru | 0:ff033dfc838b | 69 | // spi_read_multiple(BUF_STATUS_1, status, 3); |
lru | 0:ff033dfc838b | 70 | |
lru | 0:ff033dfc838b | 71 | spi_read_multiple(BUF_READ, &buffer[1], 13); |
lru | 0:ff033dfc838b | 72 | |
lru | 0:ff033dfc838b | 73 | #if 0 |
lru | 2:06e62a299a74 | 74 | printf("kmx65: raw="); |
lru | 0:ff033dfc838b | 75 | for (uint32_t i = 2; i < 14; i+=2) { |
lru | 0:ff033dfc838b | 76 | printf("%02x%02x ", buffer[i+1], buffer[i]); |
lru | 0:ff033dfc838b | 77 | } |
lru | 0:ff033dfc838b | 78 | printf(" status %02x%02x\n", status[2], status[1]); |
lru | 0:ff033dfc838b | 79 | #endif // 0 |
lru | 0:ff033dfc838b | 80 | |
lru | 0:ff033dfc838b | 81 | value.acc_x = AccScale(*reinterpret_cast<int16_t*>(buffer+2)); |
lru | 0:ff033dfc838b | 82 | value.acc_y = AccScale(*reinterpret_cast<int16_t*>(buffer+4)); |
lru | 0:ff033dfc838b | 83 | value.acc_z = AccScale(*reinterpret_cast<int16_t*>(buffer+6)); |
lru | 0:ff033dfc838b | 84 | value.mag_x = MagScale(*reinterpret_cast<int16_t*>(buffer+8)); |
lru | 0:ff033dfc838b | 85 | value.mag_y = MagScale(*reinterpret_cast<int16_t*>(buffer+10)); |
lru | 0:ff033dfc838b | 86 | value.mag_z = MagScale(*reinterpret_cast<int16_t*>(buffer+12)); |
lru | 0:ff033dfc838b | 87 | |
lru | 0:ff033dfc838b | 88 | #if 0 |
lru | 0:ff033dfc838b | 89 | printf("Acc: %8d %8d %8d Mag: %8d %8d %8d\n", |
lru | 0:ff033dfc838b | 90 | value.acc_x, value.acc_y, value.acc_z, |
lru | 0:ff033dfc838b | 91 | value.mag_x, value.mag_y, value.mag_z); |
lru | 0:ff033dfc838b | 92 | #endif // 0 |
lru | 0:ff033dfc838b | 93 | |
lru | 0:ff033dfc838b | 94 | return STATUS_OK; |
lru | 0:ff033dfc838b | 95 | } |
lru | 0:ff033dfc838b | 96 | |
lru | 2:06e62a299a74 | 97 | void Kmx65Driver::clear_buffer() |
lru | 0:ff033dfc838b | 98 | { |
lru | 0:ff033dfc838b | 99 | spi_transaction(BUF_CLEAR, 0x00); |
lru | 0:ff033dfc838b | 100 | } |
lru | 0:ff033dfc838b | 101 | |
lru | 2:06e62a299a74 | 102 | void Kmx65Driver::init_chip() |
lru | 0:ff033dfc838b | 103 | { |
lru | 0:ff033dfc838b | 104 | // Initialize chip |
lru | 0:ff033dfc838b | 105 | spi_transaction(CNTL2, 0x14); // Acc range 8g, disable sensors, oversampling |
lru | 0:ff033dfc838b | 106 | spi_transaction(CNTL1, 0x03); // Mag range 1200uT |
lru | 0:ff033dfc838b | 107 | spi_transaction(ODCNTL, 0x00); // data rate 12.5 sps |
lru | 0:ff033dfc838b | 108 | spi_transaction(BUF_CTRL1, 12); // trig level |
lru | 0:ff033dfc838b | 109 | spi_transaction(BUF_CTRL2, 0x00); // buffer FIFO mode |
lru | 0:ff033dfc838b | 110 | spi_transaction(BUF_CTRL3, 0x7E); // enable all Acc and Mag data |
lru | 0:ff033dfc838b | 111 | spi_transaction(CNTL2, 0x17); // enable sensors |
lru | 0:ff033dfc838b | 112 | } |
lru | 0:ff033dfc838b | 113 | |
lru | 0:ff033dfc838b | 114 | |
lru | 0:ff033dfc838b | 115 | /** Callback function periodically updating sensor value. |
lru | 0:ff033dfc838b | 116 | */ |
lru | 2:06e62a299a74 | 117 | void Kmx65Sensor::updater() |
lru | 0:ff033dfc838b | 118 | { |
lru | 2:06e62a299a74 | 119 | Kmx65Value val; |
lru | 2:06e62a299a74 | 120 | if (_driver.read(val) == Kmx65Driver::STATUS_OK) { |
lru | 0:ff033dfc838b | 121 | update_value(val); |
lru | 0:ff033dfc838b | 122 | }; |
lru | 0:ff033dfc838b | 123 | _driver.clear_buffer(); |
lru | 0:ff033dfc838b | 124 | } |
lru | 0:ff033dfc838b | 125 | |
lru | 0:ff033dfc838b | 126 | /** Initialize driver and setup periodic sensor updates. |
lru | 0:ff033dfc838b | 127 | */ |
lru | 2:06e62a299a74 | 128 | void Kmx65Sensor::start(EventQueue& ev_queue) |
lru | 0:ff033dfc838b | 129 | { |
lru | 0:ff033dfc838b | 130 | _driver.init_chip(); |
lru | 0:ff033dfc838b | 131 | _driver.clear_buffer(); |
lru | 2:06e62a299a74 | 132 | ev_queue.call_every(500, callback(this, &Kmx65Sensor::updater)); |
lru | 0:ff033dfc838b | 133 | } |