google / cyanobyte

Machine-readable datasheets
https://cyanobyte.dev
Apache License 2.0
79 stars 31 forks source link

Pigweed template #274

Open Fleker opened 3 years ago

Fleker commented 3 years ago

Start work on a template that will create extensions of RegisterDevice for use w/ I2C peripherals.

Fleker commented 3 years ago

See RegisterDevice API and Getting Started

Fleker commented 3 years ago
Fleker commented 3 years ago

BUILD.gn (see also sample)

# ...

import("//build_overrides/pigweed.gni")

import("$dir_pw_build/target_types.gni")
import("$dir_pw_chrono/backend.gni")
import("$dir_pw_docgen/docs.gni")
import("$dir_pw_unit_test/test.gni")

pw_source_set("bmp180") {
  public = [ "BMP180.h" ]
  sources = [ "BMP180.cc" ]
  deps = [
    "$dir_pw_bytes",
    "$dir_pw_chrono:system_clock",
    "$dir_pw_i2c:address",
    "$dir_pw_i2c:device",
    "$dir_pw_i2c:initiator",
    "$dir_pw_result",
    "$dir_pw_status",
  ]
}

pw_test_group("tests") {
  tests = [
    ":bmp180_test",
  ]
}

pw_test("bmp180_test") {
  sources = [ "bmp180_test.cc" ]
  deps = [ ":bmp180" ]
}

pw_doc_group("docs") {
  sources = [ "docs.rst" ]
}

BMP180_test.cc

// Copyright 2021 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include <array>
#include <chrono>
#include <span>

#include "gtest/gtest.h"
// #include "pw_bytes/array.h"
// #include "pw_bytes/span.h"
// #include "pw_i2c/address.h"

using namespace std::literals::chrono_literals;

namespace pw::i2c {
namespace {

TEST(Transaction, Read) {
  EXPECT_EQ(1, 1);
}

}  // namespace
}  // namespace pw::i2c

BMP180.cc

/*
* Copyright (C) 2020 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Auto-generated file for BMP180 v0.1.0.
* Generated from peripherals/BMP180.yaml using Cyanobyte Codegen v0.0.2
* Class for BMP180
* Bosch Digital Temperature / Pressure Sensor
*/

#include "BMP180.h"

#define DEVICE_ADDRESS 119

#define REGISTER_CONTROL 244
#define REGISTER_PRESSURECALAC1 170
#define REGISTER_PRESSURECALAC2 172
#define REGISTER_PRESSURECALVB1 182
#define REGISTER_PRESSURECALVB2 184
#define REGISTER_RESULT 246
#define REGISTER_TEMPCAL3 174
#define REGISTER_TEMPCAL4 176
#define REGISTER_TEMPCAL5 178
#define REGISTER_TEMPCAL6 180
#define REGISTER_TEMPCALMC 188
#define REGISTER_TEMPCALMD 190

BMP180::BMP180(pw::i2c::Initiator& initiator):
    RegisterDevice(initiator, pw::i2c::Address(119),
          std::endian::big,
          pw::i2c::RegisterAddressSize::k1Byte) {}

pw::Status BMP180::writeControl(uint8_t data) {
  // Hard-coded timeout of 1s.
  return WriteRegister8(REGISTER_CONTROL, data, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readPressureCalAC1() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_PRESSURECALAC1, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readPressureCalAC2() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_PRESSURECALAC2, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readPressureCalVB1() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_PRESSURECALVB1, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readPressureCalVB2() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_PRESSURECALVB2, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readResult() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_RESULT, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readTempCal3() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_TEMPCAL3, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readTempCal4() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_TEMPCAL4, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readTempCal5() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_TEMPCAL5, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readTempCal6() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_TEMPCAL6, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readTempCalMC() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_TEMPCALMC, std::chrono::seconds(1));
}

pw::Result<uint16_t> BMP180::readTempCalMD() {
  // Hard-coded timeout of 1s.
  return ReadRegister16(REGISTER_TEMPCALMD, std::chrono::seconds(1));
}

float BMP180::pressureasMbars() {
    short ac1; // Variable declaration
    short ac2; // Variable declaration
    short ac3; // Variable declaration
    uint16_t ac4; // Variable declaration
    float b1; // Variable declaration
    float c3; // Variable declaration
    float c4; // Variable declaration
    float p0; // Variable declaration
    float p1; // Variable declaration
    float p2; // Variable declaration
    float pressure; // Variable declaration
    float rawComp; // Variable declaration
    float temperature; // Variable declaration
    short vb1; // Variable declaration
    short vb2; // Variable declaration
    float x; // Variable declaration
    float x1; // Variable declaration
    float x2; // Variable declaration
    float y; // Variable declaration
    float y0; // Variable declaration
    float y1; // Variable declaration
    float y2; // Variable declaration
    float z; // Variable declaration

    writeControl(52);
    pressure = readResult().value();
    temperature = temperatureasCelsius();
    pw::chrono::SystemClock::time_point before = pw::chrono::SystemClock::now();
    while (pw::chrono::SystemClock::now() - before < std::chrono::milliseconds(10)) {}
    rawComp = (temperature-25);
    ac1 = readPressureCalAC1().value();
    ac2 = readPressureCalAC2().value();
    x1 = (160*pow(2, -13)*ac2);
    vb2 = readPressureCalVB2().value();
    x2 = (pow(160, 2)*pow(2, -25)*vb2);
    x = ((x2*pow(rawComp, 2))+(x1*rawComp)+ac1);
    ac3 = readTempCal3().value();
    c3 = (160*pow(2, -15)*ac3);
    ac4 = readTempCal4().value();
    c4 = (pow(10, -3)*pow(2, -15)*ac4);
    vb1 = readPressureCalVB1().value();
    b1 = (pow(160, 2)*pow(2, -30)*vb1);
    y0 = (c4*pow(2, 15));
    y1 = (c4*c3);
    y2 = (c4*b1);
    y = ((y2*pow(rawComp, 2))+(y1*rawComp)+y0);
    z = ((pressure-x)/y);
    p0 = ((3791-8)/1600);
    p1 = (1-(7357*pow(2, -30)));
    p2 = (3038*100*pow(2, -36));
    pressure = ((p2*pow(z, 2))+(p1*z)+p0);

    return pressure;
}

float BMP180::temperatureasCelsius() {
    short rawComp; // Variable declaration
    short rawMc; // Variable declaration
    short rawMd; // Variable declaration
    float temperature; // Variable declaration
    uint16_t varAc5; // Variable declaration
    uint16_t varAc6; // Variable declaration
    float varC5; // Variable declaration
    float varMc; // Variable declaration
    float varMd; // Variable declaration

    writeControl(46);
    temperature = readResult().value();
    varAc5 = readTempCal5().value();
    varAc6 = readTempCal6().value();
    varC5 = ((pow(2, -15)/160)*varAc5);
    rawComp = (varC5*(temperature-varAc6));
    rawMc = readTempCalMC().value();
    varMc = ((pow(2, 11)/pow(160, 2))*rawMc);
    rawMd = readTempCalMD().value();
    varMd = (rawMd/160);
    temperature = (rawComp+(varMc/(rawComp+varMd)));

    return temperature;
}

BMP180.h

/*
* Copyright (C) 2020 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Auto-generated file for BMP180 v0.1.0.
* Generated from peripherals/BMP180.yaml using Cyanobyte Codegen v0.0.2
* Class for BMP180
* Bosch Digital Temperature / Pressure Sensor

*/

#pragma once

#include <cmath>

#include "pw_bytes/byte_builder.h"
#include "pw_chrono/system_clock.h"
#include "pw_i2c/address.h"
#include "pw_i2c/device.h"
#include "pw_i2c/register_device.h"
#include "pw_i2c/initiator.h"
#include "pw_result/result.h"
#include "pw_status/status.h"

class BMP180 : pw::i2c::RegisterDevice {
    public:
        BMP180(pw::i2c::Initiator& initiator);

        /**
         * Stores the current measurement type.

         */
        pw::Status writeControl(uint8_t data);
        /**
         * Constant register for pressure measurement calibration.

         */
        pw::Result<uint16_t> readPressureCalAC1();

        /**
         * Constant register for pressure measurement calibration.

         */
        pw::Result<uint16_t> readPressureCalAC2();

        /**
         * Constant register for pressure measurement calibration.

         */
        pw::Result<uint16_t> readPressureCalVB1();

        /**
         * Constant register for pressure measurement calibration.

         */
        pw::Result<uint16_t> readPressureCalVB2();

        /**
         * Stores the most recent measurement result.

         */
        pw::Result<uint16_t> readResult();

        /**
         * Third constant register for temperature measurement calibration.

         */
        pw::Result<uint16_t> readTempCal3();

        /**
         * Fourth constant register for temperature measurement calibration.

         */
        pw::Result<uint16_t> readTempCal4();

        /**
         * Fifth constant register for temperature measurement calibration.

         */
        pw::Result<uint16_t> readTempCal5();

        /**
         * Sixth constant register for temperature measurement calibration.

         */
        pw::Result<uint16_t> readTempCal6();

        /**
         * Constant register for temperature measurement calibration.

         */
        pw::Result<uint16_t> readTempCalMC();

        /**
         * Constant register for temperature measurement calibration.

         */
        pw::Result<uint16_t> readTempCalMD();

        /**
         * Reads the pressure in absolute millibars,
         * not compensated for sea level.

         */
        float pressureasMbars();

        /**
         * Reads the temperature as a raw value or in Celsius.

         */
        float temperatureasCelsius();

};

This all builds, technically. But it gives an error at the very end, maybe because it's building on the host and not for a specific device.

20210604 18:09:31 ERR 
20210604 18:09:31 ERR Build error for //pw_chrono:system_clock.NO_BACKEND_SET(//targets/stm32f429i_disc1:stm32f429i_disc1_debug):
20210604 18:09:31 ERR 
20210604 18:09:31 ERR   Attempted to build the //pw_chrono:system_clock facade with no backend.
20210604 18:09:31 ERR   
20210604 18:09:31 ERR   If you are using this facade, ensure you have configured a backend 
20210604 18:09:31 ERR   properly. The build arg for the facade must be set to a valid 
20210604 18:09:31 ERR   backend in the toolchain. For example, you may need to add a line 
20210604 18:09:31 ERR   like the following to the toolchain's .gni file:
20210604 18:09:31 ERR   
20210604 18:09:31 ERR     pw_chrono_<FACADE_NAME>_BACKEND = "//path/to/the:backend"
20210604 18:09:31 ERR   
20210604 18:09:31 ERR   If you are NOT using this facade, this error may have been triggered 
20210604 18:09:31 ERR   by trying to build all targets.
20210604 18:09:31 ERR 
20210604 18:09:32 ERR Dependency path to this target:
20210604 18:09:32 ERR 
20210604 18:09:32 ERR   gn path out //:default "//pw_chrono:system_clock.NO_BACKEND_SET(//targets/stm32f429i_disc1:stm32f429i_disc1_debug)"