mirror of
https://github.com/eried/portapack-mayhem.git
synced 2024-10-01 01:26:06 -04:00
ADS1100 (#2116)
* WIP * WIP * WIP * Corrected name * WIP * WIP * WIP * WIP * Added new calc * WIP * WIP * WIP * WIP * WIP * WIP * Added debug serial lines * WIP * Fixed issue * Fixed calculation issue * Added voltage to performance DFU menu * Added padding function and added voltage to perf menu * Clean up * Refactor * Fixed linting * Hides voltage if PP does not conatin IC * WIP showing battery % * made the percentage a int * Added % to header * Removed test UI * Removed comment * Added fix for precision too large * Added fix for precision too large * Linting
This commit is contained in:
parent
282e4da1cb
commit
67975d76a0
@ -176,6 +176,7 @@ set(CPPSRC
|
|||||||
${COMMON}/ui_language.cpp
|
${COMMON}/ui_language.cpp
|
||||||
${COMMON}/utility.cpp
|
${COMMON}/utility.cpp
|
||||||
${COMMON}/wm8731.cpp
|
${COMMON}/wm8731.cpp
|
||||||
|
${COMMON}/ads1110.cpp
|
||||||
${COMMON}/performance_counter.cpp
|
${COMMON}/performance_counter.cpp
|
||||||
app_settings.cpp
|
app_settings.cpp
|
||||||
audio.cpp
|
audio.cpp
|
||||||
|
@ -41,6 +41,11 @@ DfuMenu::DfuMenu(NavigationView& nav)
|
|||||||
&text_info_line_8,
|
&text_info_line_8,
|
||||||
&text_info_line_9,
|
&text_info_line_9,
|
||||||
&text_info_line_10});
|
&text_info_line_10});
|
||||||
|
|
||||||
|
if (portapack::battery_ads1110.isDetected()) {
|
||||||
|
add_child(&voltage_label);
|
||||||
|
add_child(&text_info_line_11);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DfuMenu::paint(Painter& painter) {
|
void DfuMenu::paint(Painter& painter) {
|
||||||
@ -48,6 +53,8 @@ void DfuMenu::paint(Painter& painter) {
|
|||||||
size_t m0_fragmented_free_space = 0;
|
size_t m0_fragmented_free_space = 0;
|
||||||
const auto m0_fragments = chHeapStatus(NULL, &m0_fragmented_free_space);
|
const auto m0_fragments = chHeapStatus(NULL, &m0_fragmented_free_space);
|
||||||
|
|
||||||
|
auto lines = (portapack::battery_ads1110.isDetected() ? 11 : 10) + 2;
|
||||||
|
|
||||||
text_info_line_1.set(to_string_dec_uint(chCoreStatus(), 6));
|
text_info_line_1.set(to_string_dec_uint(chCoreStatus(), 6));
|
||||||
text_info_line_2.set(to_string_dec_uint(m0_fragmented_free_space, 6));
|
text_info_line_2.set(to_string_dec_uint(m0_fragmented_free_space, 6));
|
||||||
text_info_line_3.set(to_string_dec_uint(m0_fragments, 6));
|
text_info_line_3.set(to_string_dec_uint(m0_fragments, 6));
|
||||||
@ -58,9 +65,11 @@ void DfuMenu::paint(Painter& painter) {
|
|||||||
text_info_line_8.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
|
text_info_line_8.set(to_string_dec_uint(shared_memory.m4_performance_counter, 6));
|
||||||
text_info_line_9.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
|
text_info_line_9.set(to_string_dec_uint(shared_memory.m4_buffer_missed, 6));
|
||||||
text_info_line_10.set(to_string_dec_uint(chTimeNow() / 1000, 6));
|
text_info_line_10.set(to_string_dec_uint(chTimeNow() / 1000, 6));
|
||||||
|
if (portapack::battery_ads1110.isDetected()) {
|
||||||
|
text_info_line_11.set(to_string_decimal_padding(portapack::battery_ads1110.readVoltage(), 3, 6));
|
||||||
|
}
|
||||||
|
|
||||||
constexpr auto margin = 5;
|
constexpr auto margin = 5;
|
||||||
constexpr auto lines = 10 + 2;
|
|
||||||
|
|
||||||
painter.fill_rectangle(
|
painter.fill_rectangle(
|
||||||
{{6 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
{{6 * CHARACTER_WIDTH - margin, 3 * LINE_HEIGHT - margin},
|
||||||
|
@ -58,7 +58,9 @@ class DfuMenu : public View {
|
|||||||
{{6 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "M4 stack:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 11 * LINE_HEIGHT}, "M4 stack:", Color::dark_cyan()},
|
||||||
{{6 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "M4 cpu %:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 12 * LINE_HEIGHT}, "M4 cpu %:", Color::dark_cyan()},
|
||||||
{{6 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "M4 miss:", Color::dark_cyan()},
|
{{6 * CHARACTER_WIDTH, 13 * LINE_HEIGHT}, "M4 miss:", Color::dark_cyan()},
|
||||||
{{6 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "uptime:", Color::dark_cyan()}};
|
{{6 * CHARACTER_WIDTH, 14 * LINE_HEIGHT}, "Uptime:", Color::dark_cyan()}};
|
||||||
|
|
||||||
|
Labels voltage_label{{{6 * CHARACTER_WIDTH, 15 * LINE_HEIGHT}, "Voltage:", Color::dark_cyan()}};
|
||||||
|
|
||||||
Text text_info_line_1{{15 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_1{{15 * CHARACTER_WIDTH, 5 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
Text text_info_line_2{{15 * CHARACTER_WIDTH, 6 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_2{{15 * CHARACTER_WIDTH, 6 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
@ -70,6 +72,7 @@ class DfuMenu : public View {
|
|||||||
Text text_info_line_8{{15 * CHARACTER_WIDTH, 12 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_8{{15 * CHARACTER_WIDTH, 12 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
Text text_info_line_9{{15 * CHARACTER_WIDTH, 13 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_9{{15 * CHARACTER_WIDTH, 13 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
Text text_info_line_10{{15 * CHARACTER_WIDTH, 14 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
Text text_info_line_10{{15 * CHARACTER_WIDTH, 14 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
|
Text text_info_line_11{{15 * CHARACTER_WIDTH, 15 * LINE_HEIGHT, 6 * CHARACTER_WIDTH, 1 * LINE_HEIGHT}, ""};
|
||||||
};
|
};
|
||||||
|
|
||||||
class DfuMenu2 : public View {
|
class DfuMenu2 : public View {
|
||||||
|
@ -52,6 +52,7 @@ using asahi_kasei::ak4951::AK4951;
|
|||||||
#include "sd_card.hpp"
|
#include "sd_card.hpp"
|
||||||
#include "string_format.hpp"
|
#include "string_format.hpp"
|
||||||
#include "bitmap.hpp"
|
#include "bitmap.hpp"
|
||||||
|
#include "ui_widget.hpp"
|
||||||
|
|
||||||
namespace portapack {
|
namespace portapack {
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ ClockManager clock_manager{
|
|||||||
|
|
||||||
WM8731 audio_codec_wm8731{i2c0, 0x1a};
|
WM8731 audio_codec_wm8731{i2c0, 0x1a};
|
||||||
AK4951 audio_codec_ak4951{i2c0, 0x12};
|
AK4951 audio_codec_ak4951{i2c0, 0x12};
|
||||||
|
ads1110::ADS1110 battery_ads1110{i2c0, 0x48};
|
||||||
|
|
||||||
ReceiverModel receiver_model;
|
ReceiverModel receiver_model;
|
||||||
TransmitterModel transmitter_model;
|
TransmitterModel transmitter_model;
|
||||||
@ -585,6 +587,7 @@ init_status_t init() {
|
|||||||
chThdSleepMilliseconds(10);
|
chThdSleepMilliseconds(10);
|
||||||
|
|
||||||
audio::init(portapack_audio_codec());
|
audio::init(portapack_audio_codec());
|
||||||
|
battery_ads1110.init();
|
||||||
|
|
||||||
if (lcd_fast_setup)
|
if (lcd_fast_setup)
|
||||||
draw_splash_screen_icon(4, ui::bitmap_icon_speaker);
|
draw_splash_screen_icon(4, ui::bitmap_icon_speaker);
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
#include "backlight.hpp"
|
#include "backlight.hpp"
|
||||||
#include "usb_serial.hpp"
|
#include "usb_serial.hpp"
|
||||||
|
|
||||||
|
#include "ads1110.hpp"
|
||||||
|
|
||||||
#include "radio.hpp"
|
#include "radio.hpp"
|
||||||
#include "clock_manager.hpp"
|
#include "clock_manager.hpp"
|
||||||
#include "temperature_logger.hpp"
|
#include "temperature_logger.hpp"
|
||||||
@ -61,6 +63,7 @@ extern portapack::USBSerial usb_serial;
|
|||||||
extern si5351::Si5351 clock_generator;
|
extern si5351::Si5351 clock_generator;
|
||||||
extern ClockManager clock_manager;
|
extern ClockManager clock_manager;
|
||||||
|
|
||||||
|
extern ads1110::ADS1110 battery_ads1110;
|
||||||
extern ReceiverModel receiver_model;
|
extern ReceiverModel receiver_model;
|
||||||
extern TransmitterModel transmitter_model;
|
extern TransmitterModel transmitter_model;
|
||||||
|
|
||||||
|
@ -172,6 +172,31 @@ std::string to_string_decimal(float decimal, int8_t precision) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string to_string_decimal_padding(float decimal, int8_t precision, const int32_t l) {
|
||||||
|
double integer_part;
|
||||||
|
double fractional_part;
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
if (precision > 9) precision = 9; // we will convert to uin32_t, and that is the max it can hold.
|
||||||
|
|
||||||
|
fractional_part = modf(decimal, &integer_part) * pow(10, precision);
|
||||||
|
|
||||||
|
if (fractional_part < 0) {
|
||||||
|
fractional_part = -fractional_part;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = to_string_dec_int(integer_part) + "." + to_string_dec_uint(fractional_part, precision, '0');
|
||||||
|
|
||||||
|
// Add padding with spaces to meet the length requirement
|
||||||
|
if (result.length() < l) {
|
||||||
|
int padding_length = l - result.length();
|
||||||
|
std::string padding(padding_length, ' ');
|
||||||
|
result = padding + result;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
// right-justified frequency in Hz, always 10 characters
|
// right-justified frequency in Hz, always 10 characters
|
||||||
std::string to_string_freq(const uint64_t f) {
|
std::string to_string_freq(const uint64_t f) {
|
||||||
std::string final_str{""};
|
std::string final_str{""};
|
||||||
|
@ -54,6 +54,7 @@ std::string to_string_bin(const uint32_t n, const uint8_t l = 0);
|
|||||||
std::string to_string_dec_uint(const uint32_t n, const int32_t l, const char fill = ' ');
|
std::string to_string_dec_uint(const uint32_t n, const int32_t l, const char fill = ' ');
|
||||||
std::string to_string_dec_int(const int32_t n, const int32_t l, const char fill = 0);
|
std::string to_string_dec_int(const int32_t n, const int32_t l, const char fill = 0);
|
||||||
std::string to_string_decimal(float decimal, int8_t precision);
|
std::string to_string_decimal(float decimal, int8_t precision);
|
||||||
|
std::string to_string_decimal_padding(float decimal, int8_t precision, const int32_t l);
|
||||||
|
|
||||||
std::string to_string_hex(uint64_t n, int32_t length);
|
std::string to_string_hex(uint64_t n, int32_t length);
|
||||||
std::string to_string_hex_array(uint8_t* array, int32_t length);
|
std::string to_string_hex_array(uint8_t* array, int32_t length);
|
||||||
|
130
firmware/common/ads1110.cpp
Normal file
130
firmware/common/ads1110.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 jLynx.
|
||||||
|
*
|
||||||
|
* This file is part of PortaPack.
|
||||||
|
*
|
||||||
|
* This program 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 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program 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; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ads1110.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace ads1110 {
|
||||||
|
|
||||||
|
constexpr float BATTERY_MIN_VOLTAGE = 3.0;
|
||||||
|
constexpr float BATTERY_MAX_VOLTAGE = 4.0;
|
||||||
|
|
||||||
|
void ADS1110::init() {
|
||||||
|
if (!detected_) {
|
||||||
|
detected_ = detect();
|
||||||
|
}
|
||||||
|
if (detected_) {
|
||||||
|
// Set the configuration register
|
||||||
|
write(0x8C);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ADS1110::detect() {
|
||||||
|
uint8_t data[3];
|
||||||
|
if (bus.receive(bus_address, data, 3)) {
|
||||||
|
// Check if the received data is valid
|
||||||
|
uint8_t configRegister = data[2];
|
||||||
|
if ((configRegister & 0x0F) == 0x0C) {
|
||||||
|
// The configuration register value matches the expected value (0x8C)
|
||||||
|
detected_ = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ADS1110::write(const uint8_t value) {
|
||||||
|
return bus.transmit(bus_address, &value, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
float ADS1110::readVoltage() {
|
||||||
|
// Read the conversion result
|
||||||
|
uint8_t data[3];
|
||||||
|
if (!bus.receive(bus_address, data, 3)) {
|
||||||
|
return 0.0f; // Return 0 if the read fails
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t raw = (static_cast<uint16_t>(data[0]) << 8) | data[1];
|
||||||
|
|
||||||
|
// Calculate the voltage based on the output code
|
||||||
|
float voltage = 0.0f;
|
||||||
|
float minCode = 0;
|
||||||
|
float pga = 0.0f;
|
||||||
|
|
||||||
|
uint8_t pga_rate = data[2] & 0x03;
|
||||||
|
switch (pga_rate) {
|
||||||
|
case 0:
|
||||||
|
pga = 1.0f;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
pga = 2.0f;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
pga = 4.0f;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
pga = 8.0f;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Handle invalid data rate
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t data_rate = (data[2] >> 2) & 0x03;
|
||||||
|
switch (data_rate) {
|
||||||
|
case 0: // 240
|
||||||
|
minCode = -2048.0;
|
||||||
|
break;
|
||||||
|
case 1: // 60
|
||||||
|
minCode = -8192.0;
|
||||||
|
break;
|
||||||
|
case 2: // 30
|
||||||
|
minCode = -16384.0;
|
||||||
|
break;
|
||||||
|
case 3: // 15
|
||||||
|
minCode = -32768.0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Handle invalid data rate
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.048 is the reference voltage & 2.0 is to make up for the voltage divider
|
||||||
|
voltage = raw / (-1.0 * minCode) * pga * 2.048 * 2.0;
|
||||||
|
|
||||||
|
return voltage;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ADS1110::getBatteryInfo(float& batteryPercentage, float& voltage) {
|
||||||
|
voltage = readVoltage();
|
||||||
|
|
||||||
|
// Calculate the remaining battery percentage
|
||||||
|
batteryPercentage = (voltage - BATTERY_MIN_VOLTAGE) /
|
||||||
|
(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE) * 100.0;
|
||||||
|
|
||||||
|
// Limit the values to the valid range
|
||||||
|
batteryPercentage = std::clamp(batteryPercentage, 0.0f, 100.0f);
|
||||||
|
// ToDo: if its > 4, then 100%, if < 3 then 0%
|
||||||
|
}
|
||||||
|
|
||||||
|
} /* namespace ads1110 */
|
58
firmware/common/ads1110.hpp
Normal file
58
firmware/common/ads1110.hpp
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 jLynx.
|
||||||
|
*
|
||||||
|
* This file is part of PortaPack.
|
||||||
|
*
|
||||||
|
* This program 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 2, or (at your option)
|
||||||
|
* any later version.
|
||||||
|
*
|
||||||
|
* This program 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; see the file COPYING. If not, write to
|
||||||
|
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||||
|
* Boston, MA 02110-1301, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ADS1110_H__
|
||||||
|
#define __ADS1110_H__
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <array>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "i2c_pp.hpp"
|
||||||
|
|
||||||
|
namespace ads1110 {
|
||||||
|
|
||||||
|
using address_t = uint8_t;
|
||||||
|
using reg_t = uint16_t;
|
||||||
|
|
||||||
|
class ADS1110 {
|
||||||
|
public:
|
||||||
|
constexpr ADS1110(I2C& bus, const I2C::address_t bus_address)
|
||||||
|
: bus(bus), bus_address(bus_address), detected_(false) {}
|
||||||
|
|
||||||
|
void init();
|
||||||
|
bool isDetected() const { return detected_; }
|
||||||
|
|
||||||
|
float readVoltage();
|
||||||
|
void getBatteryInfo(float& batteryPercentage, float& voltage);
|
||||||
|
|
||||||
|
private:
|
||||||
|
I2C& bus;
|
||||||
|
const I2C::address_t bus_address;
|
||||||
|
bool detected_;
|
||||||
|
|
||||||
|
bool write(const uint8_t value);
|
||||||
|
bool detect();
|
||||||
|
};
|
||||||
|
|
||||||
|
} /* namespace ads1110 */
|
||||||
|
|
||||||
|
#endif /* __ADS1110_H__ */
|
Loading…
Reference in New Issue
Block a user