This is a basic code to be used for Sequana BLE Lab exercises.

Committer:
lru
Date:
Thu Mar 14 13:25:02 2019 +0000
Revision:
2:06e62a299a74
Parent:
source/Kx64.cpp@0:ff033dfc838b
Updated acc/mag sensor naming.

Who changed what in which revision?

UserRevisionLine numberNew 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 }