Compare commits
36 Commits
8304828bf3
...
659542f094
| Author | SHA1 | Date | |
|---|---|---|---|
| 659542f094 | |||
| 487d75fd73 | |||
| b3f13767dc | |||
| d4a1d0f87a | |||
| d65beadadf | |||
| bde17a2c8f | |||
| 76947dd464 | |||
| cd4b67e68f | |||
| cfad427ec1 | |||
| 353babc103 | |||
| cd3a18e216 | |||
| 16fedf6792 | |||
| 7cd8d821f6 | |||
| 49c2f80503 | |||
| 471c7b769e | |||
| ddbd505f56 | |||
| 1820047ad1 | |||
| 60782bed72 | |||
| ff076e6ad5 | |||
| cc8c27da2c | |||
| 6820b8c4d4 | |||
| eac33a38f5 | |||
| 8b900b95ac | |||
| 5d6d2279b8 | |||
| 7aaadfe61c | |||
| 982f3e11c7 | |||
| 6fabd3354c | |||
| afa596d4a6 | |||
| fe68a83aaa | |||
| 82cb276350 | |||
| aa852ffcea | |||
| 955fa85fd1 | |||
| dbf0d55c09 | |||
| dd52051b75 | |||
| eaa4732166 | |||
| dea9823e9e |
@ -20,4 +20,9 @@ dependencies:
|
||||
version: "1.7.6~1"
|
||||
rules:
|
||||
- if: "target == esp32s3"
|
||||
jgromes/radiolib:
|
||||
version: "7.2.1"
|
||||
rules:
|
||||
- if: "target in [esp32s3, esp32p4]"
|
||||
|
||||
idf: '5.5'
|
||||
|
||||
@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
INCLUDE_DIRS "Source"
|
||||
REQUIRES Tactility esp_lcd ST7796 BQ25896 BQ27220 TCA8418 DRV2605 PwmBacklight driver esp_adc
|
||||
REQUIRES Tactility esp_lcd ST7796 BQ25896 BQ27220 TCA8418 DRV2605 SX126x PwmBacklight driver esp_adc
|
||||
)
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include <Bq25896.h>
|
||||
#include <Drv2605.h>
|
||||
#include <Sx1262.h>
|
||||
#include <Tactility/hal/Configuration.h>
|
||||
|
||||
#define TPAGER_SPI_TRANSFER_SIZE_LIMIT (480 * 222 * (LV_COLOR_DEPTH / 8))
|
||||
@ -22,6 +23,17 @@ static DeviceVector createDevices() {
|
||||
auto tca8418 = std::make_shared<Tca8418>(I2C_NUM_0);
|
||||
auto keyboard = std::make_shared<TpagerKeyboard>(tca8418);
|
||||
|
||||
auto sx1262 = std::make_shared<Sx1262>(Sx1262::Configuration{
|
||||
.spiHostDevice = SPI2_HOST,
|
||||
.spiFrequency = 10'000'000,
|
||||
.csPin = GPIO_NUM_36,
|
||||
.resetPin = GPIO_NUM_47,
|
||||
.busyPin = GPIO_NUM_48,
|
||||
.irqPin = GPIO_NUM_14,
|
||||
.tcxoVoltage = 3.0,
|
||||
.useRegulatorLdo = false
|
||||
});
|
||||
|
||||
return std::vector<std::shared_ptr<Device>> {
|
||||
tca8418,
|
||||
std::make_shared<Bq25896>(I2C_NUM_0),
|
||||
@ -31,7 +43,8 @@ static DeviceVector createDevices() {
|
||||
createTpagerSdCard(),
|
||||
createDisplay(),
|
||||
keyboard,
|
||||
std::make_shared<TpagerEncoder>()
|
||||
std::make_shared<TpagerEncoder>(),
|
||||
sx1262
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
5
Drivers/RadioLibCompat/CMakeLists.txt
Normal file
5
Drivers/RadioLibCompat/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRC_DIRS "Source"
|
||||
INCLUDE_DIRS "Source"
|
||||
REQUIRES Tactility radiolib
|
||||
)
|
||||
3
Drivers/RadioLibCompat/README.md
Normal file
3
Drivers/RadioLibCompat/README.md
Normal file
@ -0,0 +1,3 @@
|
||||
# RadioLibCompat
|
||||
|
||||
A set of helper classes to implement `RadioLib` drivers in Tactility.
|
||||
167
Drivers/RadioLibCompat/Source/RadiolibTactilityHal.cpp
Normal file
167
Drivers/RadioLibCompat/Source/RadiolibTactilityHal.cpp
Normal file
@ -0,0 +1,167 @@
|
||||
#include "RadiolibTactilityHal.h"
|
||||
|
||||
#include "hal/gpio_hal.h"
|
||||
#include "esp_timer.h"
|
||||
|
||||
constexpr const char* TAG = "RadiolibTactilityHal";
|
||||
|
||||
void RadiolibTactilityHal::init() {
|
||||
// we only need to init the SPI here
|
||||
spiBegin();
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::term() {
|
||||
// we only need to stop the SPI here
|
||||
spiEnd();
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::pinMode(uint32_t pin, uint32_t mode) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_hal_context_t gpiohal;
|
||||
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
|
||||
|
||||
gpio_config_t conf = {
|
||||
.pin_bit_mask = (1ULL<<pin),
|
||||
.mode = (gpio_mode_t)mode,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = (gpio_int_type_t)gpiohal.dev->pin[pin].int_type,
|
||||
};
|
||||
gpio_config(&conf);
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::digitalWrite(uint32_t pin, uint32_t value) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_set_level((gpio_num_t)pin, value);
|
||||
}
|
||||
|
||||
uint32_t RadiolibTactilityHal::digitalRead(uint32_t pin) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(gpio_get_level((gpio_num_t)pin));
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isrServiceInitialized) {
|
||||
gpio_install_isr_service((int)ESP_INTR_FLAG_IRAM);
|
||||
isrServiceInitialized = true;
|
||||
}
|
||||
gpio_set_intr_type((gpio_num_t)interruptNum, (gpio_int_type_t)(mode & 0x7));
|
||||
|
||||
// this uses function typecasting, which is not defined when the functions have different signatures
|
||||
// untested and might not work
|
||||
// TODO: I think the wisest course of action is forbidding registration via RadioLib entirely,
|
||||
// as it doesn't suit Tactility with its lack of context passing
|
||||
gpio_isr_handler_add((gpio_num_t)interruptNum, (void (*)(void*))interruptCb, NULL);
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::detachInterrupt(uint32_t interruptNum) {
|
||||
if(interruptNum == RADIOLIB_NC) {
|
||||
return;
|
||||
}
|
||||
|
||||
gpio_isr_handler_remove((gpio_num_t)interruptNum);
|
||||
gpio_wakeup_disable((gpio_num_t)interruptNum);
|
||||
gpio_set_intr_type((gpio_num_t)interruptNum, GPIO_INTR_DISABLE);
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::delay(unsigned long ms) {
|
||||
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::delayMicroseconds(unsigned long us) {
|
||||
uint64_t m = (uint64_t)esp_timer_get_time();
|
||||
if(us) {
|
||||
uint64_t e = (m + us);
|
||||
if(m > e) { // overflow
|
||||
while((uint64_t)esp_timer_get_time() > e);
|
||||
}
|
||||
while((uint64_t)esp_timer_get_time() < e);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long RadiolibTactilityHal::millis() {
|
||||
return((unsigned long)(esp_timer_get_time() / 1000ULL));
|
||||
}
|
||||
|
||||
unsigned long RadiolibTactilityHal::micros() {
|
||||
return((unsigned long)(esp_timer_get_time()));
|
||||
}
|
||||
|
||||
long RadiolibTactilityHal::pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) {
|
||||
if(pin == RADIOLIB_NC) {
|
||||
return(0);
|
||||
}
|
||||
|
||||
this->pinMode(pin, GPIO_MODE_INPUT);
|
||||
uint32_t start = this->micros();
|
||||
uint32_t curtick = this->micros();
|
||||
|
||||
while(this->digitalRead(pin) == state) {
|
||||
if((this->micros() - curtick) > timeout) {
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
return(this->micros() - start);
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::spiBegin() {
|
||||
if (!spiInitialized) {
|
||||
TT_LOG_I(TAG, "SPI Begin!");
|
||||
spi_device_interface_config_t devcfg = {};
|
||||
devcfg.clock_speed_hz = spiFrequency;
|
||||
devcfg.mode = 0;
|
||||
devcfg.spics_io_num = csPin;
|
||||
devcfg.queue_size = 1;
|
||||
esp_err_t ret = spi_bus_add_device(spiHostDevice, &devcfg, &spiDeviceHandle);
|
||||
if (ret != ESP_OK) {
|
||||
TT_LOG_E(TAG, "Failed to add SPI device: %s", esp_err_to_name(ret));
|
||||
}
|
||||
spiInitialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::spiBeginTransaction() {
|
||||
// This function is used to set up the transaction (speed, bit order, mode, ...).
|
||||
// With the ESP-IDF HAL this is automatically done, so no code needed.
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::spiTransfer(uint8_t* out, size_t len, uint8_t* in) {
|
||||
spi_transaction_t t;
|
||||
|
||||
auto lock = getLock()->asScopedLock();
|
||||
bool locked = lock.lock(portMAX_DELAY);
|
||||
if (!locked) {
|
||||
TT_LOG_E(TAG, "Failed to aquire SPI lock");
|
||||
}
|
||||
|
||||
memset(&t, 0, sizeof(t)); // Zero out the transaction
|
||||
t.length = len * 8; // Length is in bits
|
||||
t.tx_buffer = out; // The data to send
|
||||
t.rx_buffer = in; // The data to receive
|
||||
spi_device_polling_transmit(spiDeviceHandle, &t);
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::spiEndTransaction() {
|
||||
// nothing needs to be done here
|
||||
}
|
||||
|
||||
void RadiolibTactilityHal::spiEnd() {
|
||||
if (spiInitialized) {
|
||||
spi_bus_remove_device(spiDeviceHandle);
|
||||
spiInitialized = false;
|
||||
}
|
||||
}
|
||||
64
Drivers/RadioLibCompat/Source/RadiolibTactilityHal.h
Normal file
64
Drivers/RadioLibCompat/Source/RadiolibTactilityHal.h
Normal file
@ -0,0 +1,64 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/Lock.h>
|
||||
#include <Tactility/hal/spi/Spi.h>
|
||||
|
||||
#include <freertos/FreeRTOS.h>
|
||||
#include <freertos/task.h>
|
||||
|
||||
#include <RadioLib.h>
|
||||
|
||||
#include <driver/gpio.h>
|
||||
#include <driver/spi_master.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
class RadiolibTactilityHal : public RadioLibHal {
|
||||
private:
|
||||
spi_host_device_t spiHostDevice;
|
||||
int spiFrequency;
|
||||
gpio_num_t csPin;
|
||||
spi_device_handle_t spiDeviceHandle;
|
||||
std::shared_ptr<tt::Lock> lock;
|
||||
bool spiInitialized;
|
||||
bool isrServiceInitialized;
|
||||
|
||||
public:
|
||||
explicit RadiolibTactilityHal(spi_host_device_t spiHostDevice, int spiFrequency, gpio_num_t csPin)
|
||||
: RadioLibHal(
|
||||
GPIO_MODE_INPUT,
|
||||
GPIO_MODE_OUTPUT,
|
||||
0, // LOW
|
||||
1, // HIGH
|
||||
GPIO_INTR_POSEDGE,
|
||||
GPIO_INTR_NEGEDGE)
|
||||
, spiHostDevice(spiHostDevice)
|
||||
, spiFrequency(spiFrequency)
|
||||
, csPin(csPin)
|
||||
, lock(tt::hal::spi::getLock(spiHostDevice))
|
||||
, spiInitialized(false)
|
||||
, isrServiceInitialized(false) {}
|
||||
|
||||
void init() override;
|
||||
void term() override;
|
||||
|
||||
void pinMode(uint32_t pin, uint32_t mode) override;
|
||||
void digitalWrite(uint32_t pin, uint32_t value) override;
|
||||
uint32_t digitalRead(uint32_t pin) override;
|
||||
void attachInterrupt(uint32_t interruptNum, void (*interruptCb)(void), uint32_t mode) override;
|
||||
void detachInterrupt(uint32_t interruptNum) override;
|
||||
|
||||
void delay(unsigned long ms) override;
|
||||
void delayMicroseconds(unsigned long us) override;
|
||||
unsigned long millis() override;
|
||||
unsigned long micros() override;
|
||||
long pulseIn(uint32_t pin, uint32_t state, unsigned long timeout) override;
|
||||
|
||||
void spiBegin() override;
|
||||
void spiBeginTransaction() override;
|
||||
void spiTransfer(uint8_t* out, size_t len, uint8_t* in) override;
|
||||
void spiEndTransaction() override;
|
||||
void spiEnd();
|
||||
|
||||
std::shared_ptr<tt::Lock> getLock() const { return lock; }
|
||||
};
|
||||
93
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.cpp
Normal file
93
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
#include "RadiolibThreadedDevice.h"
|
||||
#include <cstring>
|
||||
|
||||
constexpr const char* TAG = "RadiolibThreadedDevice";
|
||||
|
||||
bool RadiolibThreadedDevice::start() {
|
||||
auto lock = getMutex().asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
if ((thread != nullptr) && (thread->getState() != tt::Thread::State::Stopped)) {
|
||||
TT_LOG_W(TAG, "Already started");
|
||||
return true;
|
||||
}
|
||||
|
||||
threadInterrupted = false;
|
||||
|
||||
TT_LOG_I(TAG, "Starting thread");
|
||||
setState(State::PendingOn);
|
||||
|
||||
thread = std::make_unique<tt::Thread>(
|
||||
threadName,
|
||||
threadSize,
|
||||
[this]() {
|
||||
return this->threadMain();
|
||||
}
|
||||
);
|
||||
thread->setPriority(tt::Thread::Priority::High);
|
||||
thread->start();
|
||||
|
||||
TT_LOG_I(TAG, "Starting finished");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RadiolibThreadedDevice::stop() {
|
||||
auto lock = getMutex().asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
setState(State::PendingOff);
|
||||
|
||||
if (thread != nullptr) {
|
||||
threadInterrupted = true;
|
||||
interruptSignal();
|
||||
|
||||
// Detach thread, it will auto-delete when leaving the current scope
|
||||
auto old_thread = std::move(thread);
|
||||
|
||||
if (old_thread->getState() != tt::Thread::State::Stopped) {
|
||||
// Unlock so thread can lock
|
||||
lock.unlock();
|
||||
// Wait for thread to finish
|
||||
old_thread->join();
|
||||
// Re-lock to continue logic below
|
||||
lock.lock();
|
||||
}
|
||||
}
|
||||
|
||||
setState(State::Off);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RadiolibThreadedDevice::isThreadInterrupted() const {
|
||||
auto lock = getMutex().asScopedLock();
|
||||
lock.lock();
|
||||
return threadInterrupted;
|
||||
}
|
||||
|
||||
int32_t RadiolibThreadedDevice::threadMain() {
|
||||
|
||||
int rc = doBegin(getModulation());
|
||||
if (rc != 0) {
|
||||
return rc;
|
||||
}
|
||||
setState(State::On);
|
||||
|
||||
while (!isThreadInterrupted()) {
|
||||
doListen();
|
||||
|
||||
// Thread might've been interrupted in the meanwhile
|
||||
if (isThreadInterrupted()) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (getTxQueueSize() > 0) {
|
||||
doTransmit();
|
||||
} else {
|
||||
doReceive();
|
||||
}
|
||||
}
|
||||
|
||||
doEnd();
|
||||
return 0;
|
||||
}
|
||||
36
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.h
Normal file
36
Drivers/RadioLibCompat/Source/RadiolibThreadedDevice.h
Normal file
@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/radio/RadioDevice.h>
|
||||
#include <Tactility/Thread.h>
|
||||
|
||||
class RadiolibThreadedDevice : public tt::hal::radio::RadioDevice {
|
||||
|
||||
private:
|
||||
std::string threadName;
|
||||
size_t threadSize;
|
||||
std::unique_ptr<tt::Thread> _Nullable thread;
|
||||
bool threadInterrupted = false;
|
||||
|
||||
protected:
|
||||
virtual int32_t threadMain();
|
||||
bool isThreadInterrupted() const;
|
||||
|
||||
virtual void interruptSignal() = 0;
|
||||
|
||||
virtual int doBegin(const Modulation modulation) = 0;
|
||||
virtual void doEnd() = 0;
|
||||
virtual void doTransmit() = 0;
|
||||
virtual void doListen() = 0;
|
||||
virtual void doReceive() = 0;
|
||||
|
||||
public:
|
||||
explicit RadiolibThreadedDevice(const std::string& threadName, const size_t threadSize)
|
||||
: threadName(threadName)
|
||||
, threadSize(threadSize)
|
||||
{}
|
||||
|
||||
~RadiolibThreadedDevice() override = default;
|
||||
|
||||
virtual bool start() override;
|
||||
virtual bool stop() override;
|
||||
};
|
||||
5
Drivers/SX126x/CMakeLists.txt
Normal file
5
Drivers/SX126x/CMakeLists.txt
Normal file
@ -0,0 +1,5 @@
|
||||
idf_component_register(
|
||||
SRC_DIRS "Source"
|
||||
INCLUDE_DIRS "Source"
|
||||
REQUIRES Tactility driver RadioLibCompat radiolib
|
||||
)
|
||||
7
Drivers/SX126x/README.md
Normal file
7
Drivers/SX126x/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# SX126x
|
||||
|
||||
Radio with LoRa/(G)FSK capabilities.
|
||||
|
||||
## SX1262
|
||||
|
||||
- [Product Information](https://www.semtech.com/products/wireless-rf/lora-connect/sx1262)
|
||||
441
Drivers/SX126x/Source/Sx1262.cpp
Normal file
441
Drivers/SX126x/Source/Sx1262.cpp
Normal file
@ -0,0 +1,441 @@
|
||||
#include "Sx1262.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "hal/gpio_hal.h"
|
||||
|
||||
constexpr const char* TAG = "Sx1262";
|
||||
|
||||
template<typename T>
|
||||
static constexpr Sx1262::ParameterStatus checkLimitsAndApply(T &target, const float value, const float lower, const float upper, const unsigned step = 0) {
|
||||
if ((value >= lower) && (value <= upper)) {
|
||||
if (step != 0) {
|
||||
int ivalue = static_cast<int>(value);
|
||||
if ((ivalue % step) != 0) {
|
||||
return Sx1262::ParameterStatus::ValueError;
|
||||
}
|
||||
}
|
||||
|
||||
target = static_cast<T>(value);
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
}
|
||||
return Sx1262::ParameterStatus::ValueError;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static constexpr Sx1262::ParameterStatus checkValuesAndApply(T &target, const float value, std::initializer_list<float> valids) {
|
||||
for (float valid : valids) {
|
||||
if (value == valid) {
|
||||
target = static_cast<T>(value);
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
}
|
||||
}
|
||||
return Sx1262::ParameterStatus::ValueError;
|
||||
}
|
||||
|
||||
void IRAM_ATTR dio1handler(void* context) {
|
||||
((Sx1262*)context)->dio1Event();
|
||||
}
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::setLoraParameter(const Parameter parameter, const float value) {
|
||||
using enum Parameter;
|
||||
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
return checkLimitsAndApply(power, value, -9.0, 22.0);
|
||||
case Frequency:
|
||||
return checkLimitsAndApply(frequency, value, 150.0, 960.0);
|
||||
case Bandwidth:
|
||||
return checkValuesAndApply(bandwidth, value, {
|
||||
7.8, 10.4, 15.6, 20.8, 31.25, 41.7, 62.5, 125.0, 250.0, 500.0
|
||||
});
|
||||
case SpreadFactor:
|
||||
return checkLimitsAndApply(spreadFactor, value, 7.0, 12.0, 1);
|
||||
case CodingRate:
|
||||
return checkLimitsAndApply(codingRate, value, 5.0, 8.0, 1);
|
||||
case SyncWord:
|
||||
return checkLimitsAndApply(syncWord, value, 0.0, 255.0, 1);
|
||||
case PreambleLength:
|
||||
return checkLimitsAndApply(preambleLength, value, 0.0, 65535.0, 1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TT_LOG_W(TAG, "Tried to set unsupported LoRa parameter \"%s\" to %f", toString(parameter), value);
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::setFskParameter(const Parameter parameter, const float value) {
|
||||
using enum Parameter;
|
||||
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
return checkLimitsAndApply(power, value, -9.0, 22.0);
|
||||
case Frequency:
|
||||
return checkLimitsAndApply(frequency, value, 150.0, 960.0);
|
||||
case Bandwidth:
|
||||
return checkValuesAndApply(bandwidth, value, {
|
||||
4.8, 5.8, 7.3, 9.7, 11.7, 14.6, 19.5, 23.4, 29.3, 39.0, 46.9, 58.6, 78.2
|
||||
});
|
||||
case PreambleLength:
|
||||
return checkLimitsAndApply(preambleLength, value, 0.0, 65535.0, 1);
|
||||
case DataRate:
|
||||
return checkLimitsAndApply(bitRate, value, 0.6, 300.0);
|
||||
case FrequencyDeviation:
|
||||
return checkLimitsAndApply(frequencyDeviation, value, 0.0, 200.0);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TT_LOG_W(TAG, "Tried to set unsupported FSK parameter \"%s\" to %f", toString(parameter), value);
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::setLrFhssParameter(const Parameter parameter, const float value) {
|
||||
using enum Parameter;
|
||||
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
return checkLimitsAndApply(power, value, -9.0, 22.0);
|
||||
case Bandwidth:
|
||||
return checkValuesAndApply(bandwidth, value, {
|
||||
39.06, 85.94, 136.72, 183.59, 335.94, 386.72, 722.66, 773.44, 1523.4, 1574.2
|
||||
});
|
||||
case CodingRate:
|
||||
return checkValuesAndApply(codingRate, value, {
|
||||
RADIOLIB_SX126X_LR_FHSS_CR_5_6,
|
||||
RADIOLIB_SX126X_LR_FHSS_CR_2_3,
|
||||
RADIOLIB_SX126X_LR_FHSS_CR_1_2,
|
||||
RADIOLIB_SX126X_LR_FHSS_CR_1_3
|
||||
});
|
||||
case NarrowGrid:
|
||||
return checkLimitsAndApply(narrowGrid, value, 0.0, 1.0, 1);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TT_LOG_W(TAG, "Tried to set unsupported LR-FHSS parameter \"%s\" to %f", toString(parameter), value);
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::setParameter(const Parameter parameter, const float value) {
|
||||
const auto currentModulation = getModulation();
|
||||
|
||||
switch (currentModulation) {
|
||||
case Modulation::LoRa:
|
||||
return setLoraParameter(parameter, value);
|
||||
case Modulation::Fsk:
|
||||
return setFskParameter(parameter, value);
|
||||
case Modulation::LrFhss:
|
||||
return setLrFhssParameter(parameter, value);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Shouldn't be reachable, return failsafe value
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::getLoraParameter(const Parameter parameter, float &value) const {
|
||||
using enum Parameter;
|
||||
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
value = power;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case Frequency:
|
||||
value = frequency;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case Bandwidth:
|
||||
value = bandwidth;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case SpreadFactor:
|
||||
value = spreadFactor;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case CodingRate:
|
||||
value = codingRate;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case SyncWord:
|
||||
value = syncWord;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case PreambleLength:
|
||||
value = preambleLength;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::getFskParameter(const Parameter parameter, float &value) const {
|
||||
using enum Parameter;
|
||||
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
value = power;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case Frequency:
|
||||
value = frequency;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case Bandwidth:
|
||||
value = bandwidth;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case DataRate:
|
||||
value = bitRate;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case FrequencyDeviation:
|
||||
value = frequencyDeviation;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::getLrFhssParameter(const Parameter parameter, float &value) const {
|
||||
using enum Parameter;
|
||||
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
value = power;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case Bandwidth:
|
||||
value = bandwidth;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case CodingRate:
|
||||
value = codingRate;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
case NarrowGrid:
|
||||
value = narrowGrid;
|
||||
return Sx1262::ParameterStatus::Success;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
|
||||
Sx1262::ParameterStatus Sx1262::getParameter(const Parameter parameter, float &value) const {
|
||||
const auto currentModulation = getModulation();
|
||||
|
||||
// No warnings are emitted to be able to discover parameters by return status
|
||||
switch (currentModulation) {
|
||||
case Modulation::LoRa:
|
||||
return getLoraParameter(parameter, value);
|
||||
case Modulation::Fsk:
|
||||
return getFskParameter(parameter, value);
|
||||
case Modulation::LrFhss:
|
||||
return getLrFhssParameter(parameter, value);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Shouldn't be reachable, return failsafe value
|
||||
return Sx1262::ParameterStatus::Unavailable;
|
||||
}
|
||||
|
||||
tt::hal::radio::Unit Sx1262::getParameterUnit(const Parameter parameter) const {
|
||||
using enum Parameter;
|
||||
using Unit = tt::hal::radio::Unit;
|
||||
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
return Unit(Unit::Name::DecibelMilliwatts);
|
||||
case Frequency:
|
||||
return Unit(Unit::Prefix::Mega, Unit::Name::Herz);
|
||||
case Bandwidth:
|
||||
return Unit(Unit::Prefix::Kilo, Unit::Name::Herz);
|
||||
case SpreadFactor:
|
||||
case CodingRate: // no break
|
||||
case SyncWord: // no break
|
||||
case PreambleLength: // no break
|
||||
return Unit(Unit::Name::None);
|
||||
case DataRate:
|
||||
return Unit(Unit::Prefix::Kilo, Unit::Name::BitsPerSecond);
|
||||
case FrequencyDeviation:
|
||||
return Unit(Unit::Prefix::Kilo, Unit::Name::Herz);
|
||||
case NarrowGrid:
|
||||
return Unit(Unit::Name::None);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
TT_LOG_W(TAG, "Tried to get unit for unsupported parameter \"%s\"", toString(parameter));
|
||||
return Unit(Unit::Name::None);
|
||||
}
|
||||
|
||||
void Sx1262::registerDio1Isr() {
|
||||
gpio_hal_context_t gpiohal;
|
||||
gpiohal.dev = GPIO_LL_GET_HW(GPIO_PORT_0);
|
||||
|
||||
gpio_config_t conf = {
|
||||
.pin_bit_mask = (1ULL<<configuration.irqPin),
|
||||
.mode = (gpio_mode_t)GPIO_MODE_INPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_ENABLE,
|
||||
.intr_type = (gpio_int_type_t)gpiohal.dev->pin[configuration.irqPin].int_type,
|
||||
};
|
||||
gpio_config(&conf);
|
||||
|
||||
// We cannot use the RadioLib API to register this action,
|
||||
// as it does not have the capability to pass an instance pointer via context.
|
||||
// A trampoline has been tried, but is not linkable to be in IRAM_ATTR (dangerous relocation).
|
||||
gpio_install_isr_service((int)ESP_INTR_FLAG_IRAM);
|
||||
gpio_set_intr_type(configuration.irqPin, GPIO_INTR_POSEDGE);
|
||||
gpio_isr_handler_add(configuration.irqPin, dio1handler, this);
|
||||
}
|
||||
|
||||
void Sx1262::unregisterDio1Isr() {
|
||||
gpio_isr_handler_remove(configuration.irqPin);
|
||||
gpio_wakeup_disable(configuration.irqPin);
|
||||
gpio_set_intr_type(configuration.irqPin, GPIO_INTR_DISABLE);
|
||||
}
|
||||
|
||||
void IRAM_ATTR Sx1262::dio1Event() {
|
||||
static const auto DRAM_ATTR bit = SX1262_DIO1_EVENT_BIT;
|
||||
events.set(bit);
|
||||
}
|
||||
|
||||
void Sx1262::txQueuedSignal() {
|
||||
events.set(SX1262_QUEUED_TX_BIT);
|
||||
}
|
||||
|
||||
void Sx1262::interruptSignal() {
|
||||
events.set(SX1262_INTERRUPT_BIT);
|
||||
}
|
||||
|
||||
int Sx1262::doBegin(const Modulation modulation) {
|
||||
uint16_t rc = RADIOLIB_ERR_NONE;
|
||||
|
||||
if (modulation == Modulation::LoRa) {
|
||||
rc = radio.begin(
|
||||
frequency,
|
||||
bandwidth,
|
||||
spreadFactor,
|
||||
codingRate,
|
||||
syncWord,
|
||||
power,
|
||||
preambleLength,
|
||||
configuration.tcxoVoltage,
|
||||
configuration.useRegulatorLdo
|
||||
);
|
||||
} else if (modulation == Modulation::Fsk) {
|
||||
rc = radio.beginFSK(
|
||||
frequency,
|
||||
bitRate,
|
||||
frequencyDeviation,
|
||||
bandwidth,
|
||||
power,
|
||||
preambleLength,
|
||||
configuration.tcxoVoltage,
|
||||
configuration.useRegulatorLdo
|
||||
);
|
||||
} else if (modulation == Modulation::LrFhss) {
|
||||
rc = radio.beginLRFHSS(
|
||||
bandwidth,
|
||||
codingRate,
|
||||
narrowGrid,
|
||||
configuration.tcxoVoltage,
|
||||
configuration.useRegulatorLdo
|
||||
);
|
||||
} else {
|
||||
TT_LOG_E(TAG, "SX1262 not capable of modulation \"%s\"", toString(modulation));
|
||||
setState(State::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (rc != RADIOLIB_ERR_NONE) {
|
||||
TT_LOG_E(TAG, "Radiolib initialization failed with code %hi", rc);
|
||||
setState(State::Error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
registerDio1Isr();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Sx1262::doEnd() {
|
||||
unregisterDio1Isr();
|
||||
}
|
||||
|
||||
void Sx1262::doTransmit() {
|
||||
currentTx = popNextQueuedTx();
|
||||
uint16_t rc = RADIOLIB_ERR_NONE;
|
||||
rc = radio.standby();
|
||||
if (rc != RADIOLIB_ERR_NONE) {
|
||||
TT_LOG_W(TAG, "RadioLib returned %hi on standby", rc);
|
||||
}
|
||||
|
||||
if (getModulation() == Modulation::Fsk) {
|
||||
rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size(),
|
||||
currentTx.packet.address);
|
||||
} else {
|
||||
rc = radio.startTransmit(currentTx.packet.data.data(), currentTx.packet.data.size());
|
||||
}
|
||||
|
||||
if (rc == RADIOLIB_ERR_NONE) {
|
||||
currentTx.callback(currentTx.id, TransmissionState::PendingTransmit);
|
||||
|
||||
auto txEventFlags = events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT, tt::EventFlag::WaitAny,
|
||||
pdMS_TO_TICKS(SX1262_TX_TIMEOUT_MILLIS));
|
||||
|
||||
// Thread might've been interrupted in the meanwhile
|
||||
if (isThreadInterrupted()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If the DIO1 bit is unset, this means the wait timed out
|
||||
if (txEventFlags & SX1262_DIO1_EVENT_BIT) {
|
||||
currentTx.callback(currentTx.id, TransmissionState::Transmitted);
|
||||
} else {
|
||||
currentTx.callback(currentTx.id, TransmissionState::Timeout);
|
||||
}
|
||||
|
||||
} else {
|
||||
TT_LOG_E(TAG, "Error transmitting id=%d, rc=%hi", currentTx.id, rc);
|
||||
currentTx.callback(currentTx.id, TransmissionState::Error);
|
||||
}
|
||||
}
|
||||
|
||||
void Sx1262::doListen() {
|
||||
if (getModulation() != Modulation::LrFhss) {
|
||||
radio.startReceive();
|
||||
events.wait(SX1262_INTERRUPT_BIT | SX1262_DIO1_EVENT_BIT | SX1262_QUEUED_TX_BIT);
|
||||
} else {
|
||||
// LR-FHSS modem only supports TX
|
||||
events.wait(SX1262_INTERRUPT_BIT | SX1262_QUEUED_TX_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void Sx1262::doReceive() {
|
||||
// LR-FHSS modem only supports TX
|
||||
if (getModulation() == Modulation::LrFhss) return;
|
||||
|
||||
uint16_t rxSize = radio.getPacketLength(true);
|
||||
std::vector<uint8_t> data(rxSize);
|
||||
uint16_t rc = radio.readData(data.data(), rxSize);
|
||||
if (rc != RADIOLIB_ERR_NONE) {
|
||||
TT_LOG_E(TAG, "Error receiving data, RadioLib returned %hi", rc);
|
||||
} else if(rxSize == 0) {
|
||||
// This can cause a flood of messages if there are ones emitted here,
|
||||
// as a warning here doesn't bring that much to the table it is skipped.
|
||||
// The body is kept empty intentionally.'
|
||||
} else {
|
||||
float rssi = radio.getRSSI();
|
||||
float snr = radio.getSNR();
|
||||
auto rxPacket = tt::hal::radio::RxPacket {
|
||||
.data = data,
|
||||
.rssi = rssi,
|
||||
.snr = snr
|
||||
};
|
||||
|
||||
publishRx(rxPacket);
|
||||
}
|
||||
|
||||
// A delay before a new command improves reliability
|
||||
vTaskDelay(pdMS_TO_TICKS(SX1262_COOLDOWN_MILLIS));
|
||||
}
|
||||
|
||||
108
Drivers/SX126x/Source/Sx1262.h
Normal file
108
Drivers/SX126x/Source/Sx1262.h
Normal file
@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <Tactility/hal/spi/Spi.h>
|
||||
#include <Tactility/EventFlag.h>
|
||||
#include <Tactility/Lock.h>
|
||||
|
||||
#include <RadioLib.h>
|
||||
#include "RadiolibTactilityHal.h"
|
||||
#include "RadiolibThreadedDevice.h"
|
||||
|
||||
#include <utility>
|
||||
|
||||
class Sx1262 final : public RadiolibThreadedDevice {
|
||||
|
||||
public:
|
||||
struct Configuration {
|
||||
spi_host_device_t spiHostDevice;
|
||||
int spiFrequency;
|
||||
gpio_num_t csPin;
|
||||
gpio_num_t resetPin;
|
||||
gpio_num_t busyPin;
|
||||
gpio_num_t irqPin;
|
||||
float tcxoVoltage;
|
||||
bool useRegulatorLdo;
|
||||
};
|
||||
|
||||
private:
|
||||
static constexpr auto SX1262_DEFAULT_NAME = "SX1262";
|
||||
static constexpr auto SX1262_COOLDOWN_MILLIS = 100;
|
||||
static constexpr auto SX1262_TX_TIMEOUT_MILLIS = 2000;
|
||||
static constexpr auto SX1262_INTERRUPT_BIT = BIT0;
|
||||
static constexpr auto SX1262_DIO1_EVENT_BIT = BIT1;
|
||||
static constexpr auto SX1262_QUEUED_TX_BIT = BIT2;
|
||||
|
||||
std::string name;
|
||||
const Configuration configuration;
|
||||
std::shared_ptr<tt::Lock> lock;
|
||||
tt::EventFlag events;
|
||||
RadiolibTactilityHal hal;
|
||||
Module radioModule;
|
||||
SX1262 radio;
|
||||
TxItem currentTx;
|
||||
|
||||
// Shared parameters which have a common lowest value are set here
|
||||
int8_t power = -9.0;
|
||||
float frequency = 150;
|
||||
float bandwidth = 0.0;
|
||||
uint8_t spreadFactor = 0.0;
|
||||
uint8_t codingRate = 0;
|
||||
uint8_t syncWord = 0;
|
||||
uint16_t preambleLength = 0;
|
||||
float bitRate = 0.0;
|
||||
float frequencyDeviation = 0.0;
|
||||
bool narrowGrid = false;
|
||||
|
||||
void registerDio1Isr();
|
||||
void unregisterDio1Isr();
|
||||
|
||||
ParameterStatus setLoraParameter(const Parameter parameter, const float value);
|
||||
ParameterStatus setFskParameter(const Parameter parameter, const float value);
|
||||
ParameterStatus setLrFhssParameter(const Parameter parameter, const float value);
|
||||
ParameterStatus getLoraParameter(const Parameter parameter, float &value) const;
|
||||
ParameterStatus getFskParameter(const Parameter parameter, float &value) const;
|
||||
ParameterStatus getLrFhssParameter(const Parameter parameter, float &value) const;
|
||||
|
||||
|
||||
protected:
|
||||
virtual void txQueuedSignal() override;
|
||||
virtual void interruptSignal() override;
|
||||
|
||||
virtual int doBegin(const Modulation modulation) override;
|
||||
virtual void doEnd() override;
|
||||
virtual void doTransmit() override;
|
||||
virtual void doListen() override;
|
||||
virtual void doReceive() override;
|
||||
|
||||
public:
|
||||
|
||||
explicit Sx1262(const Configuration& configuration, const std::string& name = SX1262_DEFAULT_NAME)
|
||||
: RadiolibThreadedDevice(name, 4096)
|
||||
, name(name)
|
||||
, configuration(configuration)
|
||||
, hal(configuration.spiHostDevice, configuration.spiFrequency, configuration.csPin)
|
||||
, radioModule(&hal, configuration.csPin, configuration.irqPin, configuration.resetPin, configuration.busyPin)
|
||||
, radio(&radioModule)
|
||||
{}
|
||||
|
||||
~Sx1262() override = default;
|
||||
|
||||
std::string getName() const override { return name; }
|
||||
std::string getDescription() const override { return "Semtech SX1262 LoRa, FSK and LR-FHSS capable radio"; }
|
||||
|
||||
ParameterStatus setParameter(const Parameter parameter, const float value) override;
|
||||
ParameterStatus getParameter(const Parameter parameter, float &value) const override;
|
||||
tt::hal::radio::Unit getParameterUnit(const Parameter parameter) const override;
|
||||
|
||||
bool canTransmit(const Modulation modulation) override {
|
||||
return (modulation == Modulation::Fsk) ||
|
||||
(modulation == Modulation::LoRa) ||
|
||||
(modulation == Modulation::LrFhss);
|
||||
}
|
||||
|
||||
bool canReceive(const Modulation modulation) override {
|
||||
return (modulation == Modulation::Fsk) || (modulation == Modulation::LoRa);
|
||||
}
|
||||
|
||||
void dio1Event();
|
||||
};
|
||||
2
ExternalApps/RadioSet/.gitignore
vendored
Normal file
2
ExternalApps/RadioSet/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
build*/
|
||||
.tactility/
|
||||
16
ExternalApps/RadioSet/CMakeLists.txt
Normal file
16
ExternalApps/RadioSet/CMakeLists.txt
Normal file
@ -0,0 +1,16 @@
|
||||
cmake_minimum_required(VERSION 3.20)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
|
||||
if (DEFINED ENV{TACTILITY_SDK_PATH})
|
||||
set(TACTILITY_SDK_PATH $ENV{TACTILITY_SDK_PATH})
|
||||
else()
|
||||
set(TACTILITY_SDK_PATH "../../release/TactilitySDK")
|
||||
message(WARNING "⚠️ TACTILITY_SDK_PATH environment variable is not set, defaulting to ${TACTILITY_SDK_PATH}")
|
||||
endif()
|
||||
|
||||
include("${TACTILITY_SDK_PATH}/TactilitySDK.cmake")
|
||||
set(EXTRA_COMPONENT_DIRS ${TACTILITY_SDK_PATH})
|
||||
|
||||
project(RadioSet)
|
||||
tactility_project(RadioSet)
|
||||
8
ExternalApps/RadioSet/main/CMakeLists.txt
Normal file
8
ExternalApps/RadioSet/main/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||
|
||||
idf_component_register(
|
||||
SRCS ${SOURCE_FILES}
|
||||
REQUIRES TactilitySDK
|
||||
)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-error=uninitialized -Wno-error=maybe-uninitialized)
|
||||
95
ExternalApps/RadioSet/main/Source/Dequeue.h
Normal file
95
ExternalApps/RadioSet/main/Source/Dequeue.h
Normal file
@ -0,0 +1,95 @@
|
||||
#pragma once
|
||||
|
||||
template <typename DataType>
|
||||
class Dequeue {
|
||||
|
||||
struct Node {
|
||||
DataType data;
|
||||
Node* next;
|
||||
Node* previous;
|
||||
|
||||
Node(DataType data, Node* next, Node* previous):
|
||||
data(data),
|
||||
next(next),
|
||||
previous(previous)
|
||||
{}
|
||||
};
|
||||
|
||||
int count = 0;
|
||||
Node* head = nullptr;
|
||||
Node* tail = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
void pushFront(DataType data) {
|
||||
auto* new_node = new Node(data, head, nullptr);
|
||||
|
||||
if (head != nullptr) {
|
||||
head->previous = new_node;
|
||||
}
|
||||
|
||||
if (tail == nullptr) {
|
||||
tail = new_node;
|
||||
}
|
||||
|
||||
head = new_node;
|
||||
count++;
|
||||
}
|
||||
|
||||
void pushBack(DataType data) {
|
||||
auto* new_node = new Node(data, nullptr, tail);
|
||||
|
||||
if (head == nullptr) {
|
||||
head = new_node;
|
||||
}
|
||||
|
||||
if (tail != nullptr) {
|
||||
tail->next = new_node;
|
||||
}
|
||||
|
||||
tail = new_node;
|
||||
count++;
|
||||
}
|
||||
|
||||
void popFront() {
|
||||
if (head != nullptr) {
|
||||
bool is_last_node = (head == tail);
|
||||
Node* node_to_delete = head;
|
||||
head = node_to_delete->next;
|
||||
if (is_last_node) {
|
||||
tail = nullptr;
|
||||
}
|
||||
delete node_to_delete;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
void popBack() {
|
||||
if (tail != nullptr) {
|
||||
bool is_last_node = (head == tail);
|
||||
Node* node_to_delete = tail;
|
||||
tail = node_to_delete->previous;
|
||||
if (is_last_node) {
|
||||
head = nullptr;
|
||||
}
|
||||
delete node_to_delete;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
DataType back() const {
|
||||
assert(tail != nullptr);
|
||||
return tail->data;
|
||||
}
|
||||
|
||||
DataType front() const {
|
||||
assert(head != nullptr);
|
||||
return head->data;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return head == nullptr;
|
||||
}
|
||||
|
||||
int size() const { return count; }
|
||||
};
|
||||
156
ExternalApps/RadioSet/main/Source/LinkedList.h
Normal file
156
ExternalApps/RadioSet/main/Source/LinkedList.h
Normal file
@ -0,0 +1,156 @@
|
||||
#pragma once
|
||||
|
||||
template <typename DataType>
|
||||
class LinkedList {
|
||||
|
||||
struct Node {
|
||||
DataType data;
|
||||
Node* next;
|
||||
Node* previous;
|
||||
|
||||
Node(DataType data, Node* next, Node* previous):
|
||||
data(data),
|
||||
next(next),
|
||||
previous(previous)
|
||||
{}
|
||||
};
|
||||
|
||||
int count = 0;
|
||||
Node* head = nullptr;
|
||||
Node* tail = nullptr;
|
||||
|
||||
public:
|
||||
class Iterator {
|
||||
Node *node = nullptr;
|
||||
public:
|
||||
Iterator(Node* node)
|
||||
: node(node) {}
|
||||
|
||||
bool advance(size_t n) {
|
||||
size_t i = 0;
|
||||
if (n == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
for (; node && (i < n); ++i) {
|
||||
node = node->next;
|
||||
}
|
||||
return (i > 0);
|
||||
}
|
||||
|
||||
DataType& operator* ()
|
||||
{
|
||||
return node->data;
|
||||
}
|
||||
|
||||
DataType* operator-> ()
|
||||
{
|
||||
return &(node->data);
|
||||
}
|
||||
|
||||
Iterator operator++ (int) {
|
||||
assert(advance(1));
|
||||
Iterator i(node);
|
||||
return i;
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& right) const {
|
||||
return node == right.node;
|
||||
}
|
||||
|
||||
bool operator!=(const Iterator& right) const {
|
||||
return node != right.node;
|
||||
}
|
||||
};
|
||||
|
||||
void pushFront(DataType data) {
|
||||
auto* new_node = new Node(data, head, nullptr);
|
||||
|
||||
if (head != nullptr) {
|
||||
head->previous = new_node;
|
||||
}
|
||||
|
||||
if (tail == nullptr) {
|
||||
tail = new_node;
|
||||
}
|
||||
|
||||
head = new_node;
|
||||
count++;
|
||||
}
|
||||
|
||||
void pushBack(DataType data) {
|
||||
auto* new_node = new Node(data, nullptr, tail);
|
||||
|
||||
if (head == nullptr) {
|
||||
head = new_node;
|
||||
}
|
||||
|
||||
if (tail != nullptr) {
|
||||
tail->next = new_node;
|
||||
}
|
||||
|
||||
tail = new_node;
|
||||
count++;
|
||||
}
|
||||
|
||||
void popFront() {
|
||||
if (head != nullptr) {
|
||||
bool is_last_node = (head == tail);
|
||||
Node* node_to_delete = head;
|
||||
head = node_to_delete->next;
|
||||
if (is_last_node) {
|
||||
tail = nullptr;
|
||||
}
|
||||
delete node_to_delete;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
void popBack() {
|
||||
if (tail != nullptr) {
|
||||
bool is_last_node = (head == tail);
|
||||
Node* node_to_delete = tail;
|
||||
tail = node_to_delete->previous;
|
||||
if (is_last_node) {
|
||||
head = nullptr;
|
||||
}
|
||||
delete node_to_delete;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
DataType back() const {
|
||||
assert(tail != nullptr);
|
||||
return tail->data;
|
||||
}
|
||||
|
||||
DataType front() const {
|
||||
assert(head != nullptr);
|
||||
return head->data;
|
||||
}
|
||||
|
||||
Iterator begin() const {
|
||||
return Iterator(head);
|
||||
}
|
||||
|
||||
Iterator end() const {
|
||||
return Iterator(nullptr);
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return head == nullptr;
|
||||
}
|
||||
|
||||
int size() const { return count; }
|
||||
|
||||
DataType operator [] (int i) const {
|
||||
auto iter = begin();
|
||||
assert(iter.advance(i));
|
||||
return *iter;
|
||||
}
|
||||
DataType& operator [] (int i) {
|
||||
auto iter = begin();
|
||||
assert(iter.advance(i));
|
||||
return *iter;
|
||||
}
|
||||
};
|
||||
37
ExternalApps/RadioSet/main/Source/Preset.h
Normal file
37
ExternalApps/RadioSet/main/Source/Preset.h
Normal file
@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <tt_hal_radio.h>
|
||||
|
||||
#include "Str.h"
|
||||
#include "LinkedList.h"
|
||||
|
||||
class Preset {
|
||||
public:
|
||||
struct PresetItem {
|
||||
RadioParameter parameter;
|
||||
float value;
|
||||
};
|
||||
|
||||
Str name;
|
||||
Modulation modulation;
|
||||
LinkedList<PresetItem> items;
|
||||
|
||||
Preset(const char* const name, Modulation modulation)
|
||||
: name(name)
|
||||
, modulation(modulation)
|
||||
{}
|
||||
|
||||
virtual ~Preset() = default;
|
||||
|
||||
void addParameter(RadioParameter parameter, float value) {
|
||||
items.pushBack({parameter, value});
|
||||
}
|
||||
|
||||
LinkedList<PresetItem>::Iterator begin() {
|
||||
return items.begin();
|
||||
}
|
||||
|
||||
LinkedList<PresetItem>::Iterator end() {
|
||||
return items.end();
|
||||
}
|
||||
};
|
||||
1095
ExternalApps/RadioSet/main/Source/RadioSet.cpp
Normal file
1095
ExternalApps/RadioSet/main/Source/RadioSet.cpp
Normal file
File diff suppressed because it is too large
Load Diff
24
ExternalApps/RadioSet/main/Source/RadioSet.h
Normal file
24
ExternalApps/RadioSet/main/Source/RadioSet.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "tt_app.h"
|
||||
#include "tt_hal_radio.h"
|
||||
#include <lvgl.h>
|
||||
|
||||
class TermView;
|
||||
class SettingsView;
|
||||
|
||||
class RadioSet {
|
||||
lv_obj_t* mainView = nullptr;
|
||||
lv_obj_t* uiDropDownMenu = nullptr;
|
||||
lv_obj_t* progressBar = nullptr;
|
||||
lv_obj_t* progressText = nullptr;
|
||||
|
||||
TermView* termView = nullptr;
|
||||
SettingsView* settingsView = nullptr;
|
||||
|
||||
public:
|
||||
|
||||
~RadioSet();
|
||||
|
||||
void onShow(AppHandle context, lv_obj_t* parent);
|
||||
};
|
||||
2
ExternalApps/RadioSet/main/Source/Str.cpp
Normal file
2
ExternalApps/RadioSet/main/Source/Str.cpp
Normal file
@ -0,0 +1,2 @@
|
||||
#define STR_IMPLEMENTATION
|
||||
#include "Str.h"
|
||||
618
ExternalApps/RadioSet/main/Source/Str.h
Normal file
618
ExternalApps/RadioSet/main/Source/Str.h
Normal file
@ -0,0 +1,618 @@
|
||||
// Str v0.33
|
||||
// Simple C++ string type with an optional local buffer, by Omar Cornut
|
||||
// https://github.com/ocornut/str
|
||||
|
||||
// LICENSE
|
||||
// This software is in the public domain. Where that dedication is not
|
||||
// recognized, you are granted a perpetual, irrevocable license to copy,
|
||||
// distribute, and modify this file as you see fit.
|
||||
|
||||
// USAGE
|
||||
// Include this file in whatever places need to refer to it.
|
||||
// In ONE .cpp file, write '#define STR_IMPLEMENTATION' before the #include of this file.
|
||||
// This expands out the actual implementation into that C/C++ file.
|
||||
|
||||
|
||||
/*
|
||||
- This isn't a fully featured string class.
|
||||
- It is a simple, bearable replacement to std::string that isn't heap abusive nor bloated (can actually be debugged by humans).
|
||||
- String are mutable. We don't maintain size so length() is not-constant time.
|
||||
- Maximum string size currently limited to 2 MB (we allocate 21 bits to hold capacity).
|
||||
- Local buffer size is currently limited to 1023 bytes (we allocate 10 bits to hold local buffer size).
|
||||
- In "non-owned" mode for literals/reference we don't do any tracking/counting of references.
|
||||
- Overhead is 8-bytes in 32-bits, 16-bytes in 64-bits (12 + alignment).
|
||||
- This code hasn't been tested very much. it is probably incomplete or broken. Made it for my own use.
|
||||
|
||||
The idea is that you can provide an arbitrary sized local buffer if you expect string to fit
|
||||
most of the time, and then you avoid using costly heap.
|
||||
|
||||
No local buffer, always use heap, sizeof()==8~16 (depends if your pointers are 32-bits or 64-bits)
|
||||
|
||||
Str s = "hey";
|
||||
|
||||
With a local buffer of 16 bytes, sizeof() == 8~16 + 16 bytes.
|
||||
|
||||
Str16 s = "filename.h"; // copy into local buffer
|
||||
Str16 s = "long_filename_not_very_long_but_longer_than_expected.h"; // use heap
|
||||
|
||||
With a local buffer of 256 bytes, sizeof() == 8~16 + 256 bytes.
|
||||
|
||||
Str256 s = "long_filename_not_very_long_but_longer_than_expected.h"; // copy into local buffer
|
||||
|
||||
Common sizes are defined at the bottom of Str.h, you may define your own.
|
||||
|
||||
Functions:
|
||||
|
||||
Str256 s;
|
||||
s.set("hello sailor"); // set (copy)
|
||||
s.setf("%s/%s.tmp", folder, filename); // set (w/format)
|
||||
s.append("hello"); // append. cost a length() calculation!
|
||||
s.appendf("hello %d", 42); // append (w/format). cost a length() calculation!
|
||||
s.set_ref("Hey!"); // set (literal/reference, just copy pointer, no tracking)
|
||||
|
||||
Constructor helper for format string: add a trailing 'f' to the type. Underlying type is the same.
|
||||
|
||||
Str256f filename("%s/%s.tmp", folder, filename); // construct (w/format)
|
||||
fopen(Str256f("%s/%s.tmp, folder, filename).c_str(), "rb"); // construct (w/format), use as function param, destruct
|
||||
|
||||
Constructor helper for reference/literal:
|
||||
|
||||
StrRef ref("literal"); // copy pointer, no allocation, no string copy
|
||||
StrRef ref2(GetDebugName()); // copy pointer. no tracking of anything whatsoever, know what you are doing!
|
||||
|
||||
All StrXXX types derives from Str and instance hold the local buffer capacity. So you can pass e.g. Str256* to a function taking base type Str* and it will be functional.
|
||||
|
||||
void MyFunc(Str& s) { s = "Hello"; } // will use local buffer if available in Str instance
|
||||
|
||||
(Using a template e.g. Str<N> we could remove the LocalBufSize storage but it would make passing typed Str<> to functions tricky.
|
||||
Instead we don't use template so you can pass them around as the base type Str*. Also, templates are ugly.)
|
||||
*/
|
||||
|
||||
/*
|
||||
CHANGELOG
|
||||
0.33 - fixed capacity() return value to match standard. e.g. a Str256's capacity() now returns 255, not 256.
|
||||
0.32 - added owned() accessor.
|
||||
0.31 - fixed various warnings.
|
||||
0.30 - turned into a single header file, removed Str.cpp.
|
||||
0.29 - fixed bug when calling reserve on non-owned strings (ie. when using StrRef or set_ref), and fixed <string> include.
|
||||
0.28 - breaking change: replaced Str32 by Str30 to avoid collision with Str32 from MacTypes.h .
|
||||
0.27 - added STR_API and basic .natvis file.
|
||||
0.26 - fixed set(cont char* src, const char* src_end) writing null terminator to the wrong position.
|
||||
0.25 - allow set(const char* NULL) or operator= NULL to clear the string. note that set() from range or other types are not allowed.
|
||||
0.24 - allow set_ref(const char* NULL) to clear the string. include fixes for linux.
|
||||
0.23 - added append(char). added append_from(int idx, XXX) functions. fixed some compilers warnings.
|
||||
0.22 - documentation improvements, comments. fixes for some compilers.
|
||||
0.21 - added StrXXXf() constructor to construct directly from a format string.
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO
|
||||
- Since we lose 4-bytes of padding on 64-bits architecture, perhaps just spread the header to 8-bytes and lift size limits?
|
||||
- More functions/helpers.
|
||||
*/
|
||||
|
||||
#ifndef STR_INCLUDED
|
||||
#define STR_INCLUDED
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// CONFIGURATION
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifndef STR_MEMALLOC
|
||||
#define STR_MEMALLOC malloc
|
||||
#include <cstdio>
|
||||
#endif
|
||||
#ifndef STR_MEMFREE
|
||||
#define STR_MEMFREE free
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
#ifndef STR_ASSERT
|
||||
#define STR_ASSERT assert
|
||||
#include <cassert>
|
||||
#endif
|
||||
#ifndef STR_API
|
||||
#define STR_API
|
||||
#endif
|
||||
#include <cstdarg> // for va_list
|
||||
#include <cstring> // for strlen, strcmp, memcpy, etc.
|
||||
|
||||
// Configuration: #define STR_DEFINE_STR32 1 to keep defining Str32/Str32f, but be warned: on macOS/iOS, MacTypes.h also defines a type named Str32.
|
||||
#ifndef STR_DEFINE_STR32
|
||||
#define STR_DEFINE_STR32 0
|
||||
#endif
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// HEADERS
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
// This is the base class that you can pass around
|
||||
// Footprint is 8-bytes (32-bits arch) or 16-bytes (64-bits arch)
|
||||
class STR_API Str
|
||||
{
|
||||
char* Data; // Point to LocalBuf() or heap allocated
|
||||
int Capacity : 21; // Max 2 MB. Exclude zero terminator.
|
||||
int LocalBufSize : 10; // Max 1023 bytes
|
||||
unsigned int Owned : 1; // Set when we have ownership of the pointed data (most common, unless using set_ref() method or StrRef constructor)
|
||||
|
||||
public:
|
||||
inline char* c_str() { return Data; }
|
||||
inline const char* c_str() const { return Data; }
|
||||
inline bool empty() const { return Data[0] == 0; }
|
||||
inline int length() const { return (int)strlen(Data); } // by design, allow user to write into the buffer at any time
|
||||
inline int capacity() const { return Capacity; }
|
||||
inline bool owned() const { return Owned ? true : false; }
|
||||
|
||||
inline void set_ref(const char* src);
|
||||
int setf(const char* fmt, ...);
|
||||
int setfv(const char* fmt, va_list args);
|
||||
int setf_nogrow(const char* fmt, ...);
|
||||
int setfv_nogrow(const char* fmt, va_list args);
|
||||
int append(char c);
|
||||
int append(const char* s, const char* s_end = NULL);
|
||||
int appendf(const char* fmt, ...);
|
||||
int appendfv(const char* fmt, va_list args);
|
||||
int append_from(int idx, char c);
|
||||
int append_from(int idx, const char* s, const char* s_end = NULL); // If you know the string length or want to append from a certain point
|
||||
int appendf_from(int idx, const char* fmt, ...);
|
||||
int appendfv_from(int idx, const char* fmt, va_list args);
|
||||
|
||||
void clear();
|
||||
void reserve(int cap);
|
||||
void reserve_discard(int cap);
|
||||
void shrink_to_fit();
|
||||
|
||||
inline char& operator[](size_t i) { return Data[i]; }
|
||||
inline char operator[](size_t i) const { return Data[i]; }
|
||||
//explicit operator const char*() const{ return Data; }
|
||||
|
||||
inline Str();
|
||||
inline Str(const char* rhs);
|
||||
inline void set(const char* src);
|
||||
inline void set(const char* src, const char* src_end);
|
||||
inline Str& operator=(const char* rhs) { set(rhs); return *this; }
|
||||
inline bool operator==(const char* rhs) const { return strcmp(c_str(), rhs) == 0; }
|
||||
|
||||
inline Str(const Str& rhs);
|
||||
inline void set(const Str& src);
|
||||
inline void set(int count, char character);
|
||||
inline Str& operator=(const Str& rhs) { set(rhs); return *this; }
|
||||
inline bool operator==(const Str& rhs) const { return strcmp(c_str(), rhs.c_str()) == 0; }
|
||||
|
||||
inline Str(int amount, char character);
|
||||
|
||||
// Destructor for all variants
|
||||
inline ~Str()
|
||||
{
|
||||
if (Owned && !is_using_local_buf())
|
||||
STR_MEMFREE(Data);
|
||||
}
|
||||
|
||||
static char* EmptyBuffer;
|
||||
|
||||
protected:
|
||||
inline char* local_buf() { return (char*)this + sizeof(Str); }
|
||||
inline const char* local_buf() const { return (char*)this + sizeof(Str); }
|
||||
inline bool is_using_local_buf() const { return Data == local_buf() && LocalBufSize != 0; }
|
||||
|
||||
// Constructor for StrXXX variants with local buffer
|
||||
Str(unsigned short local_buf_size)
|
||||
{
|
||||
STR_ASSERT(local_buf_size < 1024);
|
||||
Data = local_buf();
|
||||
Data[0] = '\0';
|
||||
Capacity = local_buf_size ? local_buf_size - 1 : 0;
|
||||
LocalBufSize = local_buf_size;
|
||||
Owned = 1;
|
||||
}
|
||||
};
|
||||
|
||||
void Str::set(const char* src)
|
||||
{
|
||||
// We allow set(NULL) or via = operator to clear the string.
|
||||
if (src == NULL)
|
||||
{
|
||||
clear();
|
||||
return;
|
||||
}
|
||||
int buf_len = (int)strlen(src);
|
||||
if (Capacity < buf_len)
|
||||
reserve_discard(buf_len);
|
||||
memcpy(Data, src, (size_t)(buf_len + 1));
|
||||
Owned = 1;
|
||||
}
|
||||
|
||||
void Str::set(const char* src, const char* src_end)
|
||||
{
|
||||
STR_ASSERT(src != NULL && src_end >= src);
|
||||
int buf_len = (int)(src_end - src);
|
||||
if ((int)Capacity < buf_len)
|
||||
reserve_discard(buf_len);
|
||||
memcpy(Data, src, (size_t)buf_len);
|
||||
Data[buf_len] = 0;
|
||||
Owned = 1;
|
||||
}
|
||||
|
||||
void Str::set(const Str& src)
|
||||
{
|
||||
int buf_len = (int)strlen(src.c_str());
|
||||
if ((int)Capacity < buf_len)
|
||||
reserve_discard(buf_len);
|
||||
memcpy(Data, src.c_str(), (size_t)(buf_len + 1));
|
||||
Owned = 1;
|
||||
}
|
||||
|
||||
void Str::set(int count, char character) {
|
||||
int buf_len = count + 1;
|
||||
if ((int)Capacity < buf_len)
|
||||
reserve_discard(buf_len);
|
||||
memset(Data, character, count);
|
||||
Data[count] = 0;
|
||||
Owned = 1;
|
||||
}
|
||||
|
||||
inline void Str::set_ref(const char* src)
|
||||
{
|
||||
if (Owned && !is_using_local_buf())
|
||||
STR_MEMFREE(Data);
|
||||
Data = src ? (char*)src : EmptyBuffer;
|
||||
Capacity = 0;
|
||||
Owned = 0;
|
||||
}
|
||||
|
||||
Str::Str()
|
||||
{
|
||||
Data = EmptyBuffer; // Shared READ-ONLY initial buffer for 0 capacity
|
||||
Capacity = 0;
|
||||
LocalBufSize = 0;
|
||||
Owned = 0;
|
||||
}
|
||||
|
||||
Str::Str(const Str& rhs) : Str()
|
||||
{
|
||||
set(rhs);
|
||||
}
|
||||
|
||||
Str::Str(const char* rhs) : Str()
|
||||
{
|
||||
set(rhs);
|
||||
}
|
||||
|
||||
Str::Str(int amount, char character) : Str() {
|
||||
set(amount, character);
|
||||
}
|
||||
|
||||
// Literal/reference string
|
||||
class StrRef : public Str
|
||||
{
|
||||
public:
|
||||
StrRef(const char* s) : Str() { set_ref(s); }
|
||||
};
|
||||
|
||||
#define STR_DEFINETYPE(TYPENAME, LOCALBUFSIZE) \
|
||||
class TYPENAME : public Str \
|
||||
{ \
|
||||
char local_buf[LOCALBUFSIZE]; \
|
||||
public: \
|
||||
TYPENAME() : Str(LOCALBUFSIZE) {} \
|
||||
TYPENAME(const Str& rhs) : Str(LOCALBUFSIZE) { set(rhs); } \
|
||||
TYPENAME(const char* rhs) : Str(LOCALBUFSIZE) { set(rhs); } \
|
||||
TYPENAME(const TYPENAME& rhs) : Str(LOCALBUFSIZE) { set(rhs); } \
|
||||
TYPENAME& operator=(const char* rhs) { set(rhs); return *this; } \
|
||||
TYPENAME& operator=(const Str& rhs) { set(rhs); return *this; } \
|
||||
TYPENAME& operator=(const TYPENAME& rhs) { set(rhs); return *this; } \
|
||||
};
|
||||
|
||||
// Disable PVS-Studio warning V730: Not all members of a class are initialized inside the constructor (local_buf is not initialized and that is fine)
|
||||
// -V:STR_DEFINETYPE:730
|
||||
|
||||
// Helper to define StrXXXf constructors
|
||||
#define STR_DEFINETYPE_F(TYPENAME, TYPENAME_F) \
|
||||
class TYPENAME_F : public TYPENAME \
|
||||
{ \
|
||||
public: \
|
||||
TYPENAME_F(const char* fmt, ...) : TYPENAME() { va_list args; va_start(args, fmt); setfv(fmt, args); va_end(args); } \
|
||||
};
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-private-field" // warning : private field 'local_buf' is not used
|
||||
#endif
|
||||
|
||||
// Declaring types for common sizes here
|
||||
STR_DEFINETYPE(Str16, 16)
|
||||
STR_DEFINETYPE(Str30, 30)
|
||||
STR_DEFINETYPE(Str64, 64)
|
||||
STR_DEFINETYPE(Str128, 128)
|
||||
STR_DEFINETYPE(Str256, 256)
|
||||
STR_DEFINETYPE(Str512, 512)
|
||||
|
||||
// Declaring helper constructors to pass in format strings in one statement
|
||||
STR_DEFINETYPE_F(Str16, Str16f)
|
||||
STR_DEFINETYPE_F(Str30, Str30f)
|
||||
STR_DEFINETYPE_F(Str64, Str64f)
|
||||
STR_DEFINETYPE_F(Str128, Str128f)
|
||||
STR_DEFINETYPE_F(Str256, Str256f)
|
||||
STR_DEFINETYPE_F(Str512, Str512f)
|
||||
|
||||
#if STR_DEFINE_STR32
|
||||
STR_DEFINETYPE(Str32, 32)
|
||||
STR_DEFINETYPE_F(Str32, Str32f)
|
||||
#endif
|
||||
|
||||
#ifdef __clang__
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
|
||||
#endif // #ifndef STR_INCLUDED
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
// IMPLEMENTATION
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
#ifdef STR_IMPLEMENTATION
|
||||
|
||||
#include <stdio.h> // for vsnprintf
|
||||
|
||||
// On some platform vsnprintf() takes va_list by reference and modifies it.
|
||||
// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
|
||||
#ifndef va_copy
|
||||
#define va_copy(dest, src) (dest = src)
|
||||
#endif
|
||||
|
||||
// Static empty buffer we can point to for empty strings
|
||||
// Pointing to a literal increases the like-hood of getting a crash if someone attempts to write in the empty string buffer.
|
||||
char* Str::EmptyBuffer = (char*)"\0NULL";
|
||||
|
||||
// Clear
|
||||
void Str::clear()
|
||||
{
|
||||
if (Owned && !is_using_local_buf())
|
||||
STR_MEMFREE(Data);
|
||||
if (LocalBufSize)
|
||||
{
|
||||
Data = local_buf();
|
||||
Data[0] = '\0';
|
||||
Capacity = LocalBufSize - 1;
|
||||
Owned = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Data = EmptyBuffer;
|
||||
Capacity = 0;
|
||||
Owned = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Reserve memory, preserving the current of the buffer
|
||||
// Capacity doesn't include the zero terminator, so reserve(5) is enough to store "hello".
|
||||
void Str::reserve(int new_capacity)
|
||||
{
|
||||
if (new_capacity <= Capacity)
|
||||
return;
|
||||
|
||||
char* new_data;
|
||||
if (new_capacity <= LocalBufSize - 1)
|
||||
{
|
||||
// Disowned -> LocalBuf
|
||||
new_data = local_buf();
|
||||
new_capacity = LocalBufSize - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disowned or LocalBuf -> Heap
|
||||
new_data = (char*)STR_MEMALLOC((size_t)(new_capacity + 1) * sizeof(char));
|
||||
}
|
||||
|
||||
// string in Data might be longer than new_capacity if it wasn't owned, don't copy too much
|
||||
#ifdef _MSC_VER
|
||||
strncpy_s(new_data, (size_t)new_capacity + 1, Data, (size_t)new_capacity);
|
||||
#else
|
||||
strncpy(new_data, Data, (size_t)new_capacity);
|
||||
#endif
|
||||
new_data[new_capacity] = 0;
|
||||
|
||||
if (Owned && !is_using_local_buf())
|
||||
STR_MEMFREE(Data);
|
||||
|
||||
Data = new_data;
|
||||
Capacity = new_capacity;
|
||||
Owned = 1;
|
||||
}
|
||||
|
||||
// Reserve memory, discarding the current of the buffer (if we expect to be fully rewritten)
|
||||
void Str::reserve_discard(int new_capacity)
|
||||
{
|
||||
if (new_capacity <= Capacity)
|
||||
return;
|
||||
|
||||
if (Owned && !is_using_local_buf())
|
||||
STR_MEMFREE(Data);
|
||||
|
||||
if (new_capacity <= LocalBufSize - 1)
|
||||
{
|
||||
// Disowned -> LocalBuf
|
||||
Data = local_buf();
|
||||
Capacity = LocalBufSize - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Disowned or LocalBuf -> Heap
|
||||
Data = (char*)STR_MEMALLOC((size_t)(new_capacity + 1) * sizeof(char));
|
||||
Capacity = new_capacity;
|
||||
}
|
||||
Owned = 1;
|
||||
}
|
||||
|
||||
void Str::shrink_to_fit()
|
||||
{
|
||||
if (!Owned || is_using_local_buf())
|
||||
return;
|
||||
int new_capacity = length();
|
||||
if (Capacity <= new_capacity)
|
||||
return;
|
||||
|
||||
char* new_data = (char*)STR_MEMALLOC((size_t)(new_capacity + 1) * sizeof(char));
|
||||
memcpy(new_data, Data, (size_t)(new_capacity + 1));
|
||||
STR_MEMFREE(Data);
|
||||
Data = new_data;
|
||||
Capacity = new_capacity;
|
||||
}
|
||||
|
||||
// FIXME: merge setfv() and appendfv()?
|
||||
int Str::setfv(const char* fmt, va_list args)
|
||||
{
|
||||
// Needed for portability on platforms where va_list are passed by reference and modified by functions
|
||||
va_list args2;
|
||||
va_copy(args2, args);
|
||||
|
||||
// MSVC returns -1 on overflow when writing, which forces us to do two passes
|
||||
// FIXME-OPT: Find a way around that.
|
||||
#ifdef _MSC_VER
|
||||
int len = vsnprintf(NULL, 0, fmt, args);
|
||||
STR_ASSERT(len >= 0);
|
||||
|
||||
if (Capacity < len)
|
||||
reserve_discard(len);
|
||||
len = vsnprintf(Data, (size_t)len + 1, fmt, args2);
|
||||
#else
|
||||
// First try
|
||||
int len = vsnprintf(Owned ? Data : NULL, Owned ? (size_t)(Capacity + 1): 0, fmt, args);
|
||||
STR_ASSERT(len >= 0);
|
||||
|
||||
if (Capacity < len)
|
||||
{
|
||||
reserve_discard(len);
|
||||
len = vsnprintf(Data, (size_t)len + 1, fmt, args2);
|
||||
}
|
||||
#endif
|
||||
|
||||
STR_ASSERT(Owned);
|
||||
return len;
|
||||
}
|
||||
|
||||
int Str::setf(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = setfv(fmt, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
int Str::setfv_nogrow(const char* fmt, va_list args)
|
||||
{
|
||||
STR_ASSERT(Owned);
|
||||
|
||||
if (Capacity == 0)
|
||||
return 0;
|
||||
|
||||
int w = vsnprintf(Data, (size_t)(Capacity + 1), fmt, args);
|
||||
Data[Capacity] = 0;
|
||||
Owned = 1;
|
||||
return (w == -1) ? Capacity : w;
|
||||
}
|
||||
|
||||
int Str::setf_nogrow(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = setfv_nogrow(fmt, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
int Str::append_from(int idx, char c)
|
||||
{
|
||||
int add_len = 1;
|
||||
if (Capacity < idx + add_len)
|
||||
reserve(idx + add_len);
|
||||
Data[idx] = c;
|
||||
Data[idx + add_len] = 0;
|
||||
STR_ASSERT(Owned);
|
||||
return add_len;
|
||||
}
|
||||
|
||||
int Str::append_from(int idx, const char* s, const char* s_end)
|
||||
{
|
||||
if (!s_end)
|
||||
s_end = s + strlen(s);
|
||||
int add_len = (int)(s_end - s);
|
||||
if (Capacity < idx + add_len)
|
||||
reserve(idx + add_len);
|
||||
memcpy(Data + idx, (const void*)s, (size_t)add_len);
|
||||
Data[idx + add_len] = 0; // Our source data isn't necessarily zero terminated
|
||||
STR_ASSERT(Owned);
|
||||
return add_len;
|
||||
}
|
||||
|
||||
// FIXME: merge setfv() and appendfv()?
|
||||
int Str::appendfv_from(int idx, const char* fmt, va_list args)
|
||||
{
|
||||
// Needed for portability on platforms where va_list are passed by reference and modified by functions
|
||||
va_list args2;
|
||||
va_copy(args2, args);
|
||||
|
||||
// MSVC returns -1 on overflow when writing, which forces us to do two passes
|
||||
// FIXME-OPT: Find a way around that.
|
||||
#ifdef _MSC_VER
|
||||
int add_len = vsnprintf(NULL, 0, fmt, args);
|
||||
STR_ASSERT(add_len >= 0);
|
||||
|
||||
if (Capacity < idx + add_len)
|
||||
reserve(idx + add_len);
|
||||
add_len = vsnprintf(Data + idx, add_len + 1, fmt, args2);
|
||||
#else
|
||||
// First try
|
||||
int add_len = vsnprintf(Owned ? Data + idx : NULL, Owned ? (size_t)(Capacity + 1 - idx) : 0, fmt, args);
|
||||
STR_ASSERT(add_len >= 0);
|
||||
|
||||
if (Capacity < idx + add_len)
|
||||
{
|
||||
reserve(idx + add_len);
|
||||
add_len = vsnprintf(Data + idx, (size_t)add_len + 1, fmt, args2);
|
||||
}
|
||||
#endif
|
||||
|
||||
STR_ASSERT(Owned);
|
||||
return add_len;
|
||||
}
|
||||
|
||||
int Str::appendf_from(int idx, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = appendfv_from(idx, fmt, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
int Str::append(char c)
|
||||
{
|
||||
int cur_len = length();
|
||||
return append_from(cur_len, c);
|
||||
}
|
||||
|
||||
int Str::append(const char* s, const char* s_end)
|
||||
{
|
||||
int cur_len = length();
|
||||
return append_from(cur_len, s, s_end);
|
||||
}
|
||||
|
||||
int Str::appendfv(const char* fmt, va_list args)
|
||||
{
|
||||
int cur_len = length();
|
||||
return appendfv_from(cur_len, fmt, args);
|
||||
}
|
||||
|
||||
int Str::appendf(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
int len = appendfv(fmt, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
#endif // #define STR_IMPLEMENTATION
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
29
ExternalApps/RadioSet/main/Source/main.cpp
Normal file
29
ExternalApps/RadioSet/main/Source/main.cpp
Normal file
@ -0,0 +1,29 @@
|
||||
#include <tt_app.h>
|
||||
#include "RadioSet.h"
|
||||
|
||||
static void onShow(AppHandle appHandle, void* data, lv_obj_t* parent) {
|
||||
static_cast<RadioSet*>(data)->onShow(appHandle, parent);
|
||||
}
|
||||
|
||||
static void* createApp() {
|
||||
return new RadioSet();
|
||||
}
|
||||
|
||||
static void destroyApp(void* app) {
|
||||
delete static_cast<RadioSet*>(app);
|
||||
}
|
||||
|
||||
ExternalAppManifest manifest = {
|
||||
.createData = createApp,
|
||||
.destroyData = destroyApp,
|
||||
.onShow = onShow,
|
||||
};
|
||||
|
||||
extern "C" {
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
tt_app_register(&manifest);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
48
ExternalApps/RadioSet/main/Source/soft-fp/adddf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/adddf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a + b
|
||||
Copyright (C) 1997,1999, 2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __adddf3(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_SEMIRAW_D(A, a);
|
||||
FP_UNPACK_SEMIRAW_D(B, b);
|
||||
FP_ADD_D(R, A, B);
|
||||
FP_PACK_SEMIRAW_D(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
48
ExternalApps/RadioSet/main/Source/soft-fp/addsf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/addsf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a + b
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __addsf3(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_SEMIRAW_S(A, a);
|
||||
FP_UNPACK_SEMIRAW_S(B, b);
|
||||
FP_ADD_S(R, A, B);
|
||||
FP_PACK_SEMIRAW_S(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
53
ExternalApps/RadioSet/main/Source/soft-fp/clzsi2.c
Normal file
53
ExternalApps/RadioSet/main/Source/soft-fp/clzsi2.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* ===-- clzsi2.c - Implement __clzsi2 -------------------------------------===
|
||||
*
|
||||
* The LLVM Compiler Infrastructure
|
||||
*
|
||||
* This file is dual licensed under the MIT and the University of Illinois Open
|
||||
* Source Licenses. See LICENSE.TXT for details.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*
|
||||
* This file implements __clzsi2 for the compiler_rt library.
|
||||
*
|
||||
* ===----------------------------------------------------------------------===
|
||||
*/
|
||||
|
||||
//
|
||||
// Ported by wsyeo for 8267 compatibility.
|
||||
//
|
||||
|
||||
// Returns: the number of leading 0-bits
|
||||
|
||||
// Precondition: a != 0
|
||||
|
||||
unsigned int __clzsi2(unsigned int a)
|
||||
{
|
||||
unsigned int x = a;
|
||||
int t = ((x & 0xFFFF0000) == 0) << 4; // if (x is small) t = 16 else 0
|
||||
x >>= 16 - t; // x = [0 - 0xFFFF]
|
||||
unsigned int r = t; // r = [0, 16]
|
||||
// return r + clz(x)
|
||||
t = ((x & 0xFF00) == 0) << 3;
|
||||
x >>= 8 - t; // x = [0 - 0xFF]
|
||||
r += t; // r = [0, 8, 16, 24]
|
||||
// return r + clz(x)
|
||||
t = ((x & 0xF0) == 0) << 2;
|
||||
x >>= 4 - t; // x = [0 - 0xF]
|
||||
r += t; // r = [0, 4, 8, 12, 16, 20, 24, 28]
|
||||
// return r + clz(x)
|
||||
t = ((x & 0xC) == 0) << 1;
|
||||
x >>= 2 - t; // x = [0 - 3]
|
||||
r += t; // r = [0 - 30] and is even
|
||||
// return r + clz(x)
|
||||
// switch (x)
|
||||
// {
|
||||
// case 0:
|
||||
// return r + 2;
|
||||
// case 1:
|
||||
// return r + 1;
|
||||
// case 2:
|
||||
// case 3:
|
||||
// return r;
|
||||
// }
|
||||
return r + ((2 - x) & -((x & 2) == 0));
|
||||
}
|
||||
48
ExternalApps/RadioSet/main/Source/soft-fp/divdf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/divdf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a / b
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __divdf3(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_D(A, a);
|
||||
FP_UNPACK_D(B, b);
|
||||
FP_DIV_D(R, A, B);
|
||||
FP_PACK_D(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
48
ExternalApps/RadioSet/main/Source/soft-fp/divsf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/divsf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a / b
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __divsf3(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_S(A, a);
|
||||
FP_UNPACK_S(B, b);
|
||||
FP_DIV_S(R, A, B);
|
||||
FP_PACK_S(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
264
ExternalApps/RadioSet/main/Source/soft-fp/double.h
Normal file
264
ExternalApps/RadioSet/main/Source/soft-fp/double.h
Normal file
@ -0,0 +1,264 @@
|
||||
/* Software floating-point emulation.
|
||||
Definitions for IEEE Double Precision
|
||||
Copyright (C) 1997, 1998, 1999, 2006, 2007, 2008, 2009, 2012
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 32
|
||||
#error "Here's a nickel kid. Go buy yourself a real computer."
|
||||
#endif
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 64
|
||||
#define _FP_FRACTBITS_D (2 * _FP_W_TYPE_SIZE)
|
||||
#else
|
||||
#define _FP_FRACTBITS_D _FP_W_TYPE_SIZE
|
||||
#endif
|
||||
|
||||
#define _FP_FRACBITS_D 53
|
||||
#define _FP_FRACXBITS_D (_FP_FRACTBITS_D - _FP_FRACBITS_D)
|
||||
#define _FP_WFRACBITS_D (_FP_WORKBITS + _FP_FRACBITS_D)
|
||||
#define _FP_WFRACXBITS_D (_FP_FRACTBITS_D - _FP_WFRACBITS_D)
|
||||
#define _FP_EXPBITS_D 11
|
||||
#define _FP_EXPBIAS_D 1023
|
||||
#define _FP_EXPMAX_D 2047
|
||||
|
||||
#define _FP_QNANBIT_D \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_QNANBIT_SH_D \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_IMPLBIT_D \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_IMPLBIT_SH_D \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_D-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_OVERFLOW_D \
|
||||
((_FP_W_TYPE)1 << _FP_WFRACBITS_D % _FP_W_TYPE_SIZE)
|
||||
|
||||
typedef float DFtype __attribute__((mode(DF)));
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 64
|
||||
|
||||
union _FP_UNION_D
|
||||
{
|
||||
DFtype flt;
|
||||
struct _FP_STRUCT_LAYOUT {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sign : 1;
|
||||
unsigned exp : _FP_EXPBITS_D;
|
||||
unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
|
||||
unsigned frac0 : _FP_W_TYPE_SIZE;
|
||||
#else
|
||||
unsigned frac0 : _FP_W_TYPE_SIZE;
|
||||
unsigned frac1 : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0) - _FP_W_TYPE_SIZE;
|
||||
unsigned exp : _FP_EXPBITS_D;
|
||||
unsigned sign : 1;
|
||||
#endif
|
||||
} bits __attribute__((packed));
|
||||
};
|
||||
|
||||
#define FP_DECL_D(X) _FP_DECL(2,X)
|
||||
#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_2(D,X,val)
|
||||
#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_2_P(D,X,val)
|
||||
#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_2(D,val,X)
|
||||
#define FP_PACK_RAW_DP(val,X) \
|
||||
do { \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_2_P(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_D(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2(D,X,val); \
|
||||
_FP_UNPACK_CANONICAL(D,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_DP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2_P(D,X,val); \
|
||||
_FP_UNPACK_CANONICAL(D,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_D(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2(D,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(D,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_DP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2_P(D,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(D,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_D(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(D,2,X); \
|
||||
_FP_PACK_RAW_2(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_DP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(D,2,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_2_P(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_D(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(D,2,X); \
|
||||
_FP_PACK_RAW_2(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_DP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(D,2,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_2_P(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,2,X)
|
||||
#define FP_NEG_D(R,X) _FP_NEG(D,2,R,X)
|
||||
#define FP_ADD_D(R,X,Y) _FP_ADD(D,2,R,X,Y)
|
||||
#define FP_SUB_D(R,X,Y) _FP_SUB(D,2,R,X,Y)
|
||||
#define FP_MUL_D(R,X,Y) _FP_MUL(D,2,R,X,Y)
|
||||
#define FP_DIV_D(R,X,Y) _FP_DIV(D,2,R,X,Y)
|
||||
#define FP_SQRT_D(R,X) _FP_SQRT(D,2,R,X)
|
||||
#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
|
||||
|
||||
#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,2,r,X,Y,un)
|
||||
#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,2,r,X,Y)
|
||||
#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,2,r,X,Y)
|
||||
|
||||
#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,2,r,X,rsz,rsg)
|
||||
#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,2,X,r,rs,rt)
|
||||
|
||||
#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_2(X)
|
||||
#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_2(X)
|
||||
|
||||
#else
|
||||
|
||||
union _FP_UNION_D
|
||||
{
|
||||
DFtype flt;
|
||||
struct _FP_STRUCT_LAYOUT {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sign : 1;
|
||||
unsigned exp : _FP_EXPBITS_D;
|
||||
_FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
|
||||
#else
|
||||
_FP_W_TYPE frac : _FP_FRACBITS_D - (_FP_IMPLBIT_D != 0);
|
||||
unsigned exp : _FP_EXPBITS_D;
|
||||
unsigned sign : 1;
|
||||
#endif
|
||||
} bits __attribute__((packed));
|
||||
};
|
||||
|
||||
#define FP_DECL_D(X) _FP_DECL(1,X)
|
||||
#define FP_UNPACK_RAW_D(X,val) _FP_UNPACK_RAW_1(D,X,val)
|
||||
#define FP_UNPACK_RAW_DP(X,val) _FP_UNPACK_RAW_1_P(D,X,val)
|
||||
#define FP_PACK_RAW_D(val,X) _FP_PACK_RAW_1(D,val,X)
|
||||
#define FP_PACK_RAW_DP(val,X) \
|
||||
do { \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_1_P(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_D(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1(D,X,val); \
|
||||
_FP_UNPACK_CANONICAL(D,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_DP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1_P(D,X,val); \
|
||||
_FP_UNPACK_CANONICAL(D,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_D(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1(D,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(D,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_DP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1_P(D,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(D,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_D(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(D,1,X); \
|
||||
_FP_PACK_RAW_1(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_DP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(D,1,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_1_P(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_D(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(D,1,X); \
|
||||
_FP_PACK_RAW_1(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_DP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(D,1,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_1_P(D,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_ISSIGNAN_D(X) _FP_ISSIGNAN(D,1,X)
|
||||
#define FP_NEG_D(R,X) _FP_NEG(D,1,R,X)
|
||||
#define FP_ADD_D(R,X,Y) _FP_ADD(D,1,R,X,Y)
|
||||
#define FP_SUB_D(R,X,Y) _FP_SUB(D,1,R,X,Y)
|
||||
#define FP_MUL_D(R,X,Y) _FP_MUL(D,1,R,X,Y)
|
||||
#define FP_DIV_D(R,X,Y) _FP_DIV(D,1,R,X,Y)
|
||||
#define FP_SQRT_D(R,X) _FP_SQRT(D,1,R,X)
|
||||
#define _FP_SQRT_MEAT_D(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
|
||||
|
||||
/* The implementation of _FP_MUL_D and _FP_DIV_D should be chosen by
|
||||
the target machine. */
|
||||
|
||||
#define FP_CMP_D(r,X,Y,un) _FP_CMP(D,1,r,X,Y,un)
|
||||
#define FP_CMP_EQ_D(r,X,Y) _FP_CMP_EQ(D,1,r,X,Y)
|
||||
#define FP_CMP_UNORD_D(r,X,Y) _FP_CMP_UNORD(D,1,r,X,Y)
|
||||
|
||||
#define FP_TO_INT_D(r,X,rsz,rsg) _FP_TO_INT(D,1,r,X,rsz,rsg)
|
||||
#define FP_FROM_INT_D(X,r,rs,rt) _FP_FROM_INT(D,1,X,r,rs,rt)
|
||||
|
||||
#define _FP_FRAC_HIGH_D(X) _FP_FRAC_HIGH_1(X)
|
||||
#define _FP_FRAC_HIGH_RAW_D(X) _FP_FRAC_HIGH_1(X)
|
||||
|
||||
#endif /* W_TYPE_SIZE < 64 */
|
||||
50
ExternalApps/RadioSet/main/Source/soft-fp/eqdf2.c
Normal file
50
ExternalApps/RadioSet/main/Source/soft-fp/eqdf2.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 0 iff a == b, 1 otherwise
|
||||
Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
CMPtype __eqdf2(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_UNPACK_RAW_D(B, b);
|
||||
FP_CMP_EQ_D(r, A, B);
|
||||
if (r && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
|
||||
FP_SET_EXCEPTION(FP_EX_INVALID);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
strong_alias(__eqdf2, __nedf2);
|
||||
50
ExternalApps/RadioSet/main/Source/soft-fp/eqsf2.c
Normal file
50
ExternalApps/RadioSet/main/Source/soft-fp/eqsf2.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 0 iff a == b, 1 otherwise
|
||||
Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
CMPtype __eqsf2(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_UNPACK_RAW_S(B, b);
|
||||
FP_CMP_EQ_S(r, A, B);
|
||||
if (r && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
|
||||
FP_SET_EXCEPTION(FP_EX_INVALID);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
strong_alias(__eqsf2, __nesf2);
|
||||
430
ExternalApps/RadioSet/main/Source/soft-fp/extended.h
Normal file
430
ExternalApps/RadioSet/main/Source/soft-fp/extended.h
Normal file
@ -0,0 +1,430 @@
|
||||
/* Software floating-point emulation.
|
||||
Definitions for IEEE Extended Precision.
|
||||
Copyright (C) 1999,2006,2007,2012 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 32
|
||||
#error "Here's a nickel, kid. Go buy yourself a real computer."
|
||||
#endif
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 64
|
||||
#define _FP_FRACTBITS_E (4*_FP_W_TYPE_SIZE)
|
||||
#else
|
||||
#define _FP_FRACTBITS_E (2*_FP_W_TYPE_SIZE)
|
||||
#endif
|
||||
|
||||
#define _FP_FRACBITS_E 64
|
||||
#define _FP_FRACXBITS_E (_FP_FRACTBITS_E - _FP_FRACBITS_E)
|
||||
#define _FP_WFRACBITS_E (_FP_WORKBITS + _FP_FRACBITS_E)
|
||||
#define _FP_WFRACXBITS_E (_FP_FRACTBITS_E - _FP_WFRACBITS_E)
|
||||
#define _FP_EXPBITS_E 15
|
||||
#define _FP_EXPBIAS_E 16383
|
||||
#define _FP_EXPMAX_E 32767
|
||||
|
||||
#define _FP_QNANBIT_E \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_QNANBIT_SH_E \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_E-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_IMPLBIT_E \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_IMPLBIT_SH_E \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_E-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_OVERFLOW_E \
|
||||
((_FP_W_TYPE)1 << (_FP_WFRACBITS_E % _FP_W_TYPE_SIZE))
|
||||
|
||||
typedef float XFtype __attribute__((mode(XF)));
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 64
|
||||
|
||||
union _FP_UNION_E
|
||||
{
|
||||
XFtype flt;
|
||||
struct _FP_STRUCT_LAYOUT
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned long pad1 : _FP_W_TYPE_SIZE;
|
||||
unsigned long pad2 : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
|
||||
unsigned long sign : 1;
|
||||
unsigned long exp : _FP_EXPBITS_E;
|
||||
unsigned long frac1 : _FP_W_TYPE_SIZE;
|
||||
unsigned long frac0 : _FP_W_TYPE_SIZE;
|
||||
#else
|
||||
unsigned long frac0 : _FP_W_TYPE_SIZE;
|
||||
unsigned long frac1 : _FP_W_TYPE_SIZE;
|
||||
unsigned exp : _FP_EXPBITS_E;
|
||||
unsigned sign : 1;
|
||||
#endif /* not bigendian */
|
||||
} bits __attribute__((packed));
|
||||
};
|
||||
|
||||
|
||||
#define FP_DECL_E(X) _FP_DECL(4,X)
|
||||
|
||||
#define FP_UNPACK_RAW_E(X, val) \
|
||||
do { \
|
||||
union _FP_UNION_E _flo; _flo.flt = (val); \
|
||||
\
|
||||
X##_f[2] = 0; X##_f[3] = 0; \
|
||||
X##_f[0] = _flo.bits.frac0; \
|
||||
X##_f[1] = _flo.bits.frac1; \
|
||||
X##_e = _flo.bits.exp; \
|
||||
X##_s = _flo.bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_RAW_EP(X, val) \
|
||||
do { \
|
||||
union _FP_UNION_E *_flo = \
|
||||
(union _FP_UNION_E *)(val); \
|
||||
\
|
||||
X##_f[2] = 0; X##_f[3] = 0; \
|
||||
X##_f[0] = _flo->bits.frac0; \
|
||||
X##_f[1] = _flo->bits.frac1; \
|
||||
X##_e = _flo->bits.exp; \
|
||||
X##_s = _flo->bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_RAW_E(val, X) \
|
||||
do { \
|
||||
union _FP_UNION_E _flo; \
|
||||
\
|
||||
if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
|
||||
else X##_f[1] &= ~(_FP_IMPLBIT_E); \
|
||||
_flo.bits.frac0 = X##_f[0]; \
|
||||
_flo.bits.frac1 = X##_f[1]; \
|
||||
_flo.bits.exp = X##_e; \
|
||||
_flo.bits.sign = X##_s; \
|
||||
\
|
||||
(val) = _flo.flt; \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_RAW_EP(val, X) \
|
||||
do { \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
{ \
|
||||
union _FP_UNION_E *_flo = \
|
||||
(union _FP_UNION_E *)(val); \
|
||||
\
|
||||
if (X##_e) X##_f[1] |= _FP_IMPLBIT_E; \
|
||||
else X##_f[1] &= ~(_FP_IMPLBIT_E); \
|
||||
_flo->bits.frac0 = X##_f[0]; \
|
||||
_flo->bits.frac1 = X##_f[1]; \
|
||||
_flo->bits.exp = X##_e; \
|
||||
_flo->bits.sign = X##_s; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_E(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_E(X,val); \
|
||||
_FP_UNPACK_CANONICAL(E,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_EP(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_EP(X,val); \
|
||||
_FP_UNPACK_CANONICAL(E,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_E(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_E(X,val); \
|
||||
_FP_UNPACK_SEMIRAW(E,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_EP(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_EP(X,val); \
|
||||
_FP_UNPACK_SEMIRAW(E,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_E(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(E,4,X); \
|
||||
FP_PACK_RAW_E(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_EP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(E,4,X); \
|
||||
FP_PACK_RAW_EP(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_E(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(E,4,X); \
|
||||
FP_PACK_RAW_E(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_EP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(E,4,X); \
|
||||
FP_PACK_RAW_EP(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,4,X)
|
||||
#define FP_NEG_E(R,X) _FP_NEG(E,4,R,X)
|
||||
#define FP_ADD_E(R,X,Y) _FP_ADD(E,4,R,X,Y)
|
||||
#define FP_SUB_E(R,X,Y) _FP_SUB(E,4,R,X,Y)
|
||||
#define FP_MUL_E(R,X,Y) _FP_MUL(E,4,R,X,Y)
|
||||
#define FP_DIV_E(R,X,Y) _FP_DIV(E,4,R,X,Y)
|
||||
#define FP_SQRT_E(R,X) _FP_SQRT(E,4,R,X)
|
||||
|
||||
/*
|
||||
* Square root algorithms:
|
||||
* We have just one right now, maybe Newton approximation
|
||||
* should be added for those machines where division is fast.
|
||||
* This has special _E version because standard _4 square
|
||||
* root would not work (it has to start normally with the
|
||||
* second word and not the first), but as we have to do it
|
||||
* anyway, we optimize it by doing most of the calculations
|
||||
* in two UWtype registers instead of four.
|
||||
*/
|
||||
|
||||
#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
|
||||
do { \
|
||||
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
|
||||
_FP_FRAC_SRL_4(X, (_FP_WORKBITS)); \
|
||||
while (q) \
|
||||
{ \
|
||||
T##_f[1] = S##_f[1] + q; \
|
||||
if (T##_f[1] <= X##_f[1]) \
|
||||
{ \
|
||||
S##_f[1] = T##_f[1] + q; \
|
||||
X##_f[1] -= T##_f[1]; \
|
||||
R##_f[1] += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_2(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
|
||||
while (q) \
|
||||
{ \
|
||||
T##_f[0] = S##_f[0] + q; \
|
||||
T##_f[1] = S##_f[1]; \
|
||||
if (T##_f[1] < X##_f[1] || \
|
||||
(T##_f[1] == X##_f[1] && \
|
||||
T##_f[0] <= X##_f[0])) \
|
||||
{ \
|
||||
S##_f[0] = T##_f[0] + q; \
|
||||
S##_f[1] += (T##_f[0] > S##_f[0]); \
|
||||
_FP_FRAC_DEC_2(X, T); \
|
||||
R##_f[0] += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_2(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
_FP_FRAC_SLL_4(R, (_FP_WORKBITS)); \
|
||||
if (X##_f[0] | X##_f[1]) \
|
||||
{ \
|
||||
if (S##_f[1] < X##_f[1] || \
|
||||
(S##_f[1] == X##_f[1] && \
|
||||
S##_f[0] < X##_f[0])) \
|
||||
R##_f[0] |= _FP_WORK_ROUND; \
|
||||
R##_f[0] |= _FP_WORK_STICKY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,4,r,X,Y,un)
|
||||
#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,4,r,X,Y)
|
||||
#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,4,r,X,Y)
|
||||
|
||||
#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,4,r,X,rsz,rsg)
|
||||
#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,4,X,r,rs,rt)
|
||||
|
||||
#define _FP_FRAC_HIGH_E(X) (X##_f[2])
|
||||
#define _FP_FRAC_HIGH_RAW_E(X) (X##_f[1])
|
||||
|
||||
#else /* not _FP_W_TYPE_SIZE < 64 */
|
||||
union _FP_UNION_E
|
||||
{
|
||||
XFtype flt;
|
||||
struct _FP_STRUCT_LAYOUT {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
_FP_W_TYPE pad : (_FP_W_TYPE_SIZE - 1 - _FP_EXPBITS_E);
|
||||
unsigned sign : 1;
|
||||
unsigned exp : _FP_EXPBITS_E;
|
||||
_FP_W_TYPE frac : _FP_W_TYPE_SIZE;
|
||||
#else
|
||||
_FP_W_TYPE frac : _FP_W_TYPE_SIZE;
|
||||
unsigned exp : _FP_EXPBITS_E;
|
||||
unsigned sign : 1;
|
||||
#endif
|
||||
} bits;
|
||||
};
|
||||
|
||||
#define FP_DECL_E(X) _FP_DECL(2,X)
|
||||
|
||||
#define FP_UNPACK_RAW_E(X, val) \
|
||||
do { \
|
||||
union _FP_UNION_E _flo; _flo.flt = (val); \
|
||||
\
|
||||
X##_f0 = _flo.bits.frac; \
|
||||
X##_f1 = 0; \
|
||||
X##_e = _flo.bits.exp; \
|
||||
X##_s = _flo.bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_RAW_EP(X, val) \
|
||||
do { \
|
||||
union _FP_UNION_E *_flo = \
|
||||
(union _FP_UNION_E *)(val); \
|
||||
\
|
||||
X##_f0 = _flo->bits.frac; \
|
||||
X##_f1 = 0; \
|
||||
X##_e = _flo->bits.exp; \
|
||||
X##_s = _flo->bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_RAW_E(val, X) \
|
||||
do { \
|
||||
union _FP_UNION_E _flo; \
|
||||
\
|
||||
if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
|
||||
else X##_f0 &= ~(_FP_IMPLBIT_E); \
|
||||
_flo.bits.frac = X##_f0; \
|
||||
_flo.bits.exp = X##_e; \
|
||||
_flo.bits.sign = X##_s; \
|
||||
\
|
||||
(val) = _flo.flt; \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_RAW_EP(fs, val, X) \
|
||||
do { \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
{ \
|
||||
union _FP_UNION_E *_flo = \
|
||||
(union _FP_UNION_E *)(val); \
|
||||
\
|
||||
if (X##_e) X##_f0 |= _FP_IMPLBIT_E; \
|
||||
else X##_f0 &= ~(_FP_IMPLBIT_E); \
|
||||
_flo->bits.frac = X##_f0; \
|
||||
_flo->bits.exp = X##_e; \
|
||||
_flo->bits.sign = X##_s; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define FP_UNPACK_E(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_E(X,val); \
|
||||
_FP_UNPACK_CANONICAL(E,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_EP(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_EP(X,val); \
|
||||
_FP_UNPACK_CANONICAL(E,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_E(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_E(X,val); \
|
||||
_FP_UNPACK_SEMIRAW(E,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_EP(X,val) \
|
||||
do { \
|
||||
FP_UNPACK_RAW_EP(X,val); \
|
||||
_FP_UNPACK_SEMIRAW(E,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_E(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(E,2,X); \
|
||||
FP_PACK_RAW_E(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_EP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(E,2,X); \
|
||||
FP_PACK_RAW_EP(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_E(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(E,2,X); \
|
||||
FP_PACK_RAW_E(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_EP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(E,2,X); \
|
||||
FP_PACK_RAW_EP(val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_ISSIGNAN_E(X) _FP_ISSIGNAN(E,2,X)
|
||||
#define FP_NEG_E(R,X) _FP_NEG(E,2,R,X)
|
||||
#define FP_ADD_E(R,X,Y) _FP_ADD(E,2,R,X,Y)
|
||||
#define FP_SUB_E(R,X,Y) _FP_SUB(E,2,R,X,Y)
|
||||
#define FP_MUL_E(R,X,Y) _FP_MUL(E,2,R,X,Y)
|
||||
#define FP_DIV_E(R,X,Y) _FP_DIV(E,2,R,X,Y)
|
||||
#define FP_SQRT_E(R,X) _FP_SQRT(E,2,R,X)
|
||||
|
||||
/*
|
||||
* Square root algorithms:
|
||||
* We have just one right now, maybe Newton approximation
|
||||
* should be added for those machines where division is fast.
|
||||
* We optimize it by doing most of the calculations
|
||||
* in one UWtype registers instead of two, although we don't
|
||||
* have to.
|
||||
*/
|
||||
#define _FP_SQRT_MEAT_E(R, S, T, X, q) \
|
||||
do { \
|
||||
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
|
||||
_FP_FRAC_SRL_2(X, (_FP_WORKBITS)); \
|
||||
while (q) \
|
||||
{ \
|
||||
T##_f0 = S##_f0 + q; \
|
||||
if (T##_f0 <= X##_f0) \
|
||||
{ \
|
||||
S##_f0 = T##_f0 + q; \
|
||||
X##_f0 -= T##_f0; \
|
||||
R##_f0 += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_1(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
_FP_FRAC_SLL_2(R, (_FP_WORKBITS)); \
|
||||
if (X##_f0) \
|
||||
{ \
|
||||
if (S##_f0 < X##_f0) \
|
||||
R##_f0 |= _FP_WORK_ROUND; \
|
||||
R##_f0 |= _FP_WORK_STICKY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FP_CMP_E(r,X,Y,un) _FP_CMP(E,2,r,X,Y,un)
|
||||
#define FP_CMP_EQ_E(r,X,Y) _FP_CMP_EQ(E,2,r,X,Y)
|
||||
#define FP_CMP_UNORD_E(r,X,Y) _FP_CMP_UNORD(E,2,r,X,Y)
|
||||
|
||||
#define FP_TO_INT_E(r,X,rsz,rsg) _FP_TO_INT(E,2,r,X,rsz,rsg)
|
||||
#define FP_FROM_INT_E(X,r,rs,rt) _FP_FROM_INT(E,2,X,r,rs,rt)
|
||||
|
||||
#define _FP_FRAC_HIGH_E(X) (X##_f1)
|
||||
#define _FP_FRAC_HIGH_RAW_E(X) (X##_f0)
|
||||
|
||||
#endif /* not _FP_W_TYPE_SIZE < 64 */
|
||||
53
ExternalApps/RadioSet/main/Source/soft-fp/extendsfdf2.c
Normal file
53
ExternalApps/RadioSet/main/Source/soft-fp/extendsfdf2.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a converted to IEEE double
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __extendsfdf2(SFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
|
||||
FP_EXTEND(D,S,2,1,R,A);
|
||||
#else
|
||||
FP_EXTEND(D,S,1,1,R,A);
|
||||
#endif
|
||||
FP_PACK_RAW_D(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixdfdi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixdfdi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 64bit signed integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DItype __fixdfdi(DFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
UDItype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_TO_INT_D(r, A, DI_BITS, 1);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixdfsi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixdfsi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 32bit signed integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
SItype __fixdfsi(DFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
USItype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_TO_INT_D(r, A, SI_BITS, 1);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixsfdi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixsfdi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 64bit signed integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
DItype __fixsfdi(SFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
UDItype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_TO_INT_S(r, A, DI_BITS, 1);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixsfsi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixsfsi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 32bit signed integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SItype __fixsfsi(SFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
USItype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_TO_INT_S(r, A, SI_BITS, 1);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixtfdi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixtfdi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 64bit signed integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "quad.h"
|
||||
|
||||
DItype __fixtfdi(TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q(A);
|
||||
UDItype r;
|
||||
|
||||
FP_UNPACK_RAW_Q(A, a);
|
||||
FP_TO_INT_Q(r, A, DI_BITS, 1);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixtfsi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixtfsi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 32bit signed integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "quad.h"
|
||||
|
||||
SItype __fixtfsi(TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q(A);
|
||||
USItype r;
|
||||
|
||||
FP_UNPACK_RAW_Q(A, a);
|
||||
FP_TO_INT_Q(r, A, SI_BITS, 1);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunsdfdi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunsdfdi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 64bit unsigned integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
UDItype __fixunsdfdi(DFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
UDItype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_TO_INT_D(r, A, DI_BITS, 0);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunsdfsi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunsdfsi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 32bit unsigned integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
USItype __fixunsdfsi(DFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
USItype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_TO_INT_D(r, A, SI_BITS, 0);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunssfdi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunssfdi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 64bit unsigned integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
UDItype __fixunssfdi(SFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
UDItype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_TO_INT_S(r, A, DI_BITS, 0);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunssfsi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunssfsi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 32bit unsigned integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
USItype __fixunssfsi(SFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
USItype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_TO_INT_S(r, A, SI_BITS, 0);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunstfdi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunstfdi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 64bit unsigned integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "quad.h"
|
||||
|
||||
UDItype __fixunstfdi(TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q(A);
|
||||
UDItype r;
|
||||
|
||||
FP_UNPACK_RAW_Q(A, a);
|
||||
FP_TO_INT_Q(r, A, DI_BITS, 0);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunstfsi.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/fixunstfsi.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a to 32bit unsigned integer
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "quad.h"
|
||||
|
||||
USItype __fixunstfsi(TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q(A);
|
||||
USItype r;
|
||||
|
||||
FP_UNPACK_RAW_Q(A, a);
|
||||
FP_TO_INT_Q(r, A, SI_BITS, 0);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatdidf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatdidf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 64bit signed integer to IEEE double
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __floatdidf(DItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
DFtype a;
|
||||
|
||||
FP_FROM_INT_D(A, i, DI_BITS, UDItype);
|
||||
FP_PACK_RAW_D(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatdisf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatdisf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 64bit signed integer to IEEE single
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __floatdisf(DItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
SFtype a;
|
||||
|
||||
FP_FROM_INT_S(A, i, DI_BITS, UDItype);
|
||||
FP_PACK_RAW_S(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatsidf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatsidf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 32bit signed integer to IEEE double
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __floatsidf(SItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
DFtype a;
|
||||
|
||||
FP_FROM_INT_D(A, i, SI_BITS, USItype);
|
||||
FP_PACK_RAW_D(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatsisf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatsisf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 32bit signed integer to IEEE single
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __floatsisf(SItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
SFtype a;
|
||||
|
||||
FP_FROM_INT_S(A, i, SI_BITS, USItype);
|
||||
FP_PACK_RAW_S(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatundidf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatundidf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 64bit unsigned integer to IEEE double
|
||||
Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __floatundidf(UDItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
DFtype a;
|
||||
|
||||
FP_FROM_INT_D(A, i, DI_BITS, UDItype);
|
||||
FP_PACK_RAW_D(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatundisf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatundisf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 64bit unsigned integer to IEEE single
|
||||
Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __floatundisf(UDItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
SFtype a;
|
||||
|
||||
FP_FROM_INT_S(A, i, DI_BITS, UDItype);
|
||||
FP_PACK_RAW_S(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatunsidf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatunsidf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 32bit unsigned integer to IEEE double
|
||||
Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __floatunsidf(USItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
DFtype a;
|
||||
|
||||
FP_FROM_INT_D(A, i, SI_BITS, USItype);
|
||||
FP_PACK_RAW_D(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
45
ExternalApps/RadioSet/main/Source/soft-fp/floatunsisf.c
Normal file
45
ExternalApps/RadioSet/main/Source/soft-fp/floatunsisf.c
Normal file
@ -0,0 +1,45 @@
|
||||
/* Software floating-point emulation.
|
||||
Convert a 32bit unsigned integer to IEEE single
|
||||
Copyright (C) 1997, 1999, 2006, 2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __floatunsisf(USItype i)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A);
|
||||
SFtype a;
|
||||
|
||||
FP_FROM_INT_S(A, i, SI_BITS, USItype);
|
||||
FP_PACK_RAW_S(a, A);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return a;
|
||||
}
|
||||
50
ExternalApps/RadioSet/main/Source/soft-fp/gedf2.c
Normal file
50
ExternalApps/RadioSet/main/Source/soft-fp/gedf2.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 0 iff a == b, 1 iff a > b, -2 iff a ? b, -1 iff a < b
|
||||
Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
CMPtype __gedf2(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_UNPACK_RAW_D(B, b);
|
||||
FP_CMP_D(r, A, B, -2);
|
||||
if (r == -2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
|
||||
FP_SET_EXCEPTION(FP_EX_INVALID);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
strong_alias(__gedf2, __gtdf2);
|
||||
50
ExternalApps/RadioSet/main/Source/soft-fp/gesf2.c
Normal file
50
ExternalApps/RadioSet/main/Source/soft-fp/gesf2.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 0 iff a == b, 1 iff a > b, -2 iff a ? b, -1 iff a < b
|
||||
Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
CMPtype __gesf2(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_UNPACK_RAW_S(B, b);
|
||||
FP_CMP_S(r, A, B, -2);
|
||||
if (r == -2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
|
||||
FP_SET_EXCEPTION(FP_EX_INVALID);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
strong_alias(__gesf2, __gtsf2);
|
||||
50
ExternalApps/RadioSet/main/Source/soft-fp/ledf2.c
Normal file
50
ExternalApps/RadioSet/main/Source/soft-fp/ledf2.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 0 iff a == b, 1 iff a > b, 2 iff a ? b, -1 iff a < b
|
||||
Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
CMPtype __ledf2(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_UNPACK_RAW_D(B, b);
|
||||
FP_CMP_D(r, A, B, 2);
|
||||
if (r == 2 && (FP_ISSIGNAN_D(A) || FP_ISSIGNAN_D(B)))
|
||||
FP_SET_EXCEPTION(FP_EX_INVALID);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
strong_alias(__ledf2, __ltdf2);
|
||||
50
ExternalApps/RadioSet/main/Source/soft-fp/lesf2.c
Normal file
50
ExternalApps/RadioSet/main/Source/soft-fp/lesf2.c
Normal file
@ -0,0 +1,50 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 0 iff a == b, 1 iff a > b, 2 iff a ? b, -1 iff a < b
|
||||
Copyright (C) 1997,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
CMPtype __lesf2(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_UNPACK_RAW_S(B, b);
|
||||
FP_CMP_S(r, A, B, 2);
|
||||
if (r == 2 && (FP_ISSIGNAN_S(A) || FP_ISSIGNAN_S(B)))
|
||||
FP_SET_EXCEPTION(FP_EX_INVALID);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
strong_alias(__lesf2, __ltsf2);
|
||||
1328
ExternalApps/RadioSet/main/Source/soft-fp/longlong.h
Normal file
1328
ExternalApps/RadioSet/main/Source/soft-fp/longlong.h
Normal file
File diff suppressed because it is too large
Load Diff
48
ExternalApps/RadioSet/main/Source/soft-fp/muldf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/muldf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a * b
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __muldf3(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_D(A, a);
|
||||
FP_UNPACK_D(B, b);
|
||||
FP_MUL_D(R, A, B);
|
||||
FP_PACK_D(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
48
ExternalApps/RadioSet/main/Source/soft-fp/mulsf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/mulsf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a * b
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __mulsf3(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_S(A, a);
|
||||
FP_UNPACK_S(B, b);
|
||||
FP_MUL_S(R, A, B);
|
||||
FP_PACK_S(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
47
ExternalApps/RadioSet/main/Source/soft-fp/negdf2.c
Normal file
47
ExternalApps/RadioSet/main/Source/soft-fp/negdf2.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Software floating-point emulation.
|
||||
Return -a
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __negdf2(DFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_UNPACK_D(A, a);
|
||||
FP_NEG_D(R, A);
|
||||
FP_PACK_D(r, R);
|
||||
FP_CLEAR_EXCEPTIONS;
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
47
ExternalApps/RadioSet/main/Source/soft-fp/negsf2.c
Normal file
47
ExternalApps/RadioSet/main/Source/soft-fp/negsf2.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Software floating-point emulation.
|
||||
Return -a
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __negsf2(SFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_UNPACK_S(A, a);
|
||||
FP_NEG_S(R, A);
|
||||
FP_PACK_S(r, R);
|
||||
FP_CLEAR_EXCEPTIONS;
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
301
ExternalApps/RadioSet/main/Source/soft-fp/op-1.h
Normal file
301
ExternalApps/RadioSet/main/Source/soft-fp/op-1.h
Normal file
@ -0,0 +1,301 @@
|
||||
/* Software floating-point emulation.
|
||||
Basic one-word fraction declaration and manipulation.
|
||||
Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define _FP_FRAC_DECL_1(X) _FP_W_TYPE X##_f
|
||||
#define _FP_FRAC_COPY_1(D,S) (D##_f = S##_f)
|
||||
#define _FP_FRAC_SET_1(X,I) (X##_f = I)
|
||||
#define _FP_FRAC_HIGH_1(X) (X##_f)
|
||||
#define _FP_FRAC_LOW_1(X) (X##_f)
|
||||
#define _FP_FRAC_WORD_1(X,w) (X##_f)
|
||||
|
||||
#define _FP_FRAC_ADDI_1(X,I) (X##_f += I)
|
||||
#define _FP_FRAC_SLL_1(X,N) \
|
||||
do { \
|
||||
if (__builtin_constant_p(N) && (N) == 1) \
|
||||
X##_f += X##_f; \
|
||||
else \
|
||||
X##_f <<= (N); \
|
||||
} while (0)
|
||||
#define _FP_FRAC_SRL_1(X,N) (X##_f >>= N)
|
||||
|
||||
/* Right shift with sticky-lsb. */
|
||||
#define _FP_FRAC_SRST_1(X,S,N,sz) __FP_FRAC_SRST_1(X##_f, S, N, sz)
|
||||
#define _FP_FRAC_SRS_1(X,N,sz) __FP_FRAC_SRS_1(X##_f, N, sz)
|
||||
|
||||
#define __FP_FRAC_SRST_1(X,S,N,sz) \
|
||||
do { \
|
||||
S = (__builtin_constant_p(N) && (N) == 1 \
|
||||
? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0); \
|
||||
X = X >> (N); \
|
||||
} while (0)
|
||||
|
||||
#define __FP_FRAC_SRS_1(X,N,sz) \
|
||||
(X = (X >> (N) | (__builtin_constant_p(N) && (N) == 1 \
|
||||
? X & 1 : (X << (_FP_W_TYPE_SIZE - (N))) != 0)))
|
||||
|
||||
#define _FP_FRAC_ADD_1(R,X,Y) (R##_f = X##_f + Y##_f)
|
||||
#define _FP_FRAC_SUB_1(R,X,Y) (R##_f = X##_f - Y##_f)
|
||||
#define _FP_FRAC_DEC_1(X,Y) (X##_f -= Y##_f)
|
||||
#define _FP_FRAC_CLZ_1(z, X) __FP_CLZ(z, X##_f)
|
||||
|
||||
/* Predicates */
|
||||
#define _FP_FRAC_NEGP_1(X) ((_FP_WS_TYPE)X##_f < 0)
|
||||
#define _FP_FRAC_ZEROP_1(X) (X##_f == 0)
|
||||
#define _FP_FRAC_OVERP_1(fs,X) (X##_f & _FP_OVERFLOW_##fs)
|
||||
#define _FP_FRAC_CLEAR_OVERP_1(fs,X) (X##_f &= ~_FP_OVERFLOW_##fs)
|
||||
#define _FP_FRAC_EQ_1(X, Y) (X##_f == Y##_f)
|
||||
#define _FP_FRAC_GE_1(X, Y) (X##_f >= Y##_f)
|
||||
#define _FP_FRAC_GT_1(X, Y) (X##_f > Y##_f)
|
||||
|
||||
#define _FP_ZEROFRAC_1 0
|
||||
#define _FP_MINFRAC_1 1
|
||||
#define _FP_MAXFRAC_1 (~(_FP_WS_TYPE)0)
|
||||
|
||||
/*
|
||||
* Unpack the raw bits of a native fp value. Do not classify or
|
||||
* normalize the data.
|
||||
*/
|
||||
|
||||
#define _FP_UNPACK_RAW_1(fs, X, val) \
|
||||
do { \
|
||||
union _FP_UNION_##fs _flo; _flo.flt = (val); \
|
||||
\
|
||||
X##_f = _flo.bits.frac; \
|
||||
X##_e = _flo.bits.exp; \
|
||||
X##_s = _flo.bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_UNPACK_RAW_1_P(fs, X, val) \
|
||||
do { \
|
||||
union _FP_UNION_##fs *_flo = \
|
||||
(union _FP_UNION_##fs *)(val); \
|
||||
\
|
||||
X##_f = _flo->bits.frac; \
|
||||
X##_e = _flo->bits.exp; \
|
||||
X##_s = _flo->bits.sign; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Repack the raw bits of a native fp value.
|
||||
*/
|
||||
|
||||
#define _FP_PACK_RAW_1(fs, val, X) \
|
||||
do { \
|
||||
union _FP_UNION_##fs _flo; \
|
||||
\
|
||||
_flo.bits.frac = X##_f; \
|
||||
_flo.bits.exp = X##_e; \
|
||||
_flo.bits.sign = X##_s; \
|
||||
\
|
||||
(val) = _flo.flt; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_PACK_RAW_1_P(fs, val, X) \
|
||||
do { \
|
||||
union _FP_UNION_##fs *_flo = \
|
||||
(union _FP_UNION_##fs *)(val); \
|
||||
\
|
||||
_flo->bits.frac = X##_f; \
|
||||
_flo->bits.exp = X##_e; \
|
||||
_flo->bits.sign = X##_s; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Multiplication algorithms:
|
||||
*/
|
||||
|
||||
/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
|
||||
multiplication immediately. */
|
||||
|
||||
#define _FP_MUL_MEAT_1_imm(wfracbits, R, X, Y) \
|
||||
do { \
|
||||
R##_f = X##_f * Y##_f; \
|
||||
/* Normalize since we know where the msb of the multiplicands \
|
||||
were (bit B), we know that the msb of the of the product is \
|
||||
at either 2B or 2B-1. */ \
|
||||
_FP_FRAC_SRS_1(R, wfracbits-1, 2*wfracbits); \
|
||||
} while (0)
|
||||
|
||||
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
|
||||
|
||||
#define _FP_MUL_MEAT_1_wide(wfracbits, R, X, Y, doit) \
|
||||
do { \
|
||||
_FP_W_TYPE _Z_f0, _Z_f1; \
|
||||
doit(_Z_f1, _Z_f0, X##_f, Y##_f); \
|
||||
/* Normalize since we know where the msb of the multiplicands \
|
||||
were (bit B), we know that the msb of the of the product is \
|
||||
at either 2B or 2B-1. */ \
|
||||
_FP_FRAC_SRS_2(_Z, wfracbits-1, 2*wfracbits); \
|
||||
R##_f = _Z_f0; \
|
||||
} while (0)
|
||||
|
||||
/* Finally, a simple widening multiply algorithm. What fun! */
|
||||
|
||||
#define _FP_MUL_MEAT_1_hard(wfracbits, R, X, Y) \
|
||||
do { \
|
||||
_FP_W_TYPE _xh, _xl, _yh, _yl, _z_f0, _z_f1, _a_f0, _a_f1; \
|
||||
\
|
||||
/* split the words in half */ \
|
||||
_xh = X##_f >> (_FP_W_TYPE_SIZE/2); \
|
||||
_xl = X##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
|
||||
_yh = Y##_f >> (_FP_W_TYPE_SIZE/2); \
|
||||
_yl = Y##_f & (((_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2)) - 1); \
|
||||
\
|
||||
/* multiply the pieces */ \
|
||||
_z_f0 = _xl * _yl; \
|
||||
_a_f0 = _xh * _yl; \
|
||||
_a_f1 = _xl * _yh; \
|
||||
_z_f1 = _xh * _yh; \
|
||||
\
|
||||
/* reassemble into two full words */ \
|
||||
if ((_a_f0 += _a_f1) < _a_f1) \
|
||||
_z_f1 += (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE/2); \
|
||||
_a_f1 = _a_f0 >> (_FP_W_TYPE_SIZE/2); \
|
||||
_a_f0 = _a_f0 << (_FP_W_TYPE_SIZE/2); \
|
||||
_FP_FRAC_ADD_2(_z, _z, _a); \
|
||||
\
|
||||
/* normalize */ \
|
||||
_FP_FRAC_SRS_2(_z, wfracbits - 1, 2*wfracbits); \
|
||||
R##_f = _z_f0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Division algorithms:
|
||||
*/
|
||||
|
||||
/* Basic. Assuming the host word size is >= 2*FRACBITS, we can do the
|
||||
division immediately. Give this macro either _FP_DIV_HELP_imm for
|
||||
C primitives or _FP_DIV_HELP_ldiv for the ISO function. Which you
|
||||
choose will depend on what the compiler does with divrem4. */
|
||||
|
||||
#define _FP_DIV_MEAT_1_imm(fs, R, X, Y, doit) \
|
||||
do { \
|
||||
_FP_W_TYPE _q, _r; \
|
||||
X##_f <<= (X##_f < Y##_f \
|
||||
? R##_e--, _FP_WFRACBITS_##fs \
|
||||
: _FP_WFRACBITS_##fs - 1); \
|
||||
doit(_q, _r, X##_f, Y##_f); \
|
||||
R##_f = _q | (_r != 0); \
|
||||
} while (0)
|
||||
|
||||
/* GCC's longlong.h defines a 2W / 1W => (1W,1W) primitive udiv_qrnnd
|
||||
that may be useful in this situation. This first is for a primitive
|
||||
that requires normalization, the second for one that does not. Look
|
||||
for UDIV_NEEDS_NORMALIZATION to tell which your machine needs. */
|
||||
|
||||
#define _FP_DIV_MEAT_1_udiv_norm(fs, R, X, Y) \
|
||||
do { \
|
||||
_FP_W_TYPE _nh, _nl, _q, _r, _y; \
|
||||
\
|
||||
/* Normalize Y -- i.e. make the most significant bit set. */ \
|
||||
_y = Y##_f << _FP_WFRACXBITS_##fs; \
|
||||
\
|
||||
/* Shift X op correspondingly high, that is, up one full word. */ \
|
||||
if (X##_f < Y##_f) \
|
||||
{ \
|
||||
R##_e--; \
|
||||
_nl = 0; \
|
||||
_nh = X##_f; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_nl = X##_f << (_FP_W_TYPE_SIZE - 1); \
|
||||
_nh = X##_f >> 1; \
|
||||
} \
|
||||
\
|
||||
udiv_qrnnd(_q, _r, _nh, _nl, _y); \
|
||||
R##_f = _q | (_r != 0); \
|
||||
} while (0)
|
||||
|
||||
#define _FP_DIV_MEAT_1_udiv(fs, R, X, Y) \
|
||||
do { \
|
||||
_FP_W_TYPE _nh, _nl, _q, _r; \
|
||||
if (X##_f < Y##_f) \
|
||||
{ \
|
||||
R##_e--; \
|
||||
_nl = X##_f << _FP_WFRACBITS_##fs; \
|
||||
_nh = X##_f >> _FP_WFRACXBITS_##fs; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_nl = X##_f << (_FP_WFRACBITS_##fs - 1); \
|
||||
_nh = X##_f >> (_FP_WFRACXBITS_##fs + 1); \
|
||||
} \
|
||||
udiv_qrnnd(_q, _r, _nh, _nl, Y##_f); \
|
||||
R##_f = _q | (_r != 0); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Square root algorithms:
|
||||
* We have just one right now, maybe Newton approximation
|
||||
* should be added for those machines where division is fast.
|
||||
*/
|
||||
|
||||
#define _FP_SQRT_MEAT_1(R, S, T, X, q) \
|
||||
do { \
|
||||
while (q != _FP_WORK_ROUND) \
|
||||
{ \
|
||||
T##_f = S##_f + q; \
|
||||
if (T##_f <= X##_f) \
|
||||
{ \
|
||||
S##_f = T##_f + q; \
|
||||
X##_f -= T##_f; \
|
||||
R##_f += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_1(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
if (X##_f) \
|
||||
{ \
|
||||
if (S##_f < X##_f) \
|
||||
R##_f |= _FP_WORK_ROUND; \
|
||||
R##_f |= _FP_WORK_STICKY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Assembly/disassembly for converting to/from integral types.
|
||||
* No shifting or overflow handled here.
|
||||
*/
|
||||
|
||||
#define _FP_FRAC_ASSEMBLE_1(r, X, rsize) (r = X##_f)
|
||||
#define _FP_FRAC_DISASSEMBLE_1(X, r, rsize) (X##_f = r)
|
||||
|
||||
|
||||
/*
|
||||
* Convert FP values between word sizes
|
||||
*/
|
||||
|
||||
#define _FP_FRAC_COPY_1_1(D, S) (D##_f = S##_f)
|
||||
616
ExternalApps/RadioSet/main/Source/soft-fp/op-2.h
Normal file
616
ExternalApps/RadioSet/main/Source/soft-fp/op-2.h
Normal file
@ -0,0 +1,616 @@
|
||||
/* Software floating-point emulation.
|
||||
Basic two-word fraction declaration and manipulation.
|
||||
Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define _FP_FRAC_DECL_2(X) _FP_W_TYPE X##_f0, X##_f1
|
||||
#define _FP_FRAC_COPY_2(D,S) (D##_f0 = S##_f0, D##_f1 = S##_f1)
|
||||
#define _FP_FRAC_SET_2(X,I) __FP_FRAC_SET_2(X, I)
|
||||
#define _FP_FRAC_HIGH_2(X) (X##_f1)
|
||||
#define _FP_FRAC_LOW_2(X) (X##_f0)
|
||||
#define _FP_FRAC_WORD_2(X,w) (X##_f##w)
|
||||
|
||||
#define _FP_FRAC_SLL_2(X,N) \
|
||||
(void)(((N) < _FP_W_TYPE_SIZE) \
|
||||
? ({ \
|
||||
if (__builtin_constant_p(N) && (N) == 1) \
|
||||
{ \
|
||||
X##_f1 = X##_f1 + X##_f1 + (((_FP_WS_TYPE)(X##_f0)) < 0); \
|
||||
X##_f0 += X##_f0; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
X##_f1 = X##_f1 << (N) | X##_f0 >> (_FP_W_TYPE_SIZE - (N)); \
|
||||
X##_f0 <<= (N); \
|
||||
} \
|
||||
0; \
|
||||
}) \
|
||||
: ({ \
|
||||
X##_f1 = X##_f0 << ((N) - _FP_W_TYPE_SIZE); \
|
||||
X##_f0 = 0; \
|
||||
}))
|
||||
|
||||
|
||||
#define _FP_FRAC_SRL_2(X,N) \
|
||||
(void)(((N) < _FP_W_TYPE_SIZE) \
|
||||
? ({ \
|
||||
X##_f0 = X##_f0 >> (N) | X##_f1 << (_FP_W_TYPE_SIZE - (N)); \
|
||||
X##_f1 >>= (N); \
|
||||
}) \
|
||||
: ({ \
|
||||
X##_f0 = X##_f1 >> ((N) - _FP_W_TYPE_SIZE); \
|
||||
X##_f1 = 0; \
|
||||
}))
|
||||
|
||||
/* Right shift with sticky-lsb. */
|
||||
#define _FP_FRAC_SRST_2(X,S, N,sz) \
|
||||
(void)(((N) < _FP_W_TYPE_SIZE) \
|
||||
? ({ \
|
||||
S = (__builtin_constant_p(N) && (N) == 1 \
|
||||
? X##_f0 & 1 \
|
||||
: (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0); \
|
||||
X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N)); \
|
||||
X##_f1 >>= (N); \
|
||||
}) \
|
||||
: ({ \
|
||||
S = ((((N) == _FP_W_TYPE_SIZE \
|
||||
? 0 \
|
||||
: (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
|
||||
| X##_f0) != 0); \
|
||||
X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE)); \
|
||||
X##_f1 = 0; \
|
||||
}))
|
||||
|
||||
#define _FP_FRAC_SRS_2(X,N,sz) \
|
||||
(void)(((N) < _FP_W_TYPE_SIZE) \
|
||||
? ({ \
|
||||
X##_f0 = (X##_f1 << (_FP_W_TYPE_SIZE - (N)) | X##_f0 >> (N) | \
|
||||
(__builtin_constant_p(N) && (N) == 1 \
|
||||
? X##_f0 & 1 \
|
||||
: (X##_f0 << (_FP_W_TYPE_SIZE - (N))) != 0)); \
|
||||
X##_f1 >>= (N); \
|
||||
}) \
|
||||
: ({ \
|
||||
X##_f0 = (X##_f1 >> ((N) - _FP_W_TYPE_SIZE) | \
|
||||
((((N) == _FP_W_TYPE_SIZE \
|
||||
? 0 \
|
||||
: (X##_f1 << (2*_FP_W_TYPE_SIZE - (N)))) \
|
||||
| X##_f0) != 0)); \
|
||||
X##_f1 = 0; \
|
||||
}))
|
||||
|
||||
#define _FP_FRAC_ADDI_2(X,I) \
|
||||
__FP_FRAC_ADDI_2(X##_f1, X##_f0, I)
|
||||
|
||||
#define _FP_FRAC_ADD_2(R,X,Y) \
|
||||
__FP_FRAC_ADD_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
|
||||
|
||||
#define _FP_FRAC_SUB_2(R,X,Y) \
|
||||
__FP_FRAC_SUB_2(R##_f1, R##_f0, X##_f1, X##_f0, Y##_f1, Y##_f0)
|
||||
|
||||
#define _FP_FRAC_DEC_2(X,Y) \
|
||||
__FP_FRAC_DEC_2(X##_f1, X##_f0, Y##_f1, Y##_f0)
|
||||
|
||||
#define _FP_FRAC_CLZ_2(R,X) \
|
||||
do { \
|
||||
if (X##_f1) \
|
||||
__FP_CLZ(R,X##_f1); \
|
||||
else \
|
||||
{ \
|
||||
__FP_CLZ(R,X##_f0); \
|
||||
R += _FP_W_TYPE_SIZE; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
/* Predicates */
|
||||
#define _FP_FRAC_NEGP_2(X) ((_FP_WS_TYPE)X##_f1 < 0)
|
||||
#define _FP_FRAC_ZEROP_2(X) ((X##_f1 | X##_f0) == 0)
|
||||
#define _FP_FRAC_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
|
||||
#define _FP_FRAC_CLEAR_OVERP_2(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
|
||||
#define _FP_FRAC_EQ_2(X, Y) (X##_f1 == Y##_f1 && X##_f0 == Y##_f0)
|
||||
#define _FP_FRAC_GT_2(X, Y) \
|
||||
(X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 > Y##_f0))
|
||||
#define _FP_FRAC_GE_2(X, Y) \
|
||||
(X##_f1 > Y##_f1 || (X##_f1 == Y##_f1 && X##_f0 >= Y##_f0))
|
||||
|
||||
#define _FP_ZEROFRAC_2 0, 0
|
||||
#define _FP_MINFRAC_2 0, 1
|
||||
#define _FP_MAXFRAC_2 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
|
||||
|
||||
/*
|
||||
* Internals
|
||||
*/
|
||||
|
||||
#define __FP_FRAC_SET_2(X,I1,I0) (X##_f0 = I0, X##_f1 = I1)
|
||||
|
||||
#define __FP_CLZ_2(R, xh, xl) \
|
||||
do { \
|
||||
if (xh) \
|
||||
__FP_CLZ(R,xh); \
|
||||
else \
|
||||
{ \
|
||||
__FP_CLZ(R,xl); \
|
||||
R += _FP_W_TYPE_SIZE; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
#if 0
|
||||
|
||||
#ifndef __FP_FRAC_ADDI_2
|
||||
#define __FP_FRAC_ADDI_2(xh, xl, i) \
|
||||
(xh += ((xl += i) < i))
|
||||
#endif
|
||||
#ifndef __FP_FRAC_ADD_2
|
||||
#define __FP_FRAC_ADD_2(rh, rl, xh, xl, yh, yl) \
|
||||
(rh = xh + yh + ((rl = xl + yl) < xl))
|
||||
#endif
|
||||
#ifndef __FP_FRAC_SUB_2
|
||||
#define __FP_FRAC_SUB_2(rh, rl, xh, xl, yh, yl) \
|
||||
(rh = xh - yh - ((rl = xl - yl) > xl))
|
||||
#endif
|
||||
#ifndef __FP_FRAC_DEC_2
|
||||
#define __FP_FRAC_DEC_2(xh, xl, yh, yl) \
|
||||
do { \
|
||||
UWtype _t = xl; \
|
||||
xh -= yh + ((xl -= yl) > _t); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#undef __FP_FRAC_ADDI_2
|
||||
#define __FP_FRAC_ADDI_2(xh, xl, i) add_ssaaaa(xh, xl, xh, xl, 0, i)
|
||||
#undef __FP_FRAC_ADD_2
|
||||
#define __FP_FRAC_ADD_2 add_ssaaaa
|
||||
#undef __FP_FRAC_SUB_2
|
||||
#define __FP_FRAC_SUB_2 sub_ddmmss
|
||||
#undef __FP_FRAC_DEC_2
|
||||
#define __FP_FRAC_DEC_2(xh, xl, yh, yl) sub_ddmmss(xh, xl, xh, xl, yh, yl)
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Unpack the raw bits of a native fp value. Do not classify or
|
||||
* normalize the data.
|
||||
*/
|
||||
|
||||
#define _FP_UNPACK_RAW_2(fs, X, val) \
|
||||
do { \
|
||||
union _FP_UNION_##fs _flo; _flo.flt = (val); \
|
||||
\
|
||||
X##_f0 = _flo.bits.frac0; \
|
||||
X##_f1 = _flo.bits.frac1; \
|
||||
X##_e = _flo.bits.exp; \
|
||||
X##_s = _flo.bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_UNPACK_RAW_2_P(fs, X, val) \
|
||||
do { \
|
||||
union _FP_UNION_##fs *_flo = \
|
||||
(union _FP_UNION_##fs *)(val); \
|
||||
\
|
||||
X##_f0 = _flo->bits.frac0; \
|
||||
X##_f1 = _flo->bits.frac1; \
|
||||
X##_e = _flo->bits.exp; \
|
||||
X##_s = _flo->bits.sign; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Repack the raw bits of a native fp value.
|
||||
*/
|
||||
|
||||
#define _FP_PACK_RAW_2(fs, val, X) \
|
||||
do { \
|
||||
union _FP_UNION_##fs _flo; \
|
||||
\
|
||||
_flo.bits.frac0 = X##_f0; \
|
||||
_flo.bits.frac1 = X##_f1; \
|
||||
_flo.bits.exp = X##_e; \
|
||||
_flo.bits.sign = X##_s; \
|
||||
\
|
||||
(val) = _flo.flt; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_PACK_RAW_2_P(fs, val, X) \
|
||||
do { \
|
||||
union _FP_UNION_##fs *_flo = \
|
||||
(union _FP_UNION_##fs *)(val); \
|
||||
\
|
||||
_flo->bits.frac0 = X##_f0; \
|
||||
_flo->bits.frac1 = X##_f1; \
|
||||
_flo->bits.exp = X##_e; \
|
||||
_flo->bits.sign = X##_s; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Multiplication algorithms:
|
||||
*/
|
||||
|
||||
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
|
||||
|
||||
#define _FP_MUL_MEAT_2_wide(wfracbits, R, X, Y, doit) \
|
||||
do { \
|
||||
_FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
|
||||
\
|
||||
doit(_FP_FRAC_WORD_4(_z,1), _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
|
||||
doit(_b_f1, _b_f0, X##_f0, Y##_f1); \
|
||||
doit(_c_f1, _c_f0, X##_f1, Y##_f0); \
|
||||
doit(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), X##_f1, Y##_f1); \
|
||||
\
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_FP_FRAC_WORD_4(_z,1), 0, _b_f1, _b_f0, \
|
||||
_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_FP_FRAC_WORD_4(_z,1)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0, \
|
||||
_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_FP_FRAC_WORD_4(_z,1)); \
|
||||
\
|
||||
/* Normalize since we know where the msb of the multiplicands \
|
||||
were (bit B), we know that the msb of the of the product is \
|
||||
at either 2B or 2B-1. */ \
|
||||
_FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
|
||||
R##_f0 = _FP_FRAC_WORD_4(_z,0); \
|
||||
R##_f1 = _FP_FRAC_WORD_4(_z,1); \
|
||||
} while (0)
|
||||
|
||||
/* Given a 1W * 1W => 2W primitive, do the extended multiplication.
|
||||
Do only 3 multiplications instead of four. This one is for machines
|
||||
where multiplication is much more expensive than subtraction. */
|
||||
|
||||
#define _FP_MUL_MEAT_2_wide_3mul(wfracbits, R, X, Y, doit) \
|
||||
do { \
|
||||
_FP_FRAC_DECL_4(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
|
||||
_FP_W_TYPE _d; \
|
||||
int _c1, _c2; \
|
||||
\
|
||||
_b_f0 = X##_f0 + X##_f1; \
|
||||
_c1 = _b_f0 < X##_f0; \
|
||||
_b_f1 = Y##_f0 + Y##_f1; \
|
||||
_c2 = _b_f1 < Y##_f0; \
|
||||
doit(_d, _FP_FRAC_WORD_4(_z,0), X##_f0, Y##_f0); \
|
||||
doit(_FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1), _b_f0, _b_f1); \
|
||||
doit(_c_f1, _c_f0, X##_f1, Y##_f1); \
|
||||
\
|
||||
_b_f0 &= -_c2; \
|
||||
_b_f1 &= -_c1; \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_FP_FRAC_WORD_4(_z,1), (_c1 & _c2), 0, _d, \
|
||||
0, _FP_FRAC_WORD_4(_z,2), _FP_FRAC_WORD_4(_z,1)); \
|
||||
__FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_b_f0); \
|
||||
__FP_FRAC_ADDI_2(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_b_f1); \
|
||||
__FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_FP_FRAC_WORD_4(_z,1), \
|
||||
0, _d, _FP_FRAC_WORD_4(_z,0)); \
|
||||
__FP_FRAC_DEC_3(_FP_FRAC_WORD_4(_z,3),_FP_FRAC_WORD_4(_z,2), \
|
||||
_FP_FRAC_WORD_4(_z,1), 0, _c_f1, _c_f0); \
|
||||
__FP_FRAC_ADD_2(_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2), \
|
||||
_c_f1, _c_f0, \
|
||||
_FP_FRAC_WORD_4(_z,3), _FP_FRAC_WORD_4(_z,2)); \
|
||||
\
|
||||
/* Normalize since we know where the msb of the multiplicands \
|
||||
were (bit B), we know that the msb of the of the product is \
|
||||
at either 2B or 2B-1. */ \
|
||||
_FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
|
||||
R##_f0 = _FP_FRAC_WORD_4(_z,0); \
|
||||
R##_f1 = _FP_FRAC_WORD_4(_z,1); \
|
||||
} while (0)
|
||||
|
||||
#define _FP_MUL_MEAT_2_gmp(wfracbits, R, X, Y) \
|
||||
do { \
|
||||
_FP_FRAC_DECL_4(_z); \
|
||||
_FP_W_TYPE _x[2], _y[2]; \
|
||||
_x[0] = X##_f0; _x[1] = X##_f1; \
|
||||
_y[0] = Y##_f0; _y[1] = Y##_f1; \
|
||||
\
|
||||
mpn_mul_n(_z_f, _x, _y, 2); \
|
||||
\
|
||||
/* Normalize since we know where the msb of the multiplicands \
|
||||
were (bit B), we know that the msb of the of the product is \
|
||||
at either 2B or 2B-1. */ \
|
||||
_FP_FRAC_SRS_4(_z, wfracbits-1, 2*wfracbits); \
|
||||
R##_f0 = _z_f[0]; \
|
||||
R##_f1 = _z_f[1]; \
|
||||
} while (0)
|
||||
|
||||
/* Do at most 120x120=240 bits multiplication using double floating
|
||||
point multiplication. This is useful if floating point
|
||||
multiplication has much bigger throughput than integer multiply.
|
||||
It is supposed to work for _FP_W_TYPE_SIZE 64 and wfracbits
|
||||
between 106 and 120 only.
|
||||
Caller guarantees that X and Y has (1LLL << (wfracbits - 1)) set.
|
||||
SETFETZ is a macro which will disable all FPU exceptions and set rounding
|
||||
towards zero, RESETFE should optionally reset it back. */
|
||||
|
||||
#define _FP_MUL_MEAT_2_120_240_double(wfracbits, R, X, Y, setfetz, resetfe) \
|
||||
do { \
|
||||
static const double _const[] = { \
|
||||
/* 2^-24 */ 5.9604644775390625e-08, \
|
||||
/* 2^-48 */ 3.5527136788005009e-15, \
|
||||
/* 2^-72 */ 2.1175823681357508e-22, \
|
||||
/* 2^-96 */ 1.2621774483536189e-29, \
|
||||
/* 2^28 */ 2.68435456e+08, \
|
||||
/* 2^4 */ 1.600000e+01, \
|
||||
/* 2^-20 */ 9.5367431640625e-07, \
|
||||
/* 2^-44 */ 5.6843418860808015e-14, \
|
||||
/* 2^-68 */ 3.3881317890172014e-21, \
|
||||
/* 2^-92 */ 2.0194839173657902e-28, \
|
||||
/* 2^-116 */ 1.2037062152420224e-35}; \
|
||||
double _a240, _b240, _c240, _d240, _e240, _f240, \
|
||||
_g240, _h240, _i240, _j240, _k240; \
|
||||
union { double d; UDItype i; } _l240, _m240, _n240, _o240, \
|
||||
_p240, _q240, _r240, _s240; \
|
||||
UDItype _t240, _u240, _v240, _w240, _x240, _y240 = 0; \
|
||||
\
|
||||
if (wfracbits < 106 || wfracbits > 120) \
|
||||
abort(); \
|
||||
\
|
||||
setfetz; \
|
||||
\
|
||||
_e240 = (double)(long)(X##_f0 & 0xffffff); \
|
||||
_j240 = (double)(long)(Y##_f0 & 0xffffff); \
|
||||
_d240 = (double)(long)((X##_f0 >> 24) & 0xffffff); \
|
||||
_i240 = (double)(long)((Y##_f0 >> 24) & 0xffffff); \
|
||||
_c240 = (double)(long)(((X##_f1 << 16) & 0xffffff) | (X##_f0 >> 48)); \
|
||||
_h240 = (double)(long)(((Y##_f1 << 16) & 0xffffff) | (Y##_f0 >> 48)); \
|
||||
_b240 = (double)(long)((X##_f1 >> 8) & 0xffffff); \
|
||||
_g240 = (double)(long)((Y##_f1 >> 8) & 0xffffff); \
|
||||
_a240 = (double)(long)(X##_f1 >> 32); \
|
||||
_f240 = (double)(long)(Y##_f1 >> 32); \
|
||||
_e240 *= _const[3]; \
|
||||
_j240 *= _const[3]; \
|
||||
_d240 *= _const[2]; \
|
||||
_i240 *= _const[2]; \
|
||||
_c240 *= _const[1]; \
|
||||
_h240 *= _const[1]; \
|
||||
_b240 *= _const[0]; \
|
||||
_g240 *= _const[0]; \
|
||||
_s240.d = _e240*_j240;\
|
||||
_r240.d = _d240*_j240 + _e240*_i240;\
|
||||
_q240.d = _c240*_j240 + _d240*_i240 + _e240*_h240;\
|
||||
_p240.d = _b240*_j240 + _c240*_i240 + _d240*_h240 + _e240*_g240;\
|
||||
_o240.d = _a240*_j240 + _b240*_i240 + _c240*_h240 + _d240*_g240 + _e240*_f240;\
|
||||
_n240.d = _a240*_i240 + _b240*_h240 + _c240*_g240 + _d240*_f240; \
|
||||
_m240.d = _a240*_h240 + _b240*_g240 + _c240*_f240; \
|
||||
_l240.d = _a240*_g240 + _b240*_f240; \
|
||||
_k240 = _a240*_f240; \
|
||||
_r240.d += _s240.d; \
|
||||
_q240.d += _r240.d; \
|
||||
_p240.d += _q240.d; \
|
||||
_o240.d += _p240.d; \
|
||||
_n240.d += _o240.d; \
|
||||
_m240.d += _n240.d; \
|
||||
_l240.d += _m240.d; \
|
||||
_k240 += _l240.d; \
|
||||
_s240.d -= ((_const[10]+_s240.d)-_const[10]); \
|
||||
_r240.d -= ((_const[9]+_r240.d)-_const[9]); \
|
||||
_q240.d -= ((_const[8]+_q240.d)-_const[8]); \
|
||||
_p240.d -= ((_const[7]+_p240.d)-_const[7]); \
|
||||
_o240.d += _const[7]; \
|
||||
_n240.d += _const[6]; \
|
||||
_m240.d += _const[5]; \
|
||||
_l240.d += _const[4]; \
|
||||
if (_s240.d != 0.0) _y240 = 1; \
|
||||
if (_r240.d != 0.0) _y240 = 1; \
|
||||
if (_q240.d != 0.0) _y240 = 1; \
|
||||
if (_p240.d != 0.0) _y240 = 1; \
|
||||
_t240 = (DItype)_k240; \
|
||||
_u240 = _l240.i; \
|
||||
_v240 = _m240.i; \
|
||||
_w240 = _n240.i; \
|
||||
_x240 = _o240.i; \
|
||||
R##_f1 = (_t240 << (128 - (wfracbits - 1))) \
|
||||
| ((_u240 & 0xffffff) >> ((wfracbits - 1) - 104)); \
|
||||
R##_f0 = ((_u240 & 0xffffff) << (168 - (wfracbits - 1))) \
|
||||
| ((_v240 & 0xffffff) << (144 - (wfracbits - 1))) \
|
||||
| ((_w240 & 0xffffff) << (120 - (wfracbits - 1))) \
|
||||
| ((_x240 & 0xffffff) >> ((wfracbits - 1) - 96)) \
|
||||
| _y240; \
|
||||
resetfe; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Division algorithms:
|
||||
*/
|
||||
|
||||
#define _FP_DIV_MEAT_2_udiv(fs, R, X, Y) \
|
||||
do { \
|
||||
_FP_W_TYPE _n_f2, _n_f1, _n_f0, _r_f1, _r_f0, _m_f1, _m_f0; \
|
||||
if (_FP_FRAC_GT_2(X, Y)) \
|
||||
{ \
|
||||
_n_f2 = X##_f1 >> 1; \
|
||||
_n_f1 = X##_f1 << (_FP_W_TYPE_SIZE - 1) | X##_f0 >> 1; \
|
||||
_n_f0 = X##_f0 << (_FP_W_TYPE_SIZE - 1); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
R##_e--; \
|
||||
_n_f2 = X##_f1; \
|
||||
_n_f1 = X##_f0; \
|
||||
_n_f0 = 0; \
|
||||
} \
|
||||
\
|
||||
/* Normalize, i.e. make the most significant bit of the \
|
||||
denominator set. */ \
|
||||
_FP_FRAC_SLL_2(Y, _FP_WFRACXBITS_##fs); \
|
||||
\
|
||||
udiv_qrnnd(R##_f1, _r_f1, _n_f2, _n_f1, Y##_f1); \
|
||||
umul_ppmm(_m_f1, _m_f0, R##_f1, Y##_f0); \
|
||||
_r_f0 = _n_f0; \
|
||||
if (_FP_FRAC_GT_2(_m, _r)) \
|
||||
{ \
|
||||
R##_f1--; \
|
||||
_FP_FRAC_ADD_2(_r, Y, _r); \
|
||||
if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
|
||||
{ \
|
||||
R##_f1--; \
|
||||
_FP_FRAC_ADD_2(_r, Y, _r); \
|
||||
} \
|
||||
} \
|
||||
_FP_FRAC_DEC_2(_r, _m); \
|
||||
\
|
||||
if (_r_f1 == Y##_f1) \
|
||||
{ \
|
||||
/* This is a special case, not an optimization \
|
||||
(_r/Y##_f1 would not fit into UWtype). \
|
||||
As _r is guaranteed to be < Y, R##_f0 can be either \
|
||||
(UWtype)-1 or (UWtype)-2. But as we know what kind \
|
||||
of bits it is (sticky, guard, round), we don't care. \
|
||||
We also don't care what the reminder is, because the \
|
||||
guard bit will be set anyway. -jj */ \
|
||||
R##_f0 = -1; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
udiv_qrnnd(R##_f0, _r_f1, _r_f1, _r_f0, Y##_f1); \
|
||||
umul_ppmm(_m_f1, _m_f0, R##_f0, Y##_f0); \
|
||||
_r_f0 = 0; \
|
||||
if (_FP_FRAC_GT_2(_m, _r)) \
|
||||
{ \
|
||||
R##_f0--; \
|
||||
_FP_FRAC_ADD_2(_r, Y, _r); \
|
||||
if (_FP_FRAC_GE_2(_r, Y) && _FP_FRAC_GT_2(_m, _r)) \
|
||||
{ \
|
||||
R##_f0--; \
|
||||
_FP_FRAC_ADD_2(_r, Y, _r); \
|
||||
} \
|
||||
} \
|
||||
if (!_FP_FRAC_EQ_2(_r, _m)) \
|
||||
R##_f0 |= _FP_WORK_STICKY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define _FP_DIV_MEAT_2_gmp(fs, R, X, Y) \
|
||||
do { \
|
||||
_FP_W_TYPE _x[4], _y[2], _z[4]; \
|
||||
_y[0] = Y##_f0; _y[1] = Y##_f1; \
|
||||
_x[0] = _x[3] = 0; \
|
||||
if (_FP_FRAC_GT_2(X, Y)) \
|
||||
{ \
|
||||
R##_e++; \
|
||||
_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE) | \
|
||||
X##_f1 >> (_FP_W_TYPE_SIZE - \
|
||||
(_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE))); \
|
||||
_x[2] = X##_f1 << (_FP_WFRACBITS_##fs-1 - _FP_W_TYPE_SIZE); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
_x[1] = (X##_f0 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE) | \
|
||||
X##_f1 >> (_FP_W_TYPE_SIZE - \
|
||||
(_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE))); \
|
||||
_x[2] = X##_f1 << (_FP_WFRACBITS_##fs - _FP_W_TYPE_SIZE); \
|
||||
} \
|
||||
\
|
||||
(void) mpn_divrem (_z, 0, _x, 4, _y, 2); \
|
||||
R##_f1 = _z[1]; \
|
||||
R##_f0 = _z[0] | ((_x[0] | _x[1]) != 0); \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Square root algorithms:
|
||||
* We have just one right now, maybe Newton approximation
|
||||
* should be added for those machines where division is fast.
|
||||
*/
|
||||
|
||||
#define _FP_SQRT_MEAT_2(R, S, T, X, q) \
|
||||
do { \
|
||||
while (q) \
|
||||
{ \
|
||||
T##_f1 = S##_f1 + q; \
|
||||
if (T##_f1 <= X##_f1) \
|
||||
{ \
|
||||
S##_f1 = T##_f1 + q; \
|
||||
X##_f1 -= T##_f1; \
|
||||
R##_f1 += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_2(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
|
||||
while (q != _FP_WORK_ROUND) \
|
||||
{ \
|
||||
T##_f0 = S##_f0 + q; \
|
||||
T##_f1 = S##_f1; \
|
||||
if (T##_f1 < X##_f1 || \
|
||||
(T##_f1 == X##_f1 && T##_f0 <= X##_f0)) \
|
||||
{ \
|
||||
S##_f0 = T##_f0 + q; \
|
||||
S##_f1 += (T##_f0 > S##_f0); \
|
||||
_FP_FRAC_DEC_2(X, T); \
|
||||
R##_f0 += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_2(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
if (X##_f0 | X##_f1) \
|
||||
{ \
|
||||
if (S##_f1 < X##_f1 || \
|
||||
(S##_f1 == X##_f1 && S##_f0 < X##_f0)) \
|
||||
R##_f0 |= _FP_WORK_ROUND; \
|
||||
R##_f0 |= _FP_WORK_STICKY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Assembly/disassembly for converting to/from integral types.
|
||||
* No shifting or overflow handled here.
|
||||
*/
|
||||
|
||||
#define _FP_FRAC_ASSEMBLE_2(r, X, rsize) \
|
||||
(void)((rsize <= _FP_W_TYPE_SIZE) \
|
||||
? ({ r = X##_f0; }) \
|
||||
: ({ \
|
||||
r = X##_f1; \
|
||||
r <<= _FP_W_TYPE_SIZE; \
|
||||
r += X##_f0; \
|
||||
}))
|
||||
|
||||
#define _FP_FRAC_DISASSEMBLE_2(X, r, rsize) \
|
||||
do { \
|
||||
X##_f0 = r; \
|
||||
X##_f1 = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Convert FP values between word sizes
|
||||
*/
|
||||
|
||||
#define _FP_FRAC_COPY_1_2(D, S) (D##_f = S##_f0)
|
||||
|
||||
#define _FP_FRAC_COPY_2_1(D, S) ((D##_f0 = S##_f), (D##_f1 = 0))
|
||||
|
||||
#define _FP_FRAC_COPY_2_2(D,S) _FP_FRAC_COPY_2(D,S)
|
||||
687
ExternalApps/RadioSet/main/Source/soft-fp/op-4.h
Normal file
687
ExternalApps/RadioSet/main/Source/soft-fp/op-4.h
Normal file
@ -0,0 +1,687 @@
|
||||
/* Software floating-point emulation.
|
||||
Basic four-word fraction declaration and manipulation.
|
||||
Copyright (C) 1997,1998,1999,2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#define _FP_FRAC_DECL_4(X) _FP_W_TYPE X##_f[4]
|
||||
#define _FP_FRAC_COPY_4(D,S) \
|
||||
(D##_f[0] = S##_f[0], D##_f[1] = S##_f[1], \
|
||||
D##_f[2] = S##_f[2], D##_f[3] = S##_f[3])
|
||||
#define _FP_FRAC_SET_4(X,I) __FP_FRAC_SET_4(X, I)
|
||||
#define _FP_FRAC_HIGH_4(X) (X##_f[3])
|
||||
#define _FP_FRAC_LOW_4(X) (X##_f[0])
|
||||
#define _FP_FRAC_WORD_4(X,w) (X##_f[w])
|
||||
|
||||
#define _FP_FRAC_SLL_4(X,N) \
|
||||
do { \
|
||||
_FP_I_TYPE _up, _down, _skip, _i; \
|
||||
_skip = (N) / _FP_W_TYPE_SIZE; \
|
||||
_up = (N) % _FP_W_TYPE_SIZE; \
|
||||
_down = _FP_W_TYPE_SIZE - _up; \
|
||||
if (!_up) \
|
||||
for (_i = 3; _i >= _skip; --_i) \
|
||||
X##_f[_i] = X##_f[_i-_skip]; \
|
||||
else \
|
||||
{ \
|
||||
for (_i = 3; _i > _skip; --_i) \
|
||||
X##_f[_i] = X##_f[_i-_skip] << _up \
|
||||
| X##_f[_i-_skip-1] >> _down; \
|
||||
X##_f[_i--] = X##_f[0] << _up; \
|
||||
} \
|
||||
for (; _i >= 0; --_i) \
|
||||
X##_f[_i] = 0; \
|
||||
} while (0)
|
||||
|
||||
/* This one was broken too */
|
||||
#define _FP_FRAC_SRL_4(X,N) \
|
||||
do { \
|
||||
_FP_I_TYPE _up, _down, _skip, _i; \
|
||||
_skip = (N) / _FP_W_TYPE_SIZE; \
|
||||
_down = (N) % _FP_W_TYPE_SIZE; \
|
||||
_up = _FP_W_TYPE_SIZE - _down; \
|
||||
if (!_down) \
|
||||
for (_i = 0; _i <= 3-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip]; \
|
||||
else \
|
||||
{ \
|
||||
for (_i = 0; _i < 3-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip] >> _down \
|
||||
| X##_f[_i+_skip+1] << _up; \
|
||||
X##_f[_i++] = X##_f[3] >> _down; \
|
||||
} \
|
||||
for (; _i < 4; ++_i) \
|
||||
X##_f[_i] = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Right shift with sticky-lsb.
|
||||
* What this actually means is that we do a standard right-shift,
|
||||
* but that if any of the bits that fall off the right hand side
|
||||
* were one then we always set the LSbit.
|
||||
*/
|
||||
#define _FP_FRAC_SRST_4(X,S,N,size) \
|
||||
do { \
|
||||
_FP_I_TYPE _up, _down, _skip, _i; \
|
||||
_FP_W_TYPE _s; \
|
||||
_skip = (N) / _FP_W_TYPE_SIZE; \
|
||||
_down = (N) % _FP_W_TYPE_SIZE; \
|
||||
_up = _FP_W_TYPE_SIZE - _down; \
|
||||
for (_s = _i = 0; _i < _skip; ++_i) \
|
||||
_s |= X##_f[_i]; \
|
||||
if (!_down) \
|
||||
for (_i = 0; _i <= 3-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip]; \
|
||||
else \
|
||||
{ \
|
||||
_s |= X##_f[_i] << _up; \
|
||||
for (_i = 0; _i < 3-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip] >> _down \
|
||||
| X##_f[_i+_skip+1] << _up; \
|
||||
X##_f[_i++] = X##_f[3] >> _down; \
|
||||
} \
|
||||
for (; _i < 4; ++_i) \
|
||||
X##_f[_i] = 0; \
|
||||
S = (_s != 0); \
|
||||
} while (0)
|
||||
|
||||
#define _FP_FRAC_SRS_4(X,N,size) \
|
||||
do { \
|
||||
int _sticky; \
|
||||
_FP_FRAC_SRST_4(X, _sticky, N, size); \
|
||||
X##_f[0] |= _sticky; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_FRAC_ADD_4(R,X,Y) \
|
||||
__FP_FRAC_ADD_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
|
||||
X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
|
||||
Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
|
||||
|
||||
#define _FP_FRAC_SUB_4(R,X,Y) \
|
||||
__FP_FRAC_SUB_4(R##_f[3], R##_f[2], R##_f[1], R##_f[0], \
|
||||
X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
|
||||
Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
|
||||
|
||||
#define _FP_FRAC_DEC_4(X,Y) \
|
||||
__FP_FRAC_DEC_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
|
||||
Y##_f[3], Y##_f[2], Y##_f[1], Y##_f[0])
|
||||
|
||||
#define _FP_FRAC_ADDI_4(X,I) \
|
||||
__FP_FRAC_ADDI_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], I)
|
||||
|
||||
#define _FP_ZEROFRAC_4 0,0,0,0
|
||||
#define _FP_MINFRAC_4 0,0,0,1
|
||||
#define _FP_MAXFRAC_4 (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0), (~(_FP_WS_TYPE)0)
|
||||
|
||||
#define _FP_FRAC_ZEROP_4(X) ((X##_f[0] | X##_f[1] | X##_f[2] | X##_f[3]) == 0)
|
||||
#define _FP_FRAC_NEGP_4(X) ((_FP_WS_TYPE)X##_f[3] < 0)
|
||||
#define _FP_FRAC_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) & _FP_OVERFLOW_##fs)
|
||||
#define _FP_FRAC_CLEAR_OVERP_4(fs,X) (_FP_FRAC_HIGH_##fs(X) &= ~_FP_OVERFLOW_##fs)
|
||||
|
||||
#define _FP_FRAC_EQ_4(X,Y) \
|
||||
(X##_f[0] == Y##_f[0] && X##_f[1] == Y##_f[1] \
|
||||
&& X##_f[2] == Y##_f[2] && X##_f[3] == Y##_f[3])
|
||||
|
||||
#define _FP_FRAC_GT_4(X,Y) \
|
||||
(X##_f[3] > Y##_f[3] || \
|
||||
(X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
|
||||
(X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
|
||||
(X##_f[1] == Y##_f[1] && X##_f[0] > Y##_f[0]) \
|
||||
)) \
|
||||
)) \
|
||||
)
|
||||
|
||||
#define _FP_FRAC_GE_4(X,Y) \
|
||||
(X##_f[3] > Y##_f[3] || \
|
||||
(X##_f[3] == Y##_f[3] && (X##_f[2] > Y##_f[2] || \
|
||||
(X##_f[2] == Y##_f[2] && (X##_f[1] > Y##_f[1] || \
|
||||
(X##_f[1] == Y##_f[1] && X##_f[0] >= Y##_f[0]) \
|
||||
)) \
|
||||
)) \
|
||||
)
|
||||
|
||||
|
||||
#define _FP_FRAC_CLZ_4(R,X) \
|
||||
do { \
|
||||
if (X##_f[3]) \
|
||||
{ \
|
||||
__FP_CLZ(R,X##_f[3]); \
|
||||
} \
|
||||
else if (X##_f[2]) \
|
||||
{ \
|
||||
__FP_CLZ(R,X##_f[2]); \
|
||||
R += _FP_W_TYPE_SIZE; \
|
||||
} \
|
||||
else if (X##_f[1]) \
|
||||
{ \
|
||||
__FP_CLZ(R,X##_f[1]); \
|
||||
R += _FP_W_TYPE_SIZE*2; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
__FP_CLZ(R,X##_f[0]); \
|
||||
R += _FP_W_TYPE_SIZE*3; \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
#define _FP_UNPACK_RAW_4(fs, X, val) \
|
||||
do { \
|
||||
union _FP_UNION_##fs _flo; _flo.flt = (val); \
|
||||
X##_f[0] = _flo.bits.frac0; \
|
||||
X##_f[1] = _flo.bits.frac1; \
|
||||
X##_f[2] = _flo.bits.frac2; \
|
||||
X##_f[3] = _flo.bits.frac3; \
|
||||
X##_e = _flo.bits.exp; \
|
||||
X##_s = _flo.bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_UNPACK_RAW_4_P(fs, X, val) \
|
||||
do { \
|
||||
union _FP_UNION_##fs *_flo = \
|
||||
(union _FP_UNION_##fs *)(val); \
|
||||
\
|
||||
X##_f[0] = _flo->bits.frac0; \
|
||||
X##_f[1] = _flo->bits.frac1; \
|
||||
X##_f[2] = _flo->bits.frac2; \
|
||||
X##_f[3] = _flo->bits.frac3; \
|
||||
X##_e = _flo->bits.exp; \
|
||||
X##_s = _flo->bits.sign; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_PACK_RAW_4(fs, val, X) \
|
||||
do { \
|
||||
union _FP_UNION_##fs _flo; \
|
||||
_flo.bits.frac0 = X##_f[0]; \
|
||||
_flo.bits.frac1 = X##_f[1]; \
|
||||
_flo.bits.frac2 = X##_f[2]; \
|
||||
_flo.bits.frac3 = X##_f[3]; \
|
||||
_flo.bits.exp = X##_e; \
|
||||
_flo.bits.sign = X##_s; \
|
||||
(val) = _flo.flt; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_PACK_RAW_4_P(fs, val, X) \
|
||||
do { \
|
||||
union _FP_UNION_##fs *_flo = \
|
||||
(union _FP_UNION_##fs *)(val); \
|
||||
\
|
||||
_flo->bits.frac0 = X##_f[0]; \
|
||||
_flo->bits.frac1 = X##_f[1]; \
|
||||
_flo->bits.frac2 = X##_f[2]; \
|
||||
_flo->bits.frac3 = X##_f[3]; \
|
||||
_flo->bits.exp = X##_e; \
|
||||
_flo->bits.sign = X##_s; \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Multiplication algorithms:
|
||||
*/
|
||||
|
||||
/* Given a 1W * 1W => 2W primitive, do the extended multiplication. */
|
||||
|
||||
#define _FP_MUL_MEAT_4_wide(wfracbits, R, X, Y, doit) \
|
||||
do { \
|
||||
_FP_FRAC_DECL_8(_z); _FP_FRAC_DECL_2(_b); _FP_FRAC_DECL_2(_c); \
|
||||
_FP_FRAC_DECL_2(_d); _FP_FRAC_DECL_2(_e); _FP_FRAC_DECL_2(_f); \
|
||||
\
|
||||
doit(_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0), X##_f[0], Y##_f[0]); \
|
||||
doit(_b_f1, _b_f0, X##_f[0], Y##_f[1]); \
|
||||
doit(_c_f1, _c_f0, X##_f[1], Y##_f[0]); \
|
||||
doit(_d_f1, _d_f0, X##_f[1], Y##_f[1]); \
|
||||
doit(_e_f1, _e_f0, X##_f[0], Y##_f[2]); \
|
||||
doit(_f_f1, _f_f0, X##_f[2], Y##_f[0]); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
|
||||
_FP_FRAC_WORD_8(_z,1), 0,_b_f1,_b_f0, \
|
||||
0,0,_FP_FRAC_WORD_8(_z,1)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
|
||||
_FP_FRAC_WORD_8(_z,1), 0,_c_f1,_c_f0, \
|
||||
_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2), \
|
||||
_FP_FRAC_WORD_8(_z,1)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
|
||||
_FP_FRAC_WORD_8(_z,2), 0,_d_f1,_d_f0, \
|
||||
0,_FP_FRAC_WORD_8(_z,3),_FP_FRAC_WORD_8(_z,2)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
|
||||
_FP_FRAC_WORD_8(_z,2), 0,_e_f1,_e_f0, \
|
||||
_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
|
||||
_FP_FRAC_WORD_8(_z,2)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
|
||||
_FP_FRAC_WORD_8(_z,2), 0,_f_f1,_f_f0, \
|
||||
_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3), \
|
||||
_FP_FRAC_WORD_8(_z,2)); \
|
||||
doit(_b_f1, _b_f0, X##_f[0], Y##_f[3]); \
|
||||
doit(_c_f1, _c_f0, X##_f[3], Y##_f[0]); \
|
||||
doit(_d_f1, _d_f0, X##_f[1], Y##_f[2]); \
|
||||
doit(_e_f1, _e_f0, X##_f[2], Y##_f[1]); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
|
||||
_FP_FRAC_WORD_8(_z,3), 0,_b_f1,_b_f0, \
|
||||
0,_FP_FRAC_WORD_8(_z,4),_FP_FRAC_WORD_8(_z,3)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
|
||||
_FP_FRAC_WORD_8(_z,3), 0,_c_f1,_c_f0, \
|
||||
_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
|
||||
_FP_FRAC_WORD_8(_z,3)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
|
||||
_FP_FRAC_WORD_8(_z,3), 0,_d_f1,_d_f0, \
|
||||
_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
|
||||
_FP_FRAC_WORD_8(_z,3)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
|
||||
_FP_FRAC_WORD_8(_z,3), 0,_e_f1,_e_f0, \
|
||||
_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4), \
|
||||
_FP_FRAC_WORD_8(_z,3)); \
|
||||
doit(_b_f1, _b_f0, X##_f[2], Y##_f[2]); \
|
||||
doit(_c_f1, _c_f0, X##_f[1], Y##_f[3]); \
|
||||
doit(_d_f1, _d_f0, X##_f[3], Y##_f[1]); \
|
||||
doit(_e_f1, _e_f0, X##_f[2], Y##_f[3]); \
|
||||
doit(_f_f1, _f_f0, X##_f[3], Y##_f[2]); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
|
||||
_FP_FRAC_WORD_8(_z,4), 0,_b_f1,_b_f0, \
|
||||
0,_FP_FRAC_WORD_8(_z,5),_FP_FRAC_WORD_8(_z,4)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
|
||||
_FP_FRAC_WORD_8(_z,4), 0,_c_f1,_c_f0, \
|
||||
_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
|
||||
_FP_FRAC_WORD_8(_z,4)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
|
||||
_FP_FRAC_WORD_8(_z,4), 0,_d_f1,_d_f0, \
|
||||
_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5), \
|
||||
_FP_FRAC_WORD_8(_z,4)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
|
||||
_FP_FRAC_WORD_8(_z,5), 0,_e_f1,_e_f0, \
|
||||
0,_FP_FRAC_WORD_8(_z,6),_FP_FRAC_WORD_8(_z,5)); \
|
||||
__FP_FRAC_ADD_3(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
|
||||
_FP_FRAC_WORD_8(_z,5), 0,_f_f1,_f_f0, \
|
||||
_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
|
||||
_FP_FRAC_WORD_8(_z,5)); \
|
||||
doit(_b_f1, _b_f0, X##_f[3], Y##_f[3]); \
|
||||
__FP_FRAC_ADD_2(_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6), \
|
||||
_b_f1,_b_f0, \
|
||||
_FP_FRAC_WORD_8(_z,7),_FP_FRAC_WORD_8(_z,6)); \
|
||||
\
|
||||
/* Normalize since we know where the msb of the multiplicands \
|
||||
were (bit B), we know that the msb of the of the product is \
|
||||
at either 2B or 2B-1. */ \
|
||||
_FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
|
||||
__FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
|
||||
_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
|
||||
} while (0)
|
||||
|
||||
#define _FP_MUL_MEAT_4_gmp(wfracbits, R, X, Y) \
|
||||
do { \
|
||||
_FP_FRAC_DECL_8(_z); \
|
||||
\
|
||||
mpn_mul_n(_z_f, _x_f, _y_f, 4); \
|
||||
\
|
||||
/* Normalize since we know where the msb of the multiplicands \
|
||||
were (bit B), we know that the msb of the of the product is \
|
||||
at either 2B or 2B-1. */ \
|
||||
_FP_FRAC_SRS_8(_z, wfracbits-1, 2*wfracbits); \
|
||||
__FP_FRAC_SET_4(R, _FP_FRAC_WORD_8(_z,3), _FP_FRAC_WORD_8(_z,2), \
|
||||
_FP_FRAC_WORD_8(_z,1), _FP_FRAC_WORD_8(_z,0)); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Helper utility for _FP_DIV_MEAT_4_udiv:
|
||||
* pppp = m * nnn
|
||||
*/
|
||||
#define umul_ppppmnnn(p3,p2,p1,p0,m,n2,n1,n0) \
|
||||
do { \
|
||||
UWtype _t; \
|
||||
umul_ppmm(p1,p0,m,n0); \
|
||||
umul_ppmm(p2,_t,m,n1); \
|
||||
__FP_FRAC_ADDI_2(p2,p1,_t); \
|
||||
umul_ppmm(p3,_t,m,n2); \
|
||||
__FP_FRAC_ADDI_2(p3,p2,_t); \
|
||||
} while (0)
|
||||
|
||||
/*
|
||||
* Division algorithms:
|
||||
*/
|
||||
|
||||
#define _FP_DIV_MEAT_4_udiv(fs, R, X, Y) \
|
||||
do { \
|
||||
int _i; \
|
||||
_FP_FRAC_DECL_4(_n); _FP_FRAC_DECL_4(_m); \
|
||||
_FP_FRAC_SET_4(_n, _FP_ZEROFRAC_4); \
|
||||
if (_FP_FRAC_GT_4(X, Y)) \
|
||||
{ \
|
||||
_n_f[3] = X##_f[0] << (_FP_W_TYPE_SIZE - 1); \
|
||||
_FP_FRAC_SRL_4(X, 1); \
|
||||
} \
|
||||
else \
|
||||
R##_e--; \
|
||||
\
|
||||
/* Normalize, i.e. make the most significant bit of the \
|
||||
denominator set. */ \
|
||||
_FP_FRAC_SLL_4(Y, _FP_WFRACXBITS_##fs); \
|
||||
\
|
||||
for (_i = 3; ; _i--) \
|
||||
{ \
|
||||
if (X##_f[3] == Y##_f[3]) \
|
||||
{ \
|
||||
/* This is a special case, not an optimization \
|
||||
(X##_f[3]/Y##_f[3] would not fit into UWtype). \
|
||||
As X## is guaranteed to be < Y, R##_f[_i] can be either \
|
||||
(UWtype)-1 or (UWtype)-2. */ \
|
||||
R##_f[_i] = -1; \
|
||||
if (!_i) \
|
||||
break; \
|
||||
__FP_FRAC_SUB_4(X##_f[3], X##_f[2], X##_f[1], X##_f[0], \
|
||||
Y##_f[2], Y##_f[1], Y##_f[0], 0, \
|
||||
X##_f[2], X##_f[1], X##_f[0], _n_f[_i]); \
|
||||
_FP_FRAC_SUB_4(X, Y, X); \
|
||||
if (X##_f[3] > Y##_f[3]) \
|
||||
{ \
|
||||
R##_f[_i] = -2; \
|
||||
_FP_FRAC_ADD_4(X, Y, X); \
|
||||
} \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
udiv_qrnnd(R##_f[_i], X##_f[3], X##_f[3], X##_f[2], Y##_f[3]); \
|
||||
umul_ppppmnnn(_m_f[3], _m_f[2], _m_f[1], _m_f[0], \
|
||||
R##_f[_i], Y##_f[2], Y##_f[1], Y##_f[0]); \
|
||||
X##_f[2] = X##_f[1]; \
|
||||
X##_f[1] = X##_f[0]; \
|
||||
X##_f[0] = _n_f[_i]; \
|
||||
if (_FP_FRAC_GT_4(_m, X)) \
|
||||
{ \
|
||||
R##_f[_i]--; \
|
||||
_FP_FRAC_ADD_4(X, Y, X); \
|
||||
if (_FP_FRAC_GE_4(X, Y) && _FP_FRAC_GT_4(_m, X)) \
|
||||
{ \
|
||||
R##_f[_i]--; \
|
||||
_FP_FRAC_ADD_4(X, Y, X); \
|
||||
} \
|
||||
} \
|
||||
_FP_FRAC_DEC_4(X, _m); \
|
||||
if (!_i) \
|
||||
{ \
|
||||
if (!_FP_FRAC_EQ_4(X, _m)) \
|
||||
R##_f[0] |= _FP_WORK_STICKY; \
|
||||
break; \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Square root algorithms:
|
||||
* We have just one right now, maybe Newton approximation
|
||||
* should be added for those machines where division is fast.
|
||||
*/
|
||||
|
||||
#define _FP_SQRT_MEAT_4(R, S, T, X, q) \
|
||||
do { \
|
||||
while (q) \
|
||||
{ \
|
||||
T##_f[3] = S##_f[3] + q; \
|
||||
if (T##_f[3] <= X##_f[3]) \
|
||||
{ \
|
||||
S##_f[3] = T##_f[3] + q; \
|
||||
X##_f[3] -= T##_f[3]; \
|
||||
R##_f[3] += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_4(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
|
||||
while (q) \
|
||||
{ \
|
||||
T##_f[2] = S##_f[2] + q; \
|
||||
T##_f[3] = S##_f[3]; \
|
||||
if (T##_f[3] < X##_f[3] || \
|
||||
(T##_f[3] == X##_f[3] && T##_f[2] <= X##_f[2])) \
|
||||
{ \
|
||||
S##_f[2] = T##_f[2] + q; \
|
||||
S##_f[3] += (T##_f[2] > S##_f[2]); \
|
||||
__FP_FRAC_DEC_2(X##_f[3], X##_f[2], \
|
||||
T##_f[3], T##_f[2]); \
|
||||
R##_f[2] += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_4(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
|
||||
while (q) \
|
||||
{ \
|
||||
T##_f[1] = S##_f[1] + q; \
|
||||
T##_f[2] = S##_f[2]; \
|
||||
T##_f[3] = S##_f[3]; \
|
||||
if (T##_f[3] < X##_f[3] || \
|
||||
(T##_f[3] == X##_f[3] && (T##_f[2] < X##_f[2] || \
|
||||
(T##_f[2] == X##_f[2] && T##_f[1] <= X##_f[1])))) \
|
||||
{ \
|
||||
S##_f[1] = T##_f[1] + q; \
|
||||
S##_f[2] += (T##_f[1] > S##_f[1]); \
|
||||
S##_f[3] += (T##_f[2] > S##_f[2]); \
|
||||
__FP_FRAC_DEC_3(X##_f[3], X##_f[2], X##_f[1], \
|
||||
T##_f[3], T##_f[2], T##_f[1]); \
|
||||
R##_f[1] += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_4(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
q = (_FP_W_TYPE)1 << (_FP_W_TYPE_SIZE - 1); \
|
||||
while (q != _FP_WORK_ROUND) \
|
||||
{ \
|
||||
T##_f[0] = S##_f[0] + q; \
|
||||
T##_f[1] = S##_f[1]; \
|
||||
T##_f[2] = S##_f[2]; \
|
||||
T##_f[3] = S##_f[3]; \
|
||||
if (_FP_FRAC_GE_4(X,T)) \
|
||||
{ \
|
||||
S##_f[0] = T##_f[0] + q; \
|
||||
S##_f[1] += (T##_f[0] > S##_f[0]); \
|
||||
S##_f[2] += (T##_f[1] > S##_f[1]); \
|
||||
S##_f[3] += (T##_f[2] > S##_f[2]); \
|
||||
_FP_FRAC_DEC_4(X, T); \
|
||||
R##_f[0] += q; \
|
||||
} \
|
||||
_FP_FRAC_SLL_4(X, 1); \
|
||||
q >>= 1; \
|
||||
} \
|
||||
if (!_FP_FRAC_ZEROP_4(X)) \
|
||||
{ \
|
||||
if (_FP_FRAC_GT_4(X,S)) \
|
||||
R##_f[0] |= _FP_WORK_ROUND; \
|
||||
R##_f[0] |= _FP_WORK_STICKY; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
/*
|
||||
* Internals
|
||||
*/
|
||||
|
||||
#define __FP_FRAC_SET_4(X,I3,I2,I1,I0) \
|
||||
(X##_f[3] = I3, X##_f[2] = I2, X##_f[1] = I1, X##_f[0] = I0)
|
||||
|
||||
#ifndef __FP_FRAC_ADD_3
|
||||
#define __FP_FRAC_ADD_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
|
||||
do { \
|
||||
_FP_W_TYPE _c1, _c2; \
|
||||
r0 = x0 + y0; \
|
||||
_c1 = r0 < x0; \
|
||||
r1 = x1 + y1; \
|
||||
_c2 = r1 < x1; \
|
||||
r1 += _c1; \
|
||||
_c2 |= r1 < _c1; \
|
||||
r2 = x2 + y2 + _c2; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef __FP_FRAC_ADD_4
|
||||
#define __FP_FRAC_ADD_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
|
||||
do { \
|
||||
_FP_W_TYPE _c1, _c2, _c3; \
|
||||
r0 = x0 + y0; \
|
||||
_c1 = r0 < x0; \
|
||||
r1 = x1 + y1; \
|
||||
_c2 = r1 < x1; \
|
||||
r1 += _c1; \
|
||||
_c2 |= r1 < _c1; \
|
||||
r2 = x2 + y2; \
|
||||
_c3 = r2 < x2; \
|
||||
r2 += _c2; \
|
||||
_c3 |= r2 < _c2; \
|
||||
r3 = x3 + y3 + _c3; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef __FP_FRAC_SUB_3
|
||||
#define __FP_FRAC_SUB_3(r2,r1,r0,x2,x1,x0,y2,y1,y0) \
|
||||
do { \
|
||||
_FP_W_TYPE _c1, _c2; \
|
||||
r0 = x0 - y0; \
|
||||
_c1 = r0 > x0; \
|
||||
r1 = x1 - y1; \
|
||||
_c2 = r1 > x1; \
|
||||
r1 -= _c1; \
|
||||
_c2 |= _c1 && (y1 == x1); \
|
||||
r2 = x2 - y2 - _c2; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef __FP_FRAC_SUB_4
|
||||
#define __FP_FRAC_SUB_4(r3,r2,r1,r0,x3,x2,x1,x0,y3,y2,y1,y0) \
|
||||
do { \
|
||||
_FP_W_TYPE _c1, _c2, _c3; \
|
||||
r0 = x0 - y0; \
|
||||
_c1 = r0 > x0; \
|
||||
r1 = x1 - y1; \
|
||||
_c2 = r1 > x1; \
|
||||
r1 -= _c1; \
|
||||
_c2 |= _c1 && (y1 == x1); \
|
||||
r2 = x2 - y2; \
|
||||
_c3 = r2 > x2; \
|
||||
r2 -= _c2; \
|
||||
_c3 |= _c2 && (y2 == x2); \
|
||||
r3 = x3 - y3 - _c3; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef __FP_FRAC_DEC_3
|
||||
#define __FP_FRAC_DEC_3(x2,x1,x0,y2,y1,y0) \
|
||||
do { \
|
||||
UWtype _t0, _t1, _t2; \
|
||||
_t0 = x0, _t1 = x1, _t2 = x2; \
|
||||
__FP_FRAC_SUB_3 (x2, x1, x0, _t2, _t1, _t0, y2, y1, y0); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef __FP_FRAC_DEC_4
|
||||
#define __FP_FRAC_DEC_4(x3,x2,x1,x0,y3,y2,y1,y0) \
|
||||
do { \
|
||||
UWtype _t0, _t1, _t2, _t3; \
|
||||
_t0 = x0, _t1 = x1, _t2 = x2, _t3 = x3; \
|
||||
__FP_FRAC_SUB_4 (x3,x2,x1,x0,_t3,_t2,_t1,_t0, y3,y2,y1,y0); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef __FP_FRAC_ADDI_4
|
||||
#define __FP_FRAC_ADDI_4(x3,x2,x1,x0,i) \
|
||||
do { \
|
||||
UWtype _t; \
|
||||
_t = ((x0 += i) < i); \
|
||||
x1 += _t; _t = (x1 < _t); \
|
||||
x2 += _t; _t = (x2 < _t); \
|
||||
x3 += _t; \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
/* Convert FP values between word sizes. This appears to be more
|
||||
* complicated than I'd have expected it to be, so these might be
|
||||
* wrong... These macros are in any case somewhat bogus because they
|
||||
* use information about what various FRAC_n variables look like
|
||||
* internally [eg, that 2 word vars are X_f0 and x_f1]. But so do
|
||||
* the ones in op-2.h and op-1.h.
|
||||
*/
|
||||
#define _FP_FRAC_COPY_1_4(D, S) (D##_f = S##_f[0])
|
||||
|
||||
#define _FP_FRAC_COPY_2_4(D, S) \
|
||||
do { \
|
||||
D##_f0 = S##_f[0]; \
|
||||
D##_f1 = S##_f[1]; \
|
||||
} while (0)
|
||||
|
||||
/* Assembly/disassembly for converting to/from integral types.
|
||||
* No shifting or overflow handled here.
|
||||
*/
|
||||
/* Put the FP value X into r, which is an integer of size rsize. */
|
||||
#define _FP_FRAC_ASSEMBLE_4(r, X, rsize) \
|
||||
do { \
|
||||
if (rsize <= _FP_W_TYPE_SIZE) \
|
||||
r = X##_f[0]; \
|
||||
else if (rsize <= 2*_FP_W_TYPE_SIZE) \
|
||||
{ \
|
||||
r = X##_f[1]; \
|
||||
r <<= _FP_W_TYPE_SIZE; \
|
||||
r += X##_f[0]; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
/* I'm feeling lazy so we deal with int == 3words (implausible)*/ \
|
||||
/* and int == 4words as a single case. */ \
|
||||
r = X##_f[3]; \
|
||||
r <<= _FP_W_TYPE_SIZE; \
|
||||
r += X##_f[2]; \
|
||||
r <<= _FP_W_TYPE_SIZE; \
|
||||
r += X##_f[1]; \
|
||||
r <<= _FP_W_TYPE_SIZE; \
|
||||
r += X##_f[0]; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* "No disassemble Number Five!" */
|
||||
/* move an integer of size rsize into X's fractional part. We rely on
|
||||
* the _f[] array consisting of words of size _FP_W_TYPE_SIZE to avoid
|
||||
* having to mask the values we store into it.
|
||||
*/
|
||||
#define _FP_FRAC_DISASSEMBLE_4(X, r, rsize) \
|
||||
do { \
|
||||
X##_f[0] = r; \
|
||||
X##_f[1] = (rsize <= _FP_W_TYPE_SIZE ? 0 : r >> _FP_W_TYPE_SIZE); \
|
||||
X##_f[2] = (rsize <= 2*_FP_W_TYPE_SIZE ? 0 : r >> 2*_FP_W_TYPE_SIZE); \
|
||||
X##_f[3] = (rsize <= 3*_FP_W_TYPE_SIZE ? 0 : r >> 3*_FP_W_TYPE_SIZE); \
|
||||
} while (0);
|
||||
|
||||
#define _FP_FRAC_COPY_4_1(D, S) \
|
||||
do { \
|
||||
D##_f[0] = S##_f; \
|
||||
D##_f[1] = D##_f[2] = D##_f[3] = 0; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_FRAC_COPY_4_2(D, S) \
|
||||
do { \
|
||||
D##_f[0] = S##_f0; \
|
||||
D##_f[1] = S##_f1; \
|
||||
D##_f[2] = D##_f[3] = 0; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_FRAC_COPY_4_4(D,S) _FP_FRAC_COPY_4(D,S)
|
||||
109
ExternalApps/RadioSet/main/Source/soft-fp/op-8.h
Normal file
109
ExternalApps/RadioSet/main/Source/soft-fp/op-8.h
Normal file
@ -0,0 +1,109 @@
|
||||
/* Software floating-point emulation.
|
||||
Basic eight-word fraction declaration and manipulation.
|
||||
Copyright (C) 1997,1998,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* We need just a few things from here for op-4, if we ever need some
|
||||
other macros, they can be added. */
|
||||
#define _FP_FRAC_DECL_8(X) _FP_W_TYPE X##_f[8]
|
||||
#define _FP_FRAC_HIGH_8(X) (X##_f[7])
|
||||
#define _FP_FRAC_LOW_8(X) (X##_f[0])
|
||||
#define _FP_FRAC_WORD_8(X,w) (X##_f[w])
|
||||
|
||||
#define _FP_FRAC_SLL_8(X,N) \
|
||||
do { \
|
||||
_FP_I_TYPE _up, _down, _skip, _i; \
|
||||
_skip = (N) / _FP_W_TYPE_SIZE; \
|
||||
_up = (N) % _FP_W_TYPE_SIZE; \
|
||||
_down = _FP_W_TYPE_SIZE - _up; \
|
||||
if (!_up) \
|
||||
for (_i = 7; _i >= _skip; --_i) \
|
||||
X##_f[_i] = X##_f[_i-_skip]; \
|
||||
else \
|
||||
{ \
|
||||
for (_i = 7; _i > _skip; --_i) \
|
||||
X##_f[_i] = X##_f[_i-_skip] << _up \
|
||||
| X##_f[_i-_skip-1] >> _down; \
|
||||
X##_f[_i--] = X##_f[0] << _up; \
|
||||
} \
|
||||
for (; _i >= 0; --_i) \
|
||||
X##_f[_i] = 0; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_FRAC_SRL_8(X,N) \
|
||||
do { \
|
||||
_FP_I_TYPE _up, _down, _skip, _i; \
|
||||
_skip = (N) / _FP_W_TYPE_SIZE; \
|
||||
_down = (N) % _FP_W_TYPE_SIZE; \
|
||||
_up = _FP_W_TYPE_SIZE - _down; \
|
||||
if (!_down) \
|
||||
for (_i = 0; _i <= 7-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip]; \
|
||||
else \
|
||||
{ \
|
||||
for (_i = 0; _i < 7-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip] >> _down \
|
||||
| X##_f[_i+_skip+1] << _up; \
|
||||
X##_f[_i++] = X##_f[7] >> _down; \
|
||||
} \
|
||||
for (; _i < 8; ++_i) \
|
||||
X##_f[_i] = 0; \
|
||||
} while (0)
|
||||
|
||||
|
||||
/* Right shift with sticky-lsb.
|
||||
* What this actually means is that we do a standard right-shift,
|
||||
* but that if any of the bits that fall off the right hand side
|
||||
* were one then we always set the LSbit.
|
||||
*/
|
||||
#define _FP_FRAC_SRS_8(X,N,size) \
|
||||
do { \
|
||||
_FP_I_TYPE _up, _down, _skip, _i; \
|
||||
_FP_W_TYPE _s; \
|
||||
_skip = (N) / _FP_W_TYPE_SIZE; \
|
||||
_down = (N) % _FP_W_TYPE_SIZE; \
|
||||
_up = _FP_W_TYPE_SIZE - _down; \
|
||||
for (_s = _i = 0; _i < _skip; ++_i) \
|
||||
_s |= X##_f[_i]; \
|
||||
if (!_down) \
|
||||
for (_i = 0; _i <= 7-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip]; \
|
||||
else \
|
||||
{ \
|
||||
_s |= X##_f[_i] << _up; \
|
||||
for (_i = 0; _i < 7-_skip; ++_i) \
|
||||
X##_f[_i] = X##_f[_i+_skip] >> _down \
|
||||
| X##_f[_i+_skip+1] << _up; \
|
||||
X##_f[_i++] = X##_f[7] >> _down; \
|
||||
} \
|
||||
for (; _i < 8; ++_i) \
|
||||
X##_f[_i] = 0; \
|
||||
/* don't fix the LSB until the very end when we're sure f[0] is stable */ \
|
||||
X##_f[0] |= (_s != 0); \
|
||||
} while (0)
|
||||
1365
ExternalApps/RadioSet/main/Source/soft-fp/op-common.h
Normal file
1365
ExternalApps/RadioSet/main/Source/soft-fp/op-common.h
Normal file
File diff suppressed because it is too large
Load Diff
270
ExternalApps/RadioSet/main/Source/soft-fp/quad.h
Normal file
270
ExternalApps/RadioSet/main/Source/soft-fp/quad.h
Normal file
@ -0,0 +1,270 @@
|
||||
/* Software floating-point emulation.
|
||||
Definitions for IEEE Quad Precision.
|
||||
Copyright (C) 1997,1998,1999,2006,2007,2012 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 32
|
||||
#error "Here's a nickel, kid. Go buy yourself a real computer."
|
||||
#endif
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 64
|
||||
#define _FP_FRACTBITS_Q (4*_FP_W_TYPE_SIZE)
|
||||
#else
|
||||
#define _FP_FRACTBITS_Q (2*_FP_W_TYPE_SIZE)
|
||||
#endif
|
||||
|
||||
#define _FP_FRACBITS_Q 113
|
||||
#define _FP_FRACXBITS_Q (_FP_FRACTBITS_Q - _FP_FRACBITS_Q)
|
||||
#define _FP_WFRACBITS_Q (_FP_WORKBITS + _FP_FRACBITS_Q)
|
||||
#define _FP_WFRACXBITS_Q (_FP_FRACTBITS_Q - _FP_WFRACBITS_Q)
|
||||
#define _FP_EXPBITS_Q 15
|
||||
#define _FP_EXPBIAS_Q 16383
|
||||
#define _FP_EXPMAX_Q 32767
|
||||
|
||||
#define _FP_QNANBIT_Q \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_QNANBIT_SH_Q \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-2+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_IMPLBIT_Q \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_IMPLBIT_SH_Q \
|
||||
((_FP_W_TYPE)1 << (_FP_FRACBITS_Q-1+_FP_WORKBITS) % _FP_W_TYPE_SIZE)
|
||||
#define _FP_OVERFLOW_Q \
|
||||
((_FP_W_TYPE)1 << (_FP_WFRACBITS_Q % _FP_W_TYPE_SIZE))
|
||||
|
||||
typedef float TFtype; // __attribute__((mode(TF)));
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 64
|
||||
|
||||
union _FP_UNION_Q
|
||||
{
|
||||
TFtype flt;
|
||||
struct _FP_STRUCT_LAYOUT
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sign : 1;
|
||||
unsigned exp : _FP_EXPBITS_Q;
|
||||
unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
|
||||
unsigned long frac2 : _FP_W_TYPE_SIZE;
|
||||
unsigned long frac1 : _FP_W_TYPE_SIZE;
|
||||
unsigned long frac0 : _FP_W_TYPE_SIZE;
|
||||
#else
|
||||
unsigned long frac0 : _FP_W_TYPE_SIZE;
|
||||
unsigned long frac1 : _FP_W_TYPE_SIZE;
|
||||
unsigned long frac2 : _FP_W_TYPE_SIZE;
|
||||
unsigned long frac3 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0)-(_FP_W_TYPE_SIZE * 3);
|
||||
unsigned exp : _FP_EXPBITS_Q;
|
||||
unsigned sign : 1;
|
||||
#endif /* not bigendian */
|
||||
} bits __attribute__((packed));
|
||||
};
|
||||
|
||||
|
||||
#define FP_DECL_Q(X) _FP_DECL(4,X)
|
||||
#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_4(Q,X,val)
|
||||
#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_4_P(Q,X,val)
|
||||
#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_4(Q,val,X)
|
||||
#define FP_PACK_RAW_QP(val,X) \
|
||||
do { \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_4_P(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_Q(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_4(Q,X,val); \
|
||||
_FP_UNPACK_CANONICAL(Q,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_QP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_4_P(Q,X,val); \
|
||||
_FP_UNPACK_CANONICAL(Q,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_Q(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_4(Q,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(Q,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_QP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_4_P(Q,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(Q,4,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_Q(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(Q,4,X); \
|
||||
_FP_PACK_RAW_4(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_QP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(Q,4,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_4_P(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_Q(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(Q,4,X); \
|
||||
_FP_PACK_RAW_4(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_QP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(Q,4,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_4_P(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,4,X)
|
||||
#define FP_NEG_Q(R,X) _FP_NEG(Q,4,R,X)
|
||||
#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,4,R,X,Y)
|
||||
#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,4,R,X,Y)
|
||||
#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,4,R,X,Y)
|
||||
#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,4,R,X,Y)
|
||||
#define FP_SQRT_Q(R,X) _FP_SQRT(Q,4,R,X)
|
||||
#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_4(R,S,T,X,Q)
|
||||
|
||||
#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,4,r,X,Y,un)
|
||||
#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,4,r,X,Y)
|
||||
#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,4,r,X,Y)
|
||||
|
||||
#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,4,r,X,rsz,rsg)
|
||||
#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,4,X,r,rs,rt)
|
||||
|
||||
#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_4(X)
|
||||
#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_4(X)
|
||||
|
||||
#else /* not _FP_W_TYPE_SIZE < 64 */
|
||||
union _FP_UNION_Q
|
||||
{
|
||||
TFtype flt /* __attribute__((mode(TF))) */ ;
|
||||
struct _FP_STRUCT_LAYOUT {
|
||||
_FP_W_TYPE a, b;
|
||||
} longs;
|
||||
struct _FP_STRUCT_LAYOUT {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sign : 1;
|
||||
unsigned exp : _FP_EXPBITS_Q;
|
||||
_FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE;
|
||||
_FP_W_TYPE frac0 : _FP_W_TYPE_SIZE;
|
||||
#else
|
||||
_FP_W_TYPE frac0 : _FP_W_TYPE_SIZE;
|
||||
_FP_W_TYPE frac1 : _FP_FRACBITS_Q - (_FP_IMPLBIT_Q != 0) - _FP_W_TYPE_SIZE;
|
||||
unsigned exp : _FP_EXPBITS_Q;
|
||||
unsigned sign : 1;
|
||||
#endif
|
||||
} bits;
|
||||
};
|
||||
|
||||
#define FP_DECL_Q(X) _FP_DECL(2,X)
|
||||
#define FP_UNPACK_RAW_Q(X,val) _FP_UNPACK_RAW_2(Q,X,val)
|
||||
#define FP_UNPACK_RAW_QP(X,val) _FP_UNPACK_RAW_2_P(Q,X,val)
|
||||
#define FP_PACK_RAW_Q(val,X) _FP_PACK_RAW_2(Q,val,X)
|
||||
#define FP_PACK_RAW_QP(val,X) \
|
||||
do { \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_2_P(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_Q(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2(Q,X,val); \
|
||||
_FP_UNPACK_CANONICAL(Q,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_QP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2_P(Q,X,val); \
|
||||
_FP_UNPACK_CANONICAL(Q,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_Q(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2(Q,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(Q,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_QP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_2_P(Q,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(Q,2,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_Q(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(Q,2,X); \
|
||||
_FP_PACK_RAW_2(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_QP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(Q,2,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_2_P(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_Q(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(Q,2,X); \
|
||||
_FP_PACK_RAW_2(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_QP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(Q,2,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_2_P(Q,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_ISSIGNAN_Q(X) _FP_ISSIGNAN(Q,2,X)
|
||||
#define FP_NEG_Q(R,X) _FP_NEG(Q,2,R,X)
|
||||
#define FP_ADD_Q(R,X,Y) _FP_ADD(Q,2,R,X,Y)
|
||||
#define FP_SUB_Q(R,X,Y) _FP_SUB(Q,2,R,X,Y)
|
||||
#define FP_MUL_Q(R,X,Y) _FP_MUL(Q,2,R,X,Y)
|
||||
#define FP_DIV_Q(R,X,Y) _FP_DIV(Q,2,R,X,Y)
|
||||
#define FP_SQRT_Q(R,X) _FP_SQRT(Q,2,R,X)
|
||||
#define _FP_SQRT_MEAT_Q(R,S,T,X,Q) _FP_SQRT_MEAT_2(R,S,T,X,Q)
|
||||
|
||||
#define FP_CMP_Q(r,X,Y,un) _FP_CMP(Q,2,r,X,Y,un)
|
||||
#define FP_CMP_EQ_Q(r,X,Y) _FP_CMP_EQ(Q,2,r,X,Y)
|
||||
#define FP_CMP_UNORD_Q(r,X,Y) _FP_CMP_UNORD(Q,2,r,X,Y)
|
||||
|
||||
#define FP_TO_INT_Q(r,X,rsz,rsg) _FP_TO_INT(Q,2,r,X,rsz,rsg)
|
||||
#define FP_FROM_INT_Q(X,r,rs,rt) _FP_FROM_INT(Q,2,X,r,rs,rt)
|
||||
|
||||
#define _FP_FRAC_HIGH_Q(X) _FP_FRAC_HIGH_2(X)
|
||||
#define _FP_FRAC_HIGH_RAW_Q(X) _FP_FRAC_HIGH_2(X)
|
||||
|
||||
#endif /* not _FP_W_TYPE_SIZE < 64 */
|
||||
69
ExternalApps/RadioSet/main/Source/soft-fp/sfp-machine.h
Normal file
69
ExternalApps/RadioSet/main/Source/soft-fp/sfp-machine.h
Normal file
@ -0,0 +1,69 @@
|
||||
#define _FP_W_TYPE_SIZE 32
|
||||
#define _FP_W_TYPE unsigned long
|
||||
#define _FP_WS_TYPE signed long
|
||||
#define _FP_I_TYPE long
|
||||
|
||||
/* The type of the result of a floating point comparison. This must
|
||||
match `__libgcc_cmp_return__' in GCC for the target. */
|
||||
typedef int __gcc_CMPtype __attribute__ ((mode (__libgcc_cmp_return__)));
|
||||
#define CMPtype __gcc_CMPtype
|
||||
|
||||
#define _FP_MUL_MEAT_S(R,X,Y) \
|
||||
_FP_MUL_MEAT_1_wide(_FP_WFRACBITS_S,R,X,Y,umul_ppmm)
|
||||
#define _FP_MUL_MEAT_D(R,X,Y) \
|
||||
_FP_MUL_MEAT_2_wide(_FP_WFRACBITS_D,R,X,Y,umul_ppmm)
|
||||
#define _FP_MUL_MEAT_Q(R,X,Y) \
|
||||
_FP_MUL_MEAT_4_wide(_FP_WFRACBITS_Q,R,X,Y,umul_ppmm)
|
||||
|
||||
#define _FP_DIV_MEAT_S(R,X,Y) _FP_DIV_MEAT_1_loop(S,R,X,Y)
|
||||
#define _FP_DIV_MEAT_D(R,X,Y) _FP_DIV_MEAT_2_udiv(D,R,X,Y)
|
||||
#define _FP_DIV_MEAT_Q(R,X,Y) _FP_DIV_MEAT_4_udiv(Q,R,X,Y)
|
||||
|
||||
/* According to RTABI, QNAN is only with the most significant bit of the
|
||||
significand set, and all other significand bits zero. */
|
||||
#define _FP_NANFRAC_H _FP_QNANBIT_H
|
||||
#define _FP_NANFRAC_S _FP_QNANBIT_S
|
||||
#define _FP_NANFRAC_D _FP_QNANBIT_D, 0
|
||||
#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0, 0, 0
|
||||
#define _FP_NANSIGN_H 0
|
||||
#define _FP_NANSIGN_S 0
|
||||
#define _FP_NANSIGN_D 0
|
||||
#define _FP_NANSIGN_Q 0
|
||||
|
||||
#define _FP_KEEPNANFRACP 1
|
||||
#define _FP_QNANNEGATEDP 0
|
||||
|
||||
/* Someone please check this. */
|
||||
#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
|
||||
do { \
|
||||
if ((_FP_FRAC_HIGH_RAW_##fs(X) & _FP_QNANBIT_##fs) \
|
||||
&& !(_FP_FRAC_HIGH_RAW_##fs(Y) & _FP_QNANBIT_##fs)) \
|
||||
{ \
|
||||
R##_s = Y##_s; \
|
||||
_FP_FRAC_COPY_##wc(R,Y); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
R##_s = X##_s; \
|
||||
_FP_FRAC_COPY_##wc(R,X); \
|
||||
} \
|
||||
R##_c = FP_CLS_NAN; \
|
||||
} while (0)
|
||||
|
||||
#define _FP_TININESS_AFTER_ROUNDING 0
|
||||
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#define __BIG_ENDIAN 4321
|
||||
|
||||
#if defined __8267EB__
|
||||
# define __BYTE_ORDER __BIG_ENDIAN
|
||||
#else
|
||||
# define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#endif
|
||||
|
||||
#define NO_ASM 1
|
||||
|
||||
/* Define ALIASNAME as a strong alias for NAME. */
|
||||
# define strong_alias(name, aliasname) _strong_alias(name, aliasname)
|
||||
# define _strong_alias(name, aliasname) \
|
||||
extern __typeof (name) aliasname __attribute__ ((alias (#name)));
|
||||
150
ExternalApps/RadioSet/main/Source/soft-fp/single.h
Normal file
150
ExternalApps/RadioSet/main/Source/soft-fp/single.h
Normal file
@ -0,0 +1,150 @@
|
||||
/* Software floating-point emulation.
|
||||
Definitions for IEEE Single Precision.
|
||||
Copyright (C) 1997,1998,1999,2006,2012 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#if _FP_W_TYPE_SIZE < 32
|
||||
#error "Here's a nickel kid. Go buy yourself a real computer."
|
||||
#endif
|
||||
|
||||
#define _FP_FRACTBITS_S _FP_W_TYPE_SIZE
|
||||
|
||||
#define _FP_FRACBITS_S 24
|
||||
#define _FP_FRACXBITS_S (_FP_FRACTBITS_S - _FP_FRACBITS_S)
|
||||
#define _FP_WFRACBITS_S (_FP_WORKBITS + _FP_FRACBITS_S)
|
||||
#define _FP_WFRACXBITS_S (_FP_FRACTBITS_S - _FP_WFRACBITS_S)
|
||||
#define _FP_EXPBITS_S 8
|
||||
#define _FP_EXPBIAS_S 127
|
||||
#define _FP_EXPMAX_S 255
|
||||
#define _FP_QNANBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2))
|
||||
#define _FP_QNANBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-2+_FP_WORKBITS))
|
||||
#define _FP_IMPLBIT_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1))
|
||||
#define _FP_IMPLBIT_SH_S ((_FP_W_TYPE)1 << (_FP_FRACBITS_S-1+_FP_WORKBITS))
|
||||
#define _FP_OVERFLOW_S ((_FP_W_TYPE)1 << (_FP_WFRACBITS_S))
|
||||
|
||||
/* The implementation of _FP_MUL_MEAT_S and _FP_DIV_MEAT_S should be
|
||||
chosen by the target machine. */
|
||||
|
||||
typedef float SFtype __attribute__((mode(SF)));
|
||||
|
||||
union _FP_UNION_S
|
||||
{
|
||||
SFtype flt;
|
||||
struct _FP_STRUCT_LAYOUT {
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
unsigned sign : 1;
|
||||
unsigned exp : _FP_EXPBITS_S;
|
||||
unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
|
||||
#else
|
||||
unsigned frac : _FP_FRACBITS_S - (_FP_IMPLBIT_S != 0);
|
||||
unsigned exp : _FP_EXPBITS_S;
|
||||
unsigned sign : 1;
|
||||
#endif
|
||||
} bits __attribute__((packed));
|
||||
};
|
||||
|
||||
#define FP_DECL_S(X) _FP_DECL(1,X)
|
||||
#define FP_UNPACK_RAW_S(X,val) _FP_UNPACK_RAW_1(S,X,val)
|
||||
#define FP_UNPACK_RAW_SP(X,val) _FP_UNPACK_RAW_1_P(S,X,val)
|
||||
#define FP_PACK_RAW_S(val,X) _FP_PACK_RAW_1(S,val,X)
|
||||
#define FP_PACK_RAW_SP(val,X) \
|
||||
do { \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_1_P(S,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_S(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1(S,X,val); \
|
||||
_FP_UNPACK_CANONICAL(S,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1_P(S,X,val); \
|
||||
_FP_UNPACK_CANONICAL(S,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_S(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1(S,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(S,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_UNPACK_SEMIRAW_SP(X,val) \
|
||||
do { \
|
||||
_FP_UNPACK_RAW_1_P(S,X,val); \
|
||||
_FP_UNPACK_SEMIRAW(S,1,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_S(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(S,1,X); \
|
||||
_FP_PACK_RAW_1(S,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_CANONICAL(S,1,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_1_P(S,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_S(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(S,1,X); \
|
||||
_FP_PACK_RAW_1(S,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_PACK_SEMIRAW_SP(val,X) \
|
||||
do { \
|
||||
_FP_PACK_SEMIRAW(S,1,X); \
|
||||
if (!FP_INHIBIT_RESULTS) \
|
||||
_FP_PACK_RAW_1_P(S,val,X); \
|
||||
} while (0)
|
||||
|
||||
#define FP_ISSIGNAN_S(X) _FP_ISSIGNAN(S,1,X)
|
||||
#define FP_NEG_S(R,X) _FP_NEG(S,1,R,X)
|
||||
#define FP_ADD_S(R,X,Y) _FP_ADD(S,1,R,X,Y)
|
||||
#define FP_SUB_S(R,X,Y) _FP_SUB(S,1,R,X,Y)
|
||||
#define FP_MUL_S(R,X,Y) _FP_MUL(S,1,R,X,Y)
|
||||
#define FP_DIV_S(R,X,Y) _FP_DIV(S,1,R,X,Y)
|
||||
#define FP_SQRT_S(R,X) _FP_SQRT(S,1,R,X)
|
||||
#define _FP_SQRT_MEAT_S(R,S,T,X,Q) _FP_SQRT_MEAT_1(R,S,T,X,Q)
|
||||
|
||||
#define FP_CMP_S(r,X,Y,un) _FP_CMP(S,1,r,X,Y,un)
|
||||
#define FP_CMP_EQ_S(r,X,Y) _FP_CMP_EQ(S,1,r,X,Y)
|
||||
#define FP_CMP_UNORD_S(r,X,Y) _FP_CMP_UNORD(S,1,r,X,Y)
|
||||
|
||||
#define FP_TO_INT_S(r,X,rsz,rsg) _FP_TO_INT(S,1,r,X,rsz,rsg)
|
||||
#define FP_FROM_INT_S(X,r,rs,rt) _FP_FROM_INT(S,1,X,r,rs,rt)
|
||||
|
||||
#define _FP_FRAC_HIGH_S(X) _FP_FRAC_HIGH_1(X)
|
||||
#define _FP_FRAC_HIGH_RAW_S(X) _FP_FRAC_HIGH_1(X)
|
||||
229
ExternalApps/RadioSet/main/Source/soft-fp/soft-fp.h
Normal file
229
ExternalApps/RadioSet/main/Source/soft-fp/soft-fp.h
Normal file
@ -0,0 +1,229 @@
|
||||
/* Software floating-point emulation.
|
||||
Copyright (C) 1997,1998,1999,2000,2002,2003,2005,2006,2007,2012
|
||||
Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com),
|
||||
Jakub Jelinek (jj@ultra.linux.cz),
|
||||
David S. Miller (davem@redhat.com) and
|
||||
Peter Maydell (pmaydell@chiark.greenend.org.uk).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef SOFT_FP_H
|
||||
#define SOFT_FP_H
|
||||
|
||||
#ifdef _LIBC
|
||||
#include <sfp-machine.h>
|
||||
#else
|
||||
#include "sfp-machine.h"
|
||||
#endif
|
||||
|
||||
/* Allow sfp-machine to have its own byte order definitions. */
|
||||
#ifndef __BYTE_ORDER
|
||||
#ifdef _LIBC
|
||||
#include <endian.h>
|
||||
#else
|
||||
#error "endianness not defined by sfp-machine.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define _FP_WORKBITS 3
|
||||
#define _FP_WORK_LSB ((_FP_W_TYPE)1 << 3)
|
||||
#define _FP_WORK_ROUND ((_FP_W_TYPE)1 << 2)
|
||||
#define _FP_WORK_GUARD ((_FP_W_TYPE)1 << 1)
|
||||
#define _FP_WORK_STICKY ((_FP_W_TYPE)1 << 0)
|
||||
|
||||
#ifndef FP_RND_NEAREST
|
||||
# define FP_RND_NEAREST 0
|
||||
# define FP_RND_ZERO 1
|
||||
# define FP_RND_PINF 2
|
||||
# define FP_RND_MINF 3
|
||||
#endif
|
||||
#ifndef FP_ROUNDMODE
|
||||
# define FP_ROUNDMODE FP_RND_NEAREST
|
||||
#endif
|
||||
|
||||
/* By default don't care about exceptions. */
|
||||
#ifndef FP_EX_INVALID
|
||||
#define FP_EX_INVALID 0
|
||||
#endif
|
||||
#ifndef FP_EX_OVERFLOW
|
||||
#define FP_EX_OVERFLOW 0
|
||||
#endif
|
||||
#ifndef FP_EX_UNDERFLOW
|
||||
#define FP_EX_UNDERFLOW 0
|
||||
#endif
|
||||
#ifndef FP_EX_DIVZERO
|
||||
#define FP_EX_DIVZERO 0
|
||||
#endif
|
||||
#ifndef FP_EX_INEXACT
|
||||
#define FP_EX_INEXACT 0
|
||||
#endif
|
||||
#ifndef FP_EX_DENORM
|
||||
#define FP_EX_DENORM 0
|
||||
#endif
|
||||
|
||||
/* _FP_STRUCT_LAYOUT may be defined as an attribute to determine the
|
||||
struct layout variant used for structures where bit-fields are used
|
||||
to access specific parts of binary floating-point numbers. This is
|
||||
required for systems where the default ABI uses struct layout with
|
||||
differences in how consecutive bit-fields are laid out from the
|
||||
default expected by soft-fp. */
|
||||
#ifndef _FP_STRUCT_LAYOUT
|
||||
#define _FP_STRUCT_LAYOUT
|
||||
#endif
|
||||
|
||||
#ifdef _FP_DECL_EX
|
||||
#define FP_DECL_EX \
|
||||
int _fex = 0; \
|
||||
_FP_DECL_EX
|
||||
#else
|
||||
#define FP_DECL_EX int _fex = 0
|
||||
#endif
|
||||
|
||||
#ifndef FP_INIT_ROUNDMODE
|
||||
#define FP_INIT_ROUNDMODE do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef FP_HANDLE_EXCEPTIONS
|
||||
#define FP_HANDLE_EXCEPTIONS do {} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef FP_INHIBIT_RESULTS
|
||||
/* By default we write the results always.
|
||||
* sfp-machine may override this and e.g.
|
||||
* check if some exceptions are unmasked
|
||||
* and inhibit it in such a case.
|
||||
*/
|
||||
#define FP_INHIBIT_RESULTS 0
|
||||
#endif
|
||||
|
||||
#define FP_SET_EXCEPTION(ex) \
|
||||
_fex |= (ex)
|
||||
|
||||
#define FP_UNSET_EXCEPTION(ex) \
|
||||
_fex &= ~(ex)
|
||||
|
||||
#define FP_CLEAR_EXCEPTIONS \
|
||||
_fex = 0
|
||||
|
||||
#define FP_CUR_EXCEPTIONS \
|
||||
(_fex)
|
||||
|
||||
#ifndef FP_TRAPPING_EXCEPTIONS
|
||||
#define FP_TRAPPING_EXCEPTIONS 0
|
||||
#endif
|
||||
|
||||
#define _FP_ROUND_NEAREST(wc, X) \
|
||||
do { \
|
||||
if ((_FP_FRAC_LOW_##wc(X) & 15) != _FP_WORK_ROUND) \
|
||||
_FP_FRAC_ADDI_##wc(X, _FP_WORK_ROUND); \
|
||||
} while (0)
|
||||
|
||||
#define _FP_ROUND_ZERO(wc, X) (void)0
|
||||
|
||||
#define _FP_ROUND_PINF(wc, X) \
|
||||
do { \
|
||||
if (!X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
|
||||
_FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
|
||||
} while (0)
|
||||
|
||||
#define _FP_ROUND_MINF(wc, X) \
|
||||
do { \
|
||||
if (X##_s && (_FP_FRAC_LOW_##wc(X) & 7)) \
|
||||
_FP_FRAC_ADDI_##wc(X, _FP_WORK_LSB); \
|
||||
} while (0)
|
||||
|
||||
#define _FP_ROUND(wc, X) \
|
||||
do { \
|
||||
if (_FP_FRAC_LOW_##wc(X) & 7) \
|
||||
FP_SET_EXCEPTION(FP_EX_INEXACT); \
|
||||
switch (FP_ROUNDMODE) \
|
||||
{ \
|
||||
case FP_RND_NEAREST: \
|
||||
_FP_ROUND_NEAREST(wc,X); \
|
||||
break; \
|
||||
case FP_RND_ZERO: \
|
||||
_FP_ROUND_ZERO(wc,X); \
|
||||
break; \
|
||||
case FP_RND_PINF: \
|
||||
_FP_ROUND_PINF(wc,X); \
|
||||
break; \
|
||||
case FP_RND_MINF: \
|
||||
_FP_ROUND_MINF(wc,X); \
|
||||
break; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define FP_CLS_NORMAL 0
|
||||
#define FP_CLS_ZERO 1
|
||||
#define FP_CLS_INF 2
|
||||
#define FP_CLS_NAN 3
|
||||
|
||||
#define _FP_CLS_COMBINE(x,y) (((x) << 2) | (y))
|
||||
|
||||
#include "op-1.h"
|
||||
#include "op-2.h"
|
||||
#include "op-4.h"
|
||||
#include "op-8.h"
|
||||
#include "op-common.h"
|
||||
|
||||
/* Sigh. Silly things longlong.h needs. */
|
||||
#define UWtype _FP_W_TYPE
|
||||
#define W_TYPE_SIZE _FP_W_TYPE_SIZE
|
||||
|
||||
typedef int QItype __attribute__((mode(QI)));
|
||||
typedef int SItype __attribute__((mode(SI)));
|
||||
typedef int DItype __attribute__((mode(DI)));
|
||||
typedef unsigned int UQItype __attribute__((mode(QI)));
|
||||
typedef unsigned int USItype __attribute__((mode(SI)));
|
||||
typedef unsigned int UDItype __attribute__((mode(DI)));
|
||||
#if _FP_W_TYPE_SIZE == 32
|
||||
typedef unsigned int UHWtype __attribute__((mode(HI)));
|
||||
#elif _FP_W_TYPE_SIZE == 64
|
||||
typedef USItype UHWtype;
|
||||
#endif
|
||||
|
||||
#ifndef CMPtype
|
||||
#define CMPtype int
|
||||
#endif
|
||||
|
||||
#define SI_BITS (__CHAR_BIT__ * (int)sizeof(SItype))
|
||||
#define DI_BITS (__CHAR_BIT__ * (int)sizeof(DItype))
|
||||
|
||||
#ifndef umul_ppmm
|
||||
#ifdef _LIBC
|
||||
#include <stdlib/longlong.h>
|
||||
#else
|
||||
#include "longlong.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _LIBC
|
||||
#include <stdlib.h>
|
||||
#else
|
||||
extern void abort (void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
47
ExternalApps/RadioSet/main/Source/soft-fp/sqrtdf2.c
Normal file
47
ExternalApps/RadioSet/main/Source/soft-fp/sqrtdf2.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Software floating-point emulation.
|
||||
Return sqrt(a)
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __sqrtdf2(DFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_D(A, a);
|
||||
FP_SQRT_D(R, A);
|
||||
FP_PACK_D(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
47
ExternalApps/RadioSet/main/Source/soft-fp/sqrtsf2.c
Normal file
47
ExternalApps/RadioSet/main/Source/soft-fp/sqrtsf2.c
Normal file
@ -0,0 +1,47 @@
|
||||
/* Software floating-point emulation.
|
||||
Return sqrt(a)
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __sqrtsf2(SFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_S(A, a);
|
||||
FP_SQRT_S(R, A);
|
||||
FP_PACK_S(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
48
ExternalApps/RadioSet/main/Source/soft-fp/subdf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/subdf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a - b
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
DFtype __subdf3(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A); FP_DECL_D(B); FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_SEMIRAW_D(A, a);
|
||||
FP_UNPACK_SEMIRAW_D(B, b);
|
||||
FP_SUB_D(R, A, B);
|
||||
FP_PACK_SEMIRAW_D(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
48
ExternalApps/RadioSet/main/Source/soft-fp/subsf3.c
Normal file
48
ExternalApps/RadioSet/main/Source/soft-fp/subsf3.c
Normal file
@ -0,0 +1,48 @@
|
||||
/* Software floating-point emulation.
|
||||
Return a - b
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
SFtype __subsf3(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_S(A); FP_DECL_S(B); FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_SEMIRAW_S(A, a);
|
||||
FP_UNPACK_SEMIRAW_S(B, b);
|
||||
FP_SUB_S(R, A, B);
|
||||
FP_PACK_SEMIRAW_S(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
53
ExternalApps/RadioSet/main/Source/soft-fp/truncdfsf2.c
Normal file
53
ExternalApps/RadioSet/main/Source/soft-fp/truncdfsf2.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* Software floating-point emulation.
|
||||
Truncate IEEE double into IEEE single
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
#include "double.h"
|
||||
|
||||
SFtype __truncdfsf2(DFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_D(A);
|
||||
FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_SEMIRAW_D(A, a);
|
||||
#if _FP_W_TYPE_SIZE < _FP_FRACBITS_D
|
||||
FP_TRUNC(S,D,1,2,R,A);
|
||||
#else
|
||||
FP_TRUNC(S,D,1,1,R,A);
|
||||
#endif
|
||||
FP_PACK_SEMIRAW_S(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
53
ExternalApps/RadioSet/main/Source/soft-fp/trunctfdf2.c
Normal file
53
ExternalApps/RadioSet/main/Source/soft-fp/trunctfdf2.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* Software floating-point emulation.
|
||||
Truncate IEEE quad into IEEE double
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
#include "quad.h"
|
||||
|
||||
DFtype __trunctfdf2(TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q(A);
|
||||
FP_DECL_D(R);
|
||||
DFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_SEMIRAW_Q(A, a);
|
||||
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
|
||||
FP_TRUNC(D,Q,2,4,R,A);
|
||||
#else
|
||||
FP_TRUNC(D,Q,1,2,R,A);
|
||||
#endif
|
||||
FP_PACK_SEMIRAW_D(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
53
ExternalApps/RadioSet/main/Source/soft-fp/trunctfsf2.c
Normal file
53
ExternalApps/RadioSet/main/Source/soft-fp/trunctfsf2.c
Normal file
@ -0,0 +1,53 @@
|
||||
/* Software floating-point emulation.
|
||||
Truncate IEEE quad into IEEE single
|
||||
Copyright (C) 1997,1999,2006 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Richard Henderson (rth@cygnus.com) and
|
||||
Jakub Jelinek (jj@ultra.linux.cz).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
#include "quad.h"
|
||||
|
||||
SFtype __trunctfsf2(TFtype a)
|
||||
{
|
||||
FP_DECL_EX;
|
||||
FP_DECL_Q(A);
|
||||
FP_DECL_S(R);
|
||||
SFtype r;
|
||||
|
||||
FP_INIT_ROUNDMODE;
|
||||
FP_UNPACK_SEMIRAW_Q(A, a);
|
||||
#if (2 * _FP_W_TYPE_SIZE) < _FP_FRACBITS_Q
|
||||
FP_TRUNC(S,Q,1,4,R,A);
|
||||
#else
|
||||
FP_TRUNC(S,Q,1,2,R,A);
|
||||
#endif
|
||||
FP_PACK_SEMIRAW_S(r, R);
|
||||
FP_HANDLE_EXCEPTIONS;
|
||||
|
||||
return r;
|
||||
}
|
||||
43
ExternalApps/RadioSet/main/Source/soft-fp/unorddf2.c
Normal file
43
ExternalApps/RadioSet/main/Source/soft-fp/unorddf2.c
Normal file
@ -0,0 +1,43 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 1 iff a or b is a NaN, 0 otherwise.
|
||||
Copyright (C) 2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Joseph Myers (joseph@codesourcery.com).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "double.h"
|
||||
|
||||
CMPtype __unorddf2(DFtype a, DFtype b)
|
||||
{
|
||||
FP_DECL_D(A); FP_DECL_D(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_D(A, a);
|
||||
FP_UNPACK_RAW_D(B, b);
|
||||
FP_CMP_UNORD_D(r, A, B);
|
||||
|
||||
return r;
|
||||
}
|
||||
44
ExternalApps/RadioSet/main/Source/soft-fp/unordsf2.c
Normal file
44
ExternalApps/RadioSet/main/Source/soft-fp/unordsf2.c
Normal file
@ -0,0 +1,44 @@
|
||||
/* Software floating-point emulation.
|
||||
Return 1 iff a or b is a NaN, 0 otherwise.
|
||||
Copyright (C) 2006,2007 Free Software Foundation, Inc.
|
||||
This file is part of the GNU C Library.
|
||||
Contributed by Joseph Myers (joseph@codesourcery.com).
|
||||
|
||||
The GNU C Library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
In addition to the permissions in the GNU Lesser General Public
|
||||
License, the Free Software Foundation gives you unlimited
|
||||
permission to link the compiled version of this file into
|
||||
combinations with other programs, and to distribute those
|
||||
combinations without any restriction coming from the use of this
|
||||
file. (The Lesser General Public License restrictions do apply in
|
||||
other respects; for example, they cover modification of the file,
|
||||
and distribution when not linked into a combine executable.)
|
||||
|
||||
The GNU C Library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with the GNU C Library; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "soft-fp.h"
|
||||
#include "single.h"
|
||||
|
||||
CMPtype __unordsf2(SFtype a, SFtype b)
|
||||
{
|
||||
FP_DECL_S(A);
|
||||
FP_DECL_S(B);
|
||||
CMPtype r;
|
||||
|
||||
FP_UNPACK_RAW_S(A, a);
|
||||
FP_UNPACK_RAW_S(B, b);
|
||||
FP_CMP_UNORD_S(r, A, B);
|
||||
|
||||
return r;
|
||||
}
|
||||
13
ExternalApps/RadioSet/manifest.properties
Normal file
13
ExternalApps/RadioSet/manifest.properties
Normal file
@ -0,0 +1,13 @@
|
||||
[manifest]
|
||||
version=0.1
|
||||
[target]
|
||||
sdk=0.6.0-SNAPSHOT1
|
||||
platforms=esp32,esp32s3
|
||||
[app]
|
||||
id=com.d49406.RadioSet
|
||||
version=0.0.1
|
||||
name=Radio Terminal
|
||||
description=Receive and transmit radio packages
|
||||
[author]
|
||||
name=Dominic Hoeglinger
|
||||
website=https://github.com/ByteWelder/Tactility
|
||||
637
ExternalApps/RadioSet/tactility.py
Normal file
637
ExternalApps/RadioSet/tactility.py
Normal file
@ -0,0 +1,637 @@
|
||||
import configparser
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import shutil
|
||||
import sys
|
||||
import subprocess
|
||||
import time
|
||||
import urllib.request
|
||||
import zipfile
|
||||
import requests
|
||||
import tarfile
|
||||
import shutil
|
||||
import configparser
|
||||
|
||||
ttbuild_path = ".tactility"
|
||||
ttbuild_version = "2.1.1"
|
||||
ttbuild_cdn = "https://cdn.tactility.one"
|
||||
ttbuild_sdk_json_validity = 3600 # seconds
|
||||
ttport = 6666
|
||||
verbose = False
|
||||
use_local_sdk = False
|
||||
valid_platforms = ["esp32", "esp32s3"]
|
||||
|
||||
spinner_pattern = [
|
||||
"⠋",
|
||||
"⠙",
|
||||
"⠹",
|
||||
"⠸",
|
||||
"⠼",
|
||||
"⠴",
|
||||
"⠦",
|
||||
"⠧",
|
||||
"⠇",
|
||||
"⠏"
|
||||
]
|
||||
|
||||
if sys.platform == "win32":
|
||||
shell_color_red = ""
|
||||
shell_color_orange = ""
|
||||
shell_color_green = ""
|
||||
shell_color_purple = ""
|
||||
shell_color_cyan = ""
|
||||
shell_color_reset = ""
|
||||
else:
|
||||
shell_color_red = "\033[91m"
|
||||
shell_color_orange = "\033[93m"
|
||||
shell_color_green = "\033[32m"
|
||||
shell_color_purple = "\033[35m"
|
||||
shell_color_cyan = "\033[36m"
|
||||
shell_color_reset = "\033[m"
|
||||
|
||||
def print_help():
|
||||
print("Usage: python tactility.py [action] [options]")
|
||||
print("")
|
||||
print("Actions:")
|
||||
print(" build [esp32,esp32s3] Build the app. Optionally specify a platform.")
|
||||
print(" esp32: ESP32")
|
||||
print(" esp32s3: ESP32 S3")
|
||||
print(" clean Clean the build folders")
|
||||
print(" clearcache Clear the SDK cache")
|
||||
print(" updateself Update this tool")
|
||||
print(" run [ip] Run the application")
|
||||
print(" install [ip] Install the application")
|
||||
print(" uninstall [ip] Uninstall the application")
|
||||
print(" bir [ip] [esp32,esp32s3] Build, install then run. Optionally specify a platform.")
|
||||
print(" brrr [ip] [esp32,esp32s3] Functionally the same as \"bir\", but \"app goes brrr\" meme variant.")
|
||||
print("")
|
||||
print("Options:")
|
||||
print(" --help Show this commandline info")
|
||||
print(" --local-sdk Use SDK specified by environment variable TACTILITY_SDK_PATH")
|
||||
print(" --skip-build Run everything except the idf.py/CMake commands")
|
||||
print(" --verbose Show extra console output")
|
||||
|
||||
# region Core
|
||||
|
||||
def download_file(url, filepath):
|
||||
global verbose
|
||||
if verbose:
|
||||
print(f"Downloading from {url} to {filepath}")
|
||||
request = urllib.request.Request(
|
||||
url,
|
||||
data=None,
|
||||
headers={
|
||||
"User-Agent": f"Tactility Build Tool {ttbuild_version}"
|
||||
}
|
||||
)
|
||||
try:
|
||||
response = urllib.request.urlopen(request)
|
||||
file = open(filepath, mode="wb")
|
||||
file.write(response.read())
|
||||
file.close()
|
||||
return True
|
||||
except OSError as error:
|
||||
if verbose:
|
||||
print_error(f"Failed to fetch URL {url}\n{error}")
|
||||
return False
|
||||
|
||||
def print_warning(message):
|
||||
print(f"{shell_color_orange}WARNING: {message}{shell_color_reset}")
|
||||
|
||||
def print_error(message):
|
||||
print(f"{shell_color_red}ERROR: {message}{shell_color_reset}")
|
||||
|
||||
def exit_with_error(message):
|
||||
print_error(message)
|
||||
sys.exit(1)
|
||||
|
||||
def get_url(ip, path):
|
||||
return f"http://{ip}:{ttport}{path}"
|
||||
|
||||
def read_properties_file(path):
|
||||
config = configparser.RawConfigParser()
|
||||
config.read(path)
|
||||
return config
|
||||
|
||||
#endregion Core
|
||||
|
||||
#region SDK helpers
|
||||
|
||||
def read_sdk_json():
|
||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
||||
json_file = open(json_file_path)
|
||||
return json.load(json_file)
|
||||
|
||||
def get_sdk_dir(version, platform):
|
||||
global use_local_sdk
|
||||
if use_local_sdk:
|
||||
return os.environ.get("TACTILITY_SDK_PATH")
|
||||
else:
|
||||
global ttbuild_cdn
|
||||
return os.path.join(ttbuild_path, f"{version}-{platform}", "TactilitySDK")
|
||||
|
||||
def get_sdk_root_dir(version, platform):
|
||||
global ttbuild_cdn
|
||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||
|
||||
def get_sdk_url(version, platform):
|
||||
global ttbuild_cdn
|
||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
||||
|
||||
def sdk_exists(version, platform):
|
||||
sdk_dir = get_sdk_dir(version, platform)
|
||||
return os.path.isdir(sdk_dir)
|
||||
|
||||
def should_update_sdk_json():
|
||||
global ttbuild_cdn
|
||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
||||
if os.path.exists(json_filepath):
|
||||
json_modification_time = os.path.getmtime(json_filepath)
|
||||
now = time.time()
|
||||
global ttbuild_sdk_json_validity
|
||||
minimum_seconds_difference = ttbuild_sdk_json_validity
|
||||
return (now - json_modification_time) > minimum_seconds_difference
|
||||
else:
|
||||
return True
|
||||
|
||||
def update_sdk_json():
|
||||
global ttbuild_cdn, ttbuild_path
|
||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
||||
return download_file(json_url, json_filepath)
|
||||
|
||||
def should_fetch_sdkconfig_files(platform_targets):
|
||||
for platform in platform_targets:
|
||||
sdkconfig_filename = f"sdkconfig.app.{platform}"
|
||||
if not os.path.exists(os.path.join(ttbuild_path, sdkconfig_filename)):
|
||||
return True
|
||||
return False
|
||||
|
||||
def fetch_sdkconfig_files(platform_targets):
|
||||
for platform in platform_targets:
|
||||
sdkconfig_filename = f"sdkconfig.app.{platform}"
|
||||
target_path = os.path.join(ttbuild_path, sdkconfig_filename)
|
||||
if not download_file(f"{ttbuild_cdn}/{sdkconfig_filename}", target_path):
|
||||
exit_with_error(f"Failed to download sdkconfig file for {platform}")
|
||||
|
||||
#endregion SDK helpers
|
||||
|
||||
#region Validation
|
||||
|
||||
def validate_environment():
|
||||
if os.environ.get("IDF_PATH") is None:
|
||||
exit_with_error("Cannot find the Espressif IDF SDK. Ensure it is installed and that it is activated via $PATH_TO_IDF_SDK/export.sh")
|
||||
if not os.path.exists("manifest.properties"):
|
||||
exit_with_error("manifest.properties not found")
|
||||
if use_local_sdk == False and os.environ.get("TACTILITY_SDK_PATH") is not None:
|
||||
print_warning("TACTILITY_SDK_PATH is set, but will be ignored by this command.")
|
||||
print_warning("If you want to use it, use the 'build local' parameters.")
|
||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||
|
||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
||||
version_map = sdk_json["versions"]
|
||||
if not sdk_version in version_map:
|
||||
exit_with_error(f"Version not found: {sdk_version}")
|
||||
version_data = version_map[sdk_version]
|
||||
available_platforms = version_data["platforms"]
|
||||
for desired_platform in platforms_to_build:
|
||||
if not desired_platform in available_platforms:
|
||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
||||
|
||||
def validate_self(sdk_json):
|
||||
if not "toolVersion" in sdk_json:
|
||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||
if not "toolCompatibility" in sdk_json:
|
||||
exit_with_error("Server returned invalid SDK data format (toolCompatibility not found)")
|
||||
if not "toolDownloadUrl" in sdk_json:
|
||||
exit_with_error("Server returned invalid SDK data format (toolDownloadUrl not found)")
|
||||
tool_version = sdk_json["toolVersion"]
|
||||
tool_compatibility = sdk_json["toolCompatibility"]
|
||||
if tool_version != ttbuild_version:
|
||||
print_warning(f"New version available: {tool_version} (currently using {ttbuild_version})")
|
||||
print_warning(f"Run 'tactility.py updateself' to update.")
|
||||
if re.search(tool_compatibility, ttbuild_version) is None:
|
||||
print_error("The tool is not compatible anymore.")
|
||||
print_error("Run 'tactility.py updateself' to update.")
|
||||
sys.exit(1)
|
||||
|
||||
#endregion Validation
|
||||
|
||||
#region Manifest
|
||||
|
||||
def read_manifest():
|
||||
return read_properties_file("manifest.properties")
|
||||
|
||||
def validate_manifest(manifest):
|
||||
# [manifest]
|
||||
if not "manifest" in manifest:
|
||||
exit_with_error("Invalid manifest format: [manifest] not found")
|
||||
if not "version" in manifest["manifest"]:
|
||||
exit_with_error("Invalid manifest format: [manifest] version not found")
|
||||
# [target]
|
||||
if not "target" in manifest:
|
||||
exit_with_error("Invalid manifest format: [target] not found")
|
||||
if not "sdk" in manifest["target"]:
|
||||
exit_with_error("Invalid manifest format: [target] sdk not found")
|
||||
if not "platforms" in manifest["target"]:
|
||||
exit_with_error("Invalid manifest format: [target] platforms not found")
|
||||
# [app]
|
||||
if not "app" in manifest:
|
||||
exit_with_error("Invalid manifest format: [app] not found")
|
||||
if not "id" in manifest["app"]:
|
||||
exit_with_error("Invalid manifest format: [app] id not found")
|
||||
if not "version" in manifest["app"]:
|
||||
exit_with_error("Invalid manifest format: [app] version not found")
|
||||
if not "name" in manifest["app"]:
|
||||
exit_with_error("Invalid manifest format: [app] name not found")
|
||||
if not "description" in manifest["app"]:
|
||||
exit_with_error("Invalid manifest format: [app] description not found")
|
||||
# [author]
|
||||
if not "author" in manifest:
|
||||
exit_with_error("Invalid manifest format: [author] not found")
|
||||
if not "name" in manifest["author"]:
|
||||
exit_with_error("Invalid manifest format: [author] name not found")
|
||||
if not "website" in manifest["author"]:
|
||||
exit_with_error("Invalid manifest format: [author] website not found")
|
||||
|
||||
def is_valid_manifest_platform(manifest, platform):
|
||||
manifest_platforms = manifest["target"]["platforms"].split(",")
|
||||
return platform in manifest_platforms
|
||||
|
||||
def validate_manifest_platform(manifest, platform):
|
||||
if not is_valid_manifest_platform(manifest, platform):
|
||||
exit_with_error(f"Platform {platform} is not available in the manifest.")
|
||||
|
||||
def get_manifest_target_platforms(manifest, requested_platform):
|
||||
if requested_platform == "" or requested_platform is None:
|
||||
return manifest["target"]["platforms"].split(",")
|
||||
else:
|
||||
validate_manifest_platform(manifest, requested_platform)
|
||||
return [requested_platform]
|
||||
|
||||
#endregion Manifest
|
||||
|
||||
#region SDK download
|
||||
|
||||
def sdk_download(version, platform):
|
||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||
sdk_url = get_sdk_url(version, platform)
|
||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||
print(f"Downloading SDK version {version} for {platform}")
|
||||
if download_file(sdk_url, filepath):
|
||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def sdk_download_all(version, platforms):
|
||||
for platform in platforms:
|
||||
if not sdk_exists(version, platform):
|
||||
if not sdk_download(version, platform):
|
||||
return False
|
||||
else:
|
||||
if verbose:
|
||||
print(f"Using cached download for SDK version {version} and platform {platform}")
|
||||
return True
|
||||
|
||||
#endregion SDK download
|
||||
|
||||
#region Building
|
||||
|
||||
def get_cmake_path(platform):
|
||||
return os.path.join("build", f"cmake-build-{platform}")
|
||||
|
||||
def find_elf_file(platform):
|
||||
cmake_dir = get_cmake_path(platform)
|
||||
if os.path.exists(cmake_dir):
|
||||
for file in os.listdir(cmake_dir):
|
||||
if file.endswith(".app.elf"):
|
||||
return os.path.join(cmake_dir, file)
|
||||
return None
|
||||
|
||||
def build_all(version, platforms, skip_build):
|
||||
for platform in platforms:
|
||||
# First build command must be "idf.py build", otherwise it fails to execute "idf.py elf"
|
||||
# We check if the ELF file exists and run the correct command
|
||||
# This can lead to code caching issues, so sometimes a clean build is required
|
||||
if find_elf_file(platform) is None:
|
||||
if not build_first(version, platform, skip_build):
|
||||
break
|
||||
else:
|
||||
if not build_consecutively(version, platform, skip_build):
|
||||
break
|
||||
|
||||
def wait_for_build(process, platform):
|
||||
buffer = []
|
||||
os.set_blocking(process.stdout.fileno(), False)
|
||||
while process.poll() is None:
|
||||
for i in spinner_pattern:
|
||||
time.sleep(0.1)
|
||||
progress_text = f"Building for {platform} {shell_color_cyan}" + str(i) + shell_color_reset
|
||||
sys.stdout.write(progress_text + "\r")
|
||||
while True:
|
||||
line = process.stdout.readline()
|
||||
decoded_line = line.decode("UTF-8")
|
||||
if decoded_line != "":
|
||||
buffer.append(decoded_line)
|
||||
else:
|
||||
break
|
||||
return buffer
|
||||
|
||||
# The first build must call "idf.py build" and consecutive builds must call "idf.py elf" as it finishes faster.
|
||||
# The problem is that the "idf.py build" always results in an error, even though the elf file is created.
|
||||
# The solution is to suppress the error if we find that the elf file was created.
|
||||
def build_first(version, platform, skip_build):
|
||||
sdk_dir = get_sdk_dir(version, platform)
|
||||
if verbose:
|
||||
print(f"Using SDK at {sdk_dir}")
|
||||
os.environ["TACTILITY_SDK_PATH"] = sdk_dir
|
||||
sdkconfig_path = os.path.join(ttbuild_path, f"sdkconfig.app.{platform}")
|
||||
os.system(f"cp {sdkconfig_path} sdkconfig")
|
||||
elf_path = find_elf_file(platform)
|
||||
# Remove previous elf file: re-creation of the file is used to measure if the build succeeded,
|
||||
# as the actual build job will always fail due to technical issues with the elf cmake script
|
||||
if elf_path is not None:
|
||||
os.remove(elf_path)
|
||||
if skip_build:
|
||||
return True
|
||||
print("Building first build")
|
||||
cmake_path = get_cmake_path(platform)
|
||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as process:
|
||||
build_output = wait_for_build(process, platform)
|
||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||
if process.returncode == 0:
|
||||
print(f"{shell_color_green}Building for {platform} ✅{shell_color_reset}")
|
||||
return True
|
||||
else:
|
||||
if find_elf_file(platform) is None:
|
||||
for line in build_output:
|
||||
print(line, end="")
|
||||
print(f"{shell_color_red}Building for {platform} failed ❌{shell_color_reset}")
|
||||
return False
|
||||
else:
|
||||
print(f"{shell_color_green}Building for {platform} ✅{shell_color_reset}")
|
||||
return True
|
||||
|
||||
def build_consecutively(version, platform, skip_build):
|
||||
sdk_dir = get_sdk_dir(version, platform)
|
||||
if verbose:
|
||||
print(f"Using SDK at {sdk_dir}")
|
||||
os.environ["TACTILITY_SDK_PATH"] = sdk_dir
|
||||
sdkconfig_path = os.path.join(ttbuild_path, f"sdkconfig.app.{platform}")
|
||||
os.system(f"cp {sdkconfig_path} sdkconfig")
|
||||
if skip_build:
|
||||
return True
|
||||
cmake_path = get_cmake_path(platform)
|
||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) as process:
|
||||
build_output = wait_for_build(process, platform)
|
||||
if process.returncode == 0:
|
||||
print(f"{shell_color_green}Building for {platform} ✅{shell_color_reset}")
|
||||
return True
|
||||
else:
|
||||
for line in build_output:
|
||||
print(line, end="")
|
||||
print(f"{shell_color_red}Building for {platform} failed ❌{shell_color_reset}")
|
||||
return False
|
||||
|
||||
#endregion Building
|
||||
|
||||
#region Packaging
|
||||
|
||||
def package_intermediate_manifest(target_path):
|
||||
if not os.path.isfile("manifest.properties"):
|
||||
print_error("manifest.properties not found")
|
||||
return
|
||||
shutil.copy("manifest.properties", os.path.join(target_path, "manifest.properties"))
|
||||
|
||||
def package_intermediate_binaries(target_path, platforms):
|
||||
elf_dir = os.path.join(target_path, "elf")
|
||||
os.makedirs(elf_dir, exist_ok=True)
|
||||
for platform in platforms:
|
||||
elf_path = find_elf_file(platform)
|
||||
if elf_path is None:
|
||||
print_error(f"ELF file not found at {elf_path}")
|
||||
return
|
||||
shutil.copy(elf_path, os.path.join(elf_dir, f"{platform}.elf"))
|
||||
|
||||
def package_intermediate_assets(target_path):
|
||||
if os.path.isdir("assets"):
|
||||
shutil.copytree("assets", os.path.join(target_path, "assets"), dirs_exist_ok=True)
|
||||
|
||||
def package_intermediate(platforms):
|
||||
target_path = os.path.join("build", "package-intermediate")
|
||||
if os.path.isdir(target_path):
|
||||
shutil.rmtree(target_path)
|
||||
os.makedirs(target_path, exist_ok=True)
|
||||
package_intermediate_manifest(target_path)
|
||||
package_intermediate_binaries(target_path, platforms)
|
||||
package_intermediate_assets(target_path)
|
||||
|
||||
def package_name(platforms):
|
||||
elf_path = find_elf_file(platforms[0])
|
||||
elf_base_name = os.path.basename(elf_path).removesuffix(".app.elf")
|
||||
return os.path.join("build", f"{elf_base_name}.app")
|
||||
|
||||
def package_all(platforms):
|
||||
print("Packaging app")
|
||||
package_intermediate(platforms)
|
||||
# Create build/something.app
|
||||
tar_path = package_name(platforms)
|
||||
tar = tarfile.open(tar_path, mode="w", format=tarfile.USTAR_FORMAT)
|
||||
tar.add(os.path.join("build", "package-intermediate"), arcname="")
|
||||
tar.close()
|
||||
|
||||
#endregion Packaging
|
||||
|
||||
def setup_environment():
|
||||
global ttbuild_path
|
||||
os.makedirs(ttbuild_path, exist_ok=True)
|
||||
|
||||
def build_action(manifest, platform_arg):
|
||||
# Environment validation
|
||||
validate_environment()
|
||||
platforms_to_build = get_manifest_target_platforms(manifest, platform_arg)
|
||||
if not use_local_sdk:
|
||||
if should_fetch_sdkconfig_files(platforms_to_build):
|
||||
fetch_sdkconfig_files(platforms_to_build)
|
||||
sdk_json = read_sdk_json()
|
||||
validate_self(sdk_json)
|
||||
if not "versions" in sdk_json:
|
||||
exit_with_error("Version data not found in sdk.json")
|
||||
# Build
|
||||
sdk_version = manifest["target"]["sdk"]
|
||||
if not use_local_sdk:
|
||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||
exit_with_error("Failed to download one or more SDKs")
|
||||
build_all(sdk_version, platforms_to_build, skip_build) # Environment validation
|
||||
if not skip_build:
|
||||
package_all(platforms_to_build)
|
||||
|
||||
def clean_action():
|
||||
if os.path.exists("build"):
|
||||
print(f"Removing build/")
|
||||
shutil.rmtree("build")
|
||||
else:
|
||||
print("Nothing to clean")
|
||||
|
||||
def clear_cache_action():
|
||||
if os.path.exists(ttbuild_path):
|
||||
print(f"Removing {ttbuild_path}/")
|
||||
shutil.rmtree(ttbuild_path)
|
||||
else:
|
||||
print("Nothing to clear")
|
||||
|
||||
def update_self_action():
|
||||
sdk_json = read_sdk_json()
|
||||
tool_download_url = sdk_json["toolDownloadUrl"]
|
||||
if download_file(tool_download_url, "tactility.py"):
|
||||
print("Updated")
|
||||
else:
|
||||
exit_with_error("Update failed")
|
||||
|
||||
def get_device_info(ip):
|
||||
print(f"Getting device info from {ip}")
|
||||
url = get_url(ip, "/info")
|
||||
try:
|
||||
response = requests.get(url)
|
||||
if response.status_code != 200:
|
||||
print_error("Run failed")
|
||||
else:
|
||||
print(response.json())
|
||||
print(f"{shell_color_green}Run successful ✅{shell_color_reset}")
|
||||
except requests.RequestException as e:
|
||||
print(f"Request failed: {e}")
|
||||
|
||||
def run_action(manifest, ip):
|
||||
app_id = manifest["app"]["id"]
|
||||
print(f"Running {app_id} on {ip}")
|
||||
url = get_url(ip, "/app/run")
|
||||
params = {'id': app_id}
|
||||
try:
|
||||
response = requests.post(url, params=params)
|
||||
if response.status_code != 200:
|
||||
print_error("Run failed")
|
||||
else:
|
||||
print(f"{shell_color_green}Run successful ✅{shell_color_reset}")
|
||||
except requests.RequestException as e:
|
||||
print(f"Request failed: {e}")
|
||||
|
||||
def install_action(ip, platforms):
|
||||
for platform in platforms:
|
||||
elf_path = find_elf_file(platform)
|
||||
if elf_path is None:
|
||||
exit_with_error(f"ELF file not built for {platform}")
|
||||
package_path = package_name(platforms)
|
||||
print(f"Installing {package_path} to {ip}")
|
||||
url = get_url(ip, "/app/install")
|
||||
try:
|
||||
# Prepare multipart form data
|
||||
with open(package_path, 'rb') as file:
|
||||
files = {
|
||||
'elf': file
|
||||
}
|
||||
response = requests.put(url, files=files)
|
||||
if response.status_code != 200:
|
||||
print_error("Install failed")
|
||||
else:
|
||||
print(f"{shell_color_green}Installation successful ✅{shell_color_reset}")
|
||||
except requests.RequestException as e:
|
||||
print_error(f"Installation failed: {e}")
|
||||
except IOError as e:
|
||||
print_error(f"File error: {e}")
|
||||
|
||||
def uninstall_action(manifest, ip):
|
||||
app_id = manifest["app"]["id"]
|
||||
print(f"Uninstalling {app_id} on {ip}")
|
||||
url = get_url(ip, "/app/uninstall")
|
||||
params = {'id': app_id}
|
||||
try:
|
||||
response = requests.put(url, params=params)
|
||||
if response.status_code != 200:
|
||||
print_error("Uninstall failed")
|
||||
else:
|
||||
print(f"{shell_color_green}Uninstall successful ✅{shell_color_reset}")
|
||||
except requests.RequestException as e:
|
||||
print(f"Request failed: {e}")
|
||||
#region Main
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(f"Tactility Build System v{ttbuild_version}")
|
||||
if "--help" in sys.argv:
|
||||
print_help()
|
||||
sys.exit()
|
||||
# Argument validation
|
||||
if len(sys.argv) == 1:
|
||||
print_help()
|
||||
sys.exit()
|
||||
action_arg = sys.argv[1]
|
||||
verbose = "--verbose" in sys.argv
|
||||
skip_build = "--skip-build" in sys.argv
|
||||
use_local_sdk = "--local-sdk" in sys.argv
|
||||
# Environment setup
|
||||
setup_environment()
|
||||
if not os.path.isfile("manifest.properties"):
|
||||
exit_with_error("manifest.properties not found")
|
||||
manifest = read_manifest()
|
||||
validate_manifest(manifest)
|
||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||
# Update SDK cache (sdk.json)
|
||||
if should_update_sdk_json() and not update_sdk_json():
|
||||
exit_with_error("Failed to retrieve SDK info")
|
||||
# Actions
|
||||
if action_arg == "build":
|
||||
if len(sys.argv) < 2:
|
||||
print_help()
|
||||
exit_with_error("Commandline parameter missing")
|
||||
platform = None
|
||||
if len(sys.argv) > 2:
|
||||
platform = sys.argv[2]
|
||||
build_action(manifest, platform)
|
||||
elif action_arg == "clean":
|
||||
clean_action()
|
||||
elif action_arg == "clearcache":
|
||||
clear_cache_action()
|
||||
elif action_arg == "updateself":
|
||||
update_self_action()
|
||||
elif action_arg == "run":
|
||||
if len(sys.argv) < 3:
|
||||
print_help()
|
||||
exit_with_error("Commandline parameter missing")
|
||||
run_action(manifest, sys.argv[2])
|
||||
elif action_arg == "install":
|
||||
if len(sys.argv) < 3:
|
||||
print_help()
|
||||
exit_with_error("Commandline parameter missing")
|
||||
platform = None
|
||||
platforms_to_install = all_platform_targets
|
||||
if len(sys.argv) >= 4:
|
||||
platform = sys.argv[3]
|
||||
platforms_to_install = [platform]
|
||||
install_action(sys.argv[2], platforms_to_install)
|
||||
elif action_arg == "uninstall":
|
||||
if len(sys.argv) < 3:
|
||||
print_help()
|
||||
exit_with_error("Commandline parameter missing")
|
||||
uninstall_action(manifest, sys.argv[2])
|
||||
elif action_arg == "bir" or action_arg == "brrr":
|
||||
if len(sys.argv) < 3:
|
||||
print_help()
|
||||
exit_with_error("Commandline parameter missing")
|
||||
platform = None
|
||||
platforms_to_install = all_platform_targets
|
||||
if len(sys.argv) >= 4:
|
||||
platform = sys.argv[3]
|
||||
platforms_to_install = [platform]
|
||||
build_action(manifest, platform)
|
||||
install_action(sys.argv[2], platforms_to_install)
|
||||
run_action(manifest, sys.argv[2])
|
||||
else:
|
||||
print_help()
|
||||
exit_with_error("Unknown commandline parameter")
|
||||
|
||||
#endregion Main
|
||||
@ -25,6 +25,7 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
||||
fatfs
|
||||
lwip
|
||||
)
|
||||
|
||||
if ("${IDF_TARGET}" STREQUAL "esp32s3")
|
||||
list(APPEND REQUIRES_LIST esp_tinyusb)
|
||||
endif ()
|
||||
|
||||
@ -21,7 +21,8 @@ public:
|
||||
Keyboard,
|
||||
Encoder,
|
||||
Power,
|
||||
Gps
|
||||
Gps,
|
||||
Radio
|
||||
};
|
||||
|
||||
typedef uint32_t Id;
|
||||
|
||||
63
Tactility/Include/Tactility/hal/radio/ParameterSet.h
Normal file
63
Tactility/Include/Tactility/hal/radio/ParameterSet.h
Normal file
@ -0,0 +1,63 @@
|
||||
#pragma once
|
||||
|
||||
#include "RadioDevice.h"
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace tt::hal::radio {
|
||||
|
||||
class ParameterSet {
|
||||
private:
|
||||
struct ParameterHash
|
||||
{
|
||||
std::size_t operator()(RadioDevice::Parameter t) const
|
||||
{
|
||||
return static_cast<std::size_t>(t);
|
||||
}
|
||||
};
|
||||
|
||||
using Map = std::unordered_map<RadioDevice::Parameter, float, ParameterHash>;
|
||||
Map parameters;
|
||||
|
||||
public:
|
||||
explicit ParameterSet() {}
|
||||
explicit ParameterSet(const ParameterSet& other) { parameters = other.parameters; }
|
||||
~ParameterSet() = default;
|
||||
|
||||
float get(const RadioDevice::Parameter parameter) { return parameters[parameter]; }
|
||||
void set(const RadioDevice::Parameter parameter, const float value) { parameters[parameter] = value; }
|
||||
bool has(const RadioDevice::Parameter parameter) { return parameters.contains(parameter); }
|
||||
bool erase(const RadioDevice::Parameter parameter) {
|
||||
if (has(parameter)) {
|
||||
parameters.erase(parameter);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void clear() { parameters.clear(); }
|
||||
|
||||
bool apply(RadioDevice &radio) {
|
||||
bool successful = true;
|
||||
for (const auto& [parameter, value] : parameters) {
|
||||
// No break on error chosen to apply all parameters,
|
||||
// a bad one doesn't make the successive tries any more invalid
|
||||
successful &= (radio.setParameter(parameter, value) == RadioDevice::ParameterStatus::Success);
|
||||
}
|
||||
return successful;
|
||||
}
|
||||
|
||||
void load(const RadioDevice &radio) {
|
||||
// This loop has to be ajusted for each new parameter.
|
||||
// Could be made more maintainable with a template enum iterator in an utility header.
|
||||
for (RadioDevice::Parameter p = RadioDevice::Parameter::Power;
|
||||
p < RadioDevice::Parameter::NarrowGrid;
|
||||
p = static_cast<RadioDevice::Parameter>((size_t)p + 1)) {
|
||||
float value = 0.0;
|
||||
if (radio.getParameter(p, value) == RadioDevice::ParameterStatus::Success) {
|
||||
set(p, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
49
Tactility/Include/Tactility/hal/radio/PubSub.h
Normal file
49
Tactility/Include/Tactility/hal/radio/PubSub.h
Normal file
@ -0,0 +1,49 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace tt::hal::radio {
|
||||
|
||||
// Proposed PubSub class, can be moved elsewhere
|
||||
template<class... Ts>
|
||||
class PubSub
|
||||
{
|
||||
public:
|
||||
typedef int SubscriptionId;
|
||||
using Notifier = std::function<void(Ts...)>;
|
||||
|
||||
protected:
|
||||
struct Subscription {
|
||||
SubscriptionId id;
|
||||
std::shared_ptr<Notifier> notifier;
|
||||
};
|
||||
|
||||
SubscriptionId lastSubscriptionId = 0;
|
||||
std::vector<Subscription> subscriptions;
|
||||
|
||||
public:
|
||||
|
||||
PubSub() {}
|
||||
virtual ~PubSub() = default;
|
||||
|
||||
SubscriptionId subscribe(Notifier onPublish) {
|
||||
subscriptions.push_back({
|
||||
.id = ++lastSubscriptionId,
|
||||
.notifier = std::make_shared<Notifier>(onPublish)
|
||||
});
|
||||
return lastSubscriptionId;
|
||||
}
|
||||
|
||||
void unsubscribe(SubscriptionId subscriptionId) {
|
||||
std::erase_if(subscriptions, [subscriptionId](auto& subscription) { return subscription.id == subscriptionId; });
|
||||
}
|
||||
|
||||
void publish(Ts... pargs) {
|
||||
for (auto& subscription : subscriptions) {
|
||||
(*subscription.notifier)(pargs...);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
183
Tactility/Include/Tactility/hal/radio/RadioDevice.h
Normal file
183
Tactility/Include/Tactility/hal/radio/RadioDevice.h
Normal file
@ -0,0 +1,183 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Device.h"
|
||||
#include "PubSub.h"
|
||||
#include "Unit.h"
|
||||
|
||||
#include <Tactility/Mutex.h>
|
||||
#include <Tactility/Thread.h>
|
||||
|
||||
#include <deque>
|
||||
#include <utility>
|
||||
|
||||
namespace tt::hal::radio {
|
||||
|
||||
struct RxPacket {
|
||||
std::vector<uint8_t> data;
|
||||
float rssi;
|
||||
float snr;
|
||||
};
|
||||
|
||||
struct TxPacket {
|
||||
std::vector<uint8_t> data;
|
||||
uint32_t address; // FSK only
|
||||
};
|
||||
|
||||
class RadioDevice : public Device {
|
||||
|
||||
public:
|
||||
enum class Modulation {
|
||||
None,
|
||||
Fsk,
|
||||
LoRa,
|
||||
LrFhss
|
||||
};
|
||||
|
||||
enum class Parameter {
|
||||
Power,
|
||||
Frequency,
|
||||
Bandwidth,
|
||||
SpreadFactor,
|
||||
CodingRate,
|
||||
SyncWord,
|
||||
PreambleLength,
|
||||
FrequencyDeviation,
|
||||
DataRate,
|
||||
AddressWidth,
|
||||
NarrowGrid
|
||||
};
|
||||
|
||||
enum class ParameterStatus {
|
||||
Unavailable,
|
||||
ValueError,
|
||||
Success
|
||||
};
|
||||
|
||||
enum class State {
|
||||
PendingOn,
|
||||
On,
|
||||
Error,
|
||||
PendingOff,
|
||||
Off
|
||||
};
|
||||
|
||||
enum class TransmissionState {
|
||||
Queued,
|
||||
PendingTransmit,
|
||||
Transmitted,
|
||||
Timeout,
|
||||
Error
|
||||
};
|
||||
|
||||
typedef int TxId;
|
||||
|
||||
using StatePubSub = PubSub<Device::Id, State>;
|
||||
using RxPubSub = PubSub<Device::Id, const RxPacket&>;
|
||||
using StateSubscriptionId = StatePubSub::SubscriptionId;
|
||||
using RxSubscriptionId = RxPubSub::SubscriptionId;
|
||||
|
||||
using StateCallback = StatePubSub::Notifier;
|
||||
using RxCallback = RxPubSub::Notifier;
|
||||
using TxStateCallback = std::function<void(TxId id, TransmissionState state)>;
|
||||
|
||||
protected:
|
||||
struct TxItem {
|
||||
TxId id;
|
||||
TxPacket packet;
|
||||
TxStateCallback callback;
|
||||
};
|
||||
|
||||
private:
|
||||
State state;
|
||||
Modulation modulation;
|
||||
Mutex mutex = Mutex(Mutex::Type::Recursive);
|
||||
StatePubSub statePubSub;
|
||||
RxPubSub rxPubSub;
|
||||
std::deque<TxItem> txQueue;
|
||||
TxId lastTxId = 0;
|
||||
|
||||
protected:
|
||||
const Mutex &getMutex() const { return mutex; }
|
||||
void setState(State newState);
|
||||
|
||||
virtual void txQueuedSignal() = 0;
|
||||
|
||||
size_t getTxQueueSize() const {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
const auto size = txQueue.size();
|
||||
return size;
|
||||
}
|
||||
|
||||
TxItem popNextQueuedTx() {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
auto tx = std::move(txQueue.front());
|
||||
txQueue.pop_front();
|
||||
|
||||
return tx;
|
||||
}
|
||||
|
||||
void publishRx(const RxPacket& packet);
|
||||
|
||||
public:
|
||||
explicit RadioDevice()
|
||||
: state(State::Off), modulation(Modulation::None) {}
|
||||
|
||||
~RadioDevice() override = default;
|
||||
|
||||
Type getType() const override { return Type::Radio; }
|
||||
|
||||
bool setModulation(const Modulation newModulation);
|
||||
Modulation getModulation() const;
|
||||
virtual ParameterStatus setParameter(const Parameter parameter, const float value) = 0;
|
||||
virtual ParameterStatus getParameter(const Parameter parameter, float &value) const = 0;
|
||||
virtual Unit getParameterUnit(const Parameter parameter) const = 0;
|
||||
virtual bool canTransmit(const Modulation modulation) = 0;
|
||||
virtual bool canReceive(const Modulation modulation) = 0;
|
||||
|
||||
virtual bool start() = 0;
|
||||
virtual bool stop() = 0;
|
||||
|
||||
TxId transmit(const TxPacket& packet, TxStateCallback callback) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
const auto txId = lastTxId;
|
||||
txQueue.push_back(TxItem{.id = txId, .packet = packet, .callback = callback});
|
||||
callback(txId, TransmissionState::Queued);
|
||||
lastTxId++;
|
||||
txQueuedSignal();
|
||||
return txId;
|
||||
}
|
||||
|
||||
StateSubscriptionId subscribeStateChange(StateCallback onChange) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return statePubSub.subscribe(onChange);
|
||||
}
|
||||
|
||||
void unsubscribeStateChange(StateSubscriptionId subscriptionId) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return rxPubSub.unsubscribe(subscriptionId);
|
||||
}
|
||||
|
||||
RxSubscriptionId subscribeRx(const RxCallback& onData) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return rxPubSub.subscribe(onData);
|
||||
}
|
||||
|
||||
void unsubscribeRx(RxSubscriptionId subscriptionId) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return rxPubSub.unsubscribe(subscriptionId);
|
||||
}
|
||||
|
||||
State getState() const;
|
||||
};
|
||||
|
||||
const char* toString(RadioDevice::Modulation modulation);
|
||||
const char* toString(RadioDevice::Parameter parameter);
|
||||
}
|
||||
46
Tactility/Include/Tactility/hal/radio/Unit.h
Normal file
46
Tactility/Include/Tactility/hal/radio/Unit.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace tt::hal::radio {
|
||||
|
||||
class Unit {
|
||||
public:
|
||||
enum class Prefix {
|
||||
Femto,
|
||||
Pico,
|
||||
Nano,
|
||||
Milli,
|
||||
None,
|
||||
Kilo,
|
||||
Mega,
|
||||
Giga,
|
||||
Terra,
|
||||
Peta
|
||||
};
|
||||
|
||||
enum class Name
|
||||
{
|
||||
None,
|
||||
BitsPerSecond,
|
||||
BytesPerSecond,
|
||||
Herz,
|
||||
Decibel,
|
||||
DecibelMilliwatts
|
||||
};
|
||||
|
||||
const Prefix prefix;
|
||||
const Name unit;
|
||||
|
||||
explicit Unit(const Prefix si, const Name unit)
|
||||
: prefix(si), unit(unit) {}
|
||||
explicit Unit(const Name unit)
|
||||
: prefix(Prefix::None), unit(unit) {}
|
||||
|
||||
std::string toString() const;
|
||||
};
|
||||
|
||||
const char* toString(const Unit::Prefix prefix);
|
||||
const char* toString(const Unit::Name unit);
|
||||
|
||||
}
|
||||
@ -58,6 +58,7 @@ namespace app {
|
||||
namespace boot { extern const AppManifest manifest; }
|
||||
namespace calculator { extern const AppManifest manifest; }
|
||||
namespace chat { extern const AppManifest manifest; }
|
||||
namespace chirp { extern const AppManifest manifest; }
|
||||
namespace development { extern const AppManifest manifest; }
|
||||
namespace display { extern const AppManifest manifest; }
|
||||
namespace files { extern const AppManifest manifest; }
|
||||
@ -119,6 +120,7 @@ static void registerSystemApps() {
|
||||
addApp(app::wifiapsettings::manifest);
|
||||
addApp(app::wificonnect::manifest);
|
||||
addApp(app::wifimanage::manifest);
|
||||
addApp(app::chirp::manifest);
|
||||
|
||||
#if defined(CONFIG_TINYUSB_MSC_ENABLED) && CONFIG_TINYUSB_MSC_ENABLED
|
||||
addApp(app::usbsettings::manifest);
|
||||
|
||||
898
Tactility/Source/app/chirpchatter/ChirpChatterApp.cpp
Normal file
898
Tactility/Source/app/chirpchatter/ChirpChatterApp.cpp
Normal file
@ -0,0 +1,898 @@
|
||||
//#ifdef ESP_PLATFORM
|
||||
|
||||
#include <Tactility/app/AppManifest.h>
|
||||
#include <Tactility/lvgl/Toolbar.h>
|
||||
#include <Tactility/Assets.h>
|
||||
#include <Tactility/StringUtils.h>
|
||||
#include <Tactility/hal/radio/RadioDevice.h>
|
||||
#include <Tactility/hal/radio/ParameterSet.h>
|
||||
|
||||
#include "Tactility/lvgl/LvglSync.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
#include <ctime>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
#include <lvgl.h>
|
||||
|
||||
extern const lv_obj_class_t lv_label_class;
|
||||
|
||||
namespace tt::app::chirp {
|
||||
|
||||
constexpr const char* TAG = "ChirpChatterApp";
|
||||
|
||||
enum CCViews
|
||||
{
|
||||
CCView_Msgs,
|
||||
CCView_LoraSettings,
|
||||
CCView_ProtoSettings
|
||||
};
|
||||
|
||||
class ChirpChatterApp;
|
||||
|
||||
template<CCViews view>
|
||||
static void changeViewHandler(lv_event_t* e) {
|
||||
auto* self = static_cast<ChirpChatterApp*>(lv_event_get_user_data(e));
|
||||
TT_LOG_I(TAG, "Clicked %d", view);
|
||||
self->changeView(view);
|
||||
}
|
||||
|
||||
static void buttonRecolorFocus(lv_event_t *event) {
|
||||
lv_obj_t *image = (lv_obj_t *)lv_event_get_user_data(event);
|
||||
if (image != NULL) {
|
||||
lv_obj_set_style_image_recolor(image, lv_palette_main(LV_PALETTE_YELLOW), LV_STATE_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
static void buttonRecolorDefocus(lv_event_t *event) {
|
||||
lv_obj_t *image = (lv_obj_t *)lv_event_get_user_data(event);
|
||||
if (image != NULL) {
|
||||
lv_obj_set_style_image_recolor(image, lv_theme_get_color_primary(image), LV_STATE_DEFAULT);
|
||||
}
|
||||
}
|
||||
|
||||
static void debugFocus(lv_event_t *event) {
|
||||
lv_obj_t *target = (lv_obj_t *)lv_event_get_current_target(event);
|
||||
if (target != NULL) {
|
||||
lv_obj_set_style_bg_color(target, lv_color_hex(0xFF0000), 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void debugDefocus(lv_event_t *event) {
|
||||
lv_obj_t *target = (lv_obj_t *)lv_event_get_current_target(event);
|
||||
if (target != NULL) {
|
||||
lv_obj_set_style_bg_color(target, lv_color_hex(0x00FF00), 0);
|
||||
}
|
||||
}
|
||||
|
||||
bool isPrintableData(const std::vector<uint8_t>& data) {
|
||||
return std::all_of(data.begin(), data.end(),
|
||||
[](uint8_t byte) {
|
||||
char c = static_cast<char>(byte);
|
||||
return std::isprint(static_cast<unsigned char>(c));
|
||||
});
|
||||
}
|
||||
|
||||
std::string hexdump(const std::vector<uint8_t>& data) {
|
||||
std::ostringstream oss;
|
||||
for (size_t i = 0; i < data.size(); ++i) {
|
||||
oss << std::hex << std::uppercase << std::setw(2) << std::setfill('0')
|
||||
<< static_cast<unsigned>(data[i]);
|
||||
if (i + 1 != data.size()) oss << ' ';
|
||||
}
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
bool isValidHexString(const std::string& hex) {
|
||||
if (hex.empty() || (hex.size() % 2) != 0) return false;
|
||||
for (char c : hex)
|
||||
if (!std::isxdigit(static_cast<unsigned char>(c)))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parseHexString(const std::string& hex, std::vector<uint8_t>& out) {
|
||||
if (!isValidHexString(hex)) return false;
|
||||
out.clear();
|
||||
out.reserve(hex.size() / 2);
|
||||
for (size_t i = 0; i < hex.size(); i += 2) {
|
||||
uint8_t high = std::isdigit(hex[i]) ? (hex[i] - '0')
|
||||
: (std::tolower(hex[i]) - 'a' + 10);
|
||||
uint8_t low = std::isdigit(hex[i+1]) ? (hex[i+1] - '0')
|
||||
: (std::tolower(hex[i+1]) - 'a' + 10);
|
||||
out.push_back(static_cast<uint8_t>((high << 4) | low));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
class LoraView {
|
||||
public:
|
||||
using DeviceActivationCallback = std::function<void(std::shared_ptr<tt::hal::radio::RadioDevice>)>;
|
||||
private:
|
||||
//using LoraParameters = tt::hal::lora::LoraParameters;
|
||||
|
||||
std::vector<std::string> loraDevNames;
|
||||
std::vector<std::shared_ptr<tt::hal::radio::RadioDevice>> loraDevs;
|
||||
std::shared_ptr<tt::hal::radio::RadioDevice> loraDevice;
|
||||
|
||||
DeviceActivationCallback cbDevActive;
|
||||
DeviceActivationCallback cbDevInactive;
|
||||
|
||||
void queryLoraDevs() {
|
||||
auto radios = tt::hal::findDevices<tt::hal::radio::RadioDevice>(tt::hal::Device::Type::Radio);
|
||||
loraDevNames.clear();
|
||||
loraDevs.clear();
|
||||
|
||||
for (const auto& radio: radios) {
|
||||
if (radio->canTransmit(tt::hal::radio::RadioDevice::Modulation::LoRa) &&
|
||||
radio->canReceive(tt::hal::radio::RadioDevice::Modulation::LoRa)) {
|
||||
loraDevNames.push_back(radio->getName());
|
||||
loraDevs.push_back(radio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lv_obj_t* initDropdownInput(int row, const char* const label, const char* const items) {
|
||||
lv_obj_t* label_obj = lv_label_create(container);
|
||||
lv_label_set_text(label_obj, label);
|
||||
lv_obj_set_grid_cell(label_obj,
|
||||
LV_GRID_ALIGN_STRETCH, 0, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(label_obj, lv_pct(100), LV_SIZE_CONTENT);
|
||||
|
||||
lv_obj_t* input = lv_dropdown_create(container);
|
||||
lv_obj_set_grid_cell(input,
|
||||
LV_GRID_ALIGN_STRETCH, 1, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(input, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_dropdown_set_options(input, items);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
lv_obj_t* initFormInput(int row, const char* const label, const char* const defval, const char* const unit) {
|
||||
lv_obj_t* label_obj = lv_label_create(container);
|
||||
lv_label_set_text(label_obj, label);
|
||||
lv_obj_set_grid_cell(label_obj,
|
||||
LV_GRID_ALIGN_STRETCH, 0, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(label_obj, lv_pct(100), LV_SIZE_CONTENT);
|
||||
|
||||
lv_obj_t* input = lv_textarea_create(container);
|
||||
lv_obj_set_grid_cell(input,
|
||||
LV_GRID_ALIGN_STRETCH, 1, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(input, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_textarea_set_text(input, defval);
|
||||
lv_textarea_set_one_line(input, true);
|
||||
|
||||
lv_obj_t* unit_obj = lv_label_create(container);
|
||||
lv_label_set_text(unit_obj, unit);
|
||||
lv_obj_set_grid_cell(unit_obj,
|
||||
LV_GRID_ALIGN_STRETCH, 2, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(unit_obj, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_text_align(unit_obj , LV_TEXT_ALIGN_CENTER, 0);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
lv_obj_t* initSliderInput(int row, const char* const label, int min, int max, int defval) {
|
||||
lv_obj_t* label_obj = lv_label_create(container);
|
||||
lv_label_set_text(label_obj, label);
|
||||
lv_obj_set_grid_cell(label_obj,
|
||||
LV_GRID_ALIGN_STRETCH, 0, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(label_obj, lv_pct(100), LV_SIZE_CONTENT);
|
||||
|
||||
lv_obj_t* input = lv_slider_create(container);
|
||||
lv_obj_set_grid_cell(input,
|
||||
LV_GRID_ALIGN_STRETCH, 1, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(input, lv_pct(100), 10);
|
||||
lv_slider_set_range(input, min, max);
|
||||
|
||||
lv_obj_t* number_obj = lv_label_create(container);
|
||||
//lv_label_set_text(number_obj, unit);
|
||||
lv_obj_set_grid_cell(number_obj,
|
||||
LV_GRID_ALIGN_STRETCH, 2, 1,
|
||||
LV_GRID_ALIGN_CENTER, row, 1);
|
||||
lv_obj_set_size(number_obj, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_obj_set_style_text_align(number_obj , LV_TEXT_ALIGN_CENTER, 0);
|
||||
char buf[8] = {0};
|
||||
lv_snprintf(buf, sizeof(buf), "%d", defval);
|
||||
lv_label_set_text(number_obj, buf);
|
||||
|
||||
lv_obj_add_event_cb(input, [](lv_event_t * e) {
|
||||
lv_obj_t* slider = lv_event_get_target_obj(e);
|
||||
lv_obj_t* label = (lv_obj_t*)lv_event_get_user_data(e);
|
||||
char buf[8] = {0};
|
||||
lv_snprintf(buf, sizeof(buf), "%d", (int)lv_slider_get_value(slider));
|
||||
lv_label_set_text(label, buf);
|
||||
}, LV_EVENT_VALUE_CHANGED, number_obj);
|
||||
|
||||
lv_slider_set_value(input, defval, LV_ANIM_OFF);
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
void initUi(lv_obj_t *parent) {
|
||||
container = lv_obj_create(parent);
|
||||
lv_obj_set_size(container, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_style_pad_all(container, 0, 0);
|
||||
|
||||
int grid_row_size = 40;
|
||||
static lv_coord_t lora_col_dsc[] = {LV_GRID_FR(3), LV_GRID_FR(2), 45, LV_GRID_TEMPLATE_LAST};
|
||||
static lv_coord_t lora_row_dsc[] = {
|
||||
grid_row_size,
|
||||
grid_row_size,
|
||||
grid_row_size,
|
||||
grid_row_size,
|
||||
grid_row_size,
|
||||
grid_row_size,
|
||||
grid_row_size,
|
||||
grid_row_size,
|
||||
LV_GRID_TEMPLATE_LAST};
|
||||
lv_obj_set_grid_dsc_array(container, lora_col_dsc, lora_row_dsc);
|
||||
|
||||
std::string dropdown_items = string::join(loraDevNames, "\n");
|
||||
loraDeviceInput = initDropdownInput(0, "LoRa Device", dropdown_items.c_str());
|
||||
loraDeviceOn = lv_switch_create(container);
|
||||
lv_obj_set_grid_cell(loraDeviceOn,
|
||||
LV_GRID_ALIGN_STRETCH, 2, 1,
|
||||
LV_GRID_ALIGN_CENTER, 0, 1);
|
||||
lv_obj_set_size(loraDeviceOn, lv_pct(100), 20);
|
||||
|
||||
frequencyInput = initFormInput(1, "Frequency", "869.525", "MHz");
|
||||
bandwidthInput = initFormInput(2, "Bandwidth", "250", "kHz");
|
||||
syncwordInput = initFormInput(3, "Sync Word", "2B", "hex");
|
||||
deBitsInput = initSliderInput(4, "Coding Rate", 4, 8, 5);
|
||||
sfInput = initSliderInput(5, "Spread Factor", 7, 12, 11);
|
||||
preambleChirpsInput = initSliderInput(6, "Preamble Chirps", 4, 32, 16);
|
||||
txPowInput = initFormInput(7, "TX Power", "27", "dBm");
|
||||
/*
|
||||
lv_obj_add_event_cb(frequencyInput, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraParameters* params = (LoraParameters*)lv_event_get_user_data(e);
|
||||
std::string buf(lv_textarea_get_text(input));
|
||||
if (!buf.empty()) {
|
||||
params->frequency = std::stof(buf);
|
||||
}
|
||||
}, LV_EVENT_VALUE_CHANGED, &loraParams);
|
||||
|
||||
lv_obj_add_event_cb(bandwidthInput, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraParameters* params = (LoraParameters*)lv_event_get_user_data(e);
|
||||
std::string buf(lv_textarea_get_text(input));
|
||||
if (!buf.empty()) {
|
||||
params->bandwidth = std::stof(buf);
|
||||
}
|
||||
}, LV_EVENT_VALUE_CHANGED, &loraParams);
|
||||
|
||||
lv_obj_add_event_cb(syncwordInput, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraParameters* params = (LoraParameters*)lv_event_get_user_data(e);
|
||||
std::string buf(lv_textarea_get_text(input));
|
||||
if (!buf.empty()) {
|
||||
std::stringstream ss;
|
||||
ss << std::hex << buf;
|
||||
ss >> params->syncWord;
|
||||
}
|
||||
}, LV_EVENT_VALUE_CHANGED, &loraParams);
|
||||
|
||||
lv_obj_add_event_cb(preambleChirpsInput, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraParameters* params = (LoraParameters*)lv_event_get_user_data(e);
|
||||
params->preambleLength = lv_slider_get_value(input);
|
||||
}, LV_EVENT_VALUE_CHANGED, &loraParams);
|
||||
|
||||
lv_obj_add_event_cb(deBitsInput, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraParameters* params = (LoraParameters*)lv_event_get_user_data(e);
|
||||
params->deBits = lv_slider_get_value(input);
|
||||
}, LV_EVENT_VALUE_CHANGED, &loraParams);
|
||||
|
||||
lv_obj_add_event_cb(sfInput, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraParameters* params = (LoraParameters*)lv_event_get_user_data(e);
|
||||
params->spreadFactor = lv_slider_get_value(input);
|
||||
}, LV_EVENT_VALUE_CHANGED, &loraParams);
|
||||
|
||||
lv_obj_add_event_cb(txPowInput, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraParameters* params = (LoraParameters*)lv_event_get_user_data(e);
|
||||
std::string buf(lv_textarea_get_text(input));
|
||||
if (!buf.empty()) {
|
||||
params->power = std::stoi(buf);
|
||||
}
|
||||
}, LV_EVENT_VALUE_CHANGED, &loraParams);
|
||||
*/
|
||||
/*
|
||||
if (loraDevNames.size() > 0) {
|
||||
loraDevice = loraService->getDevice(loraDevNames[0]);
|
||||
if (loraDevice)
|
||||
{
|
||||
using State = hal::lora::LoraDevice::State;
|
||||
switch (loraDevice->getState()) {
|
||||
case State::PendingOn:
|
||||
case State::On:
|
||||
setParameters(loraDevice->getParameters());
|
||||
disableForm();
|
||||
lv_obj_add_state(loraDeviceOn, LV_STATE_CHECKED);
|
||||
break;
|
||||
case State::Error:
|
||||
case State::PendingOff:
|
||||
case State::Off:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
TT_LOG_E(TAG, "Attempted to load device \"%s\", what is happening!?", loraDevNames[0].c_str());
|
||||
}
|
||||
}*/
|
||||
|
||||
lv_obj_add_event_cb(loraDeviceOn, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
LoraView* self = (LoraView*)lv_event_get_user_data(e);
|
||||
if (lv_obj_has_state(input, LV_STATE_CHECKED)) {
|
||||
self->enableDevice();
|
||||
} else {
|
||||
self->disableDevice();
|
||||
}
|
||||
}, LV_EVENT_VALUE_CHANGED, this);
|
||||
|
||||
}
|
||||
|
||||
void disableForm()
|
||||
{
|
||||
lv_obj_add_state(loraDeviceInput, LV_STATE_DISABLED);
|
||||
lv_obj_add_state(frequencyInput, LV_STATE_DISABLED);
|
||||
lv_obj_add_state(bandwidthInput, LV_STATE_DISABLED);
|
||||
lv_obj_add_state(syncwordInput, LV_STATE_DISABLED);
|
||||
lv_obj_add_state(deBitsInput, LV_STATE_DISABLED);
|
||||
lv_obj_add_state(preambleChirpsInput, LV_STATE_DISABLED);
|
||||
lv_obj_add_state(txPowInput, LV_STATE_DISABLED);
|
||||
}
|
||||
|
||||
void enableForm()
|
||||
{
|
||||
lv_obj_clear_state(loraDeviceInput, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(frequencyInput, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(bandwidthInput, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(syncwordInput, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(deBitsInput, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(preambleChirpsInput, LV_STATE_DISABLED);
|
||||
lv_obj_clear_state(txPowInput, LV_STATE_DISABLED);
|
||||
}
|
||||
|
||||
public:
|
||||
//std::shared_ptr<hal::lora::LoraDevice> loraDevice;
|
||||
lv_obj_t* container;
|
||||
lv_obj_t* loraDeviceOn;
|
||||
lv_obj_t* loraDeviceInput;
|
||||
lv_obj_t* frequencyInput;
|
||||
lv_obj_t* bandwidthInput;
|
||||
lv_obj_t* syncwordInput;
|
||||
lv_obj_t* deBitsInput;
|
||||
lv_obj_t* sfInput;
|
||||
lv_obj_t* preambleChirpsInput;
|
||||
lv_obj_t* txPowInput;
|
||||
|
||||
LoraView(lv_obj_t *parent) {
|
||||
queryLoraDevs();
|
||||
initUi(parent);
|
||||
setParameters(
|
||||
869.525,
|
||||
250.0,
|
||||
0x2B,
|
||||
16,
|
||||
5,
|
||||
11,
|
||||
22
|
||||
);
|
||||
}
|
||||
|
||||
void onDeviceActivation(DeviceActivationCallback cb) {
|
||||
cbDevActive = cb;
|
||||
}
|
||||
|
||||
void onDeviceDeactivation(DeviceActivationCallback cb) {
|
||||
cbDevInactive = cb;
|
||||
}
|
||||
|
||||
void setParameters(float frequency, float bandwidth, uint8_t syncWord, uint16_t preambleLength, uint8_t codingRate, uint8_t spreadFactor, int8_t power) {
|
||||
std::string buf;
|
||||
|
||||
buf = std::format("{:.6f}", frequency);
|
||||
lv_textarea_set_text(frequencyInput, buf.c_str());
|
||||
buf = std::format("{:.2f}", bandwidth);
|
||||
lv_textarea_set_text(bandwidthInput, buf.c_str());
|
||||
buf = std::format("{:X}", syncWord);
|
||||
lv_textarea_set_text(syncwordInput, buf.c_str());
|
||||
lv_slider_set_value(preambleChirpsInput, preambleLength, LV_ANIM_OFF);
|
||||
lv_slider_set_value(deBitsInput, codingRate, LV_ANIM_OFF);
|
||||
lv_slider_set_value(sfInput, spreadFactor, LV_ANIM_OFF);
|
||||
buf = std::format("{:d}", power);
|
||||
lv_textarea_set_text(txPowInput, buf.c_str());
|
||||
}
|
||||
|
||||
void configureFromForm() {
|
||||
using enum tt::hal::radio::RadioDevice::Parameter;
|
||||
using enum tt::hal::radio::RadioDevice::ParameterStatus;
|
||||
|
||||
std::string buffer;
|
||||
int value = 0;
|
||||
bool configured = true;
|
||||
buffer = lv_textarea_get_text(frequencyInput);
|
||||
if (!buffer.empty()) {
|
||||
configured &= (loraDevice->setParameter(Frequency, std::stof(buffer)) == Success);
|
||||
}
|
||||
buffer = lv_textarea_get_text(bandwidthInput);
|
||||
if (!buffer.empty()) {
|
||||
configured &= (loraDevice->setParameter(Bandwidth, std::stof(buffer)) == Success);
|
||||
}
|
||||
buffer = lv_textarea_get_text(syncwordInput);
|
||||
if (!buffer.empty()) {
|
||||
uint8_t syncWord = 0;
|
||||
std::stringstream ss(buffer);
|
||||
ss >> std::hex >> syncWord;
|
||||
|
||||
configured &= (loraDevice->setParameter(SyncWord, std::stoi(buffer, nullptr, 16)) == Success);
|
||||
}
|
||||
value = lv_slider_get_value(deBitsInput);
|
||||
configured &= (loraDevice->setParameter(CodingRate, value) == Success);
|
||||
|
||||
value = lv_slider_get_value(sfInput);
|
||||
configured &= (loraDevice->setParameter(SpreadFactor, value) == Success);
|
||||
|
||||
value = lv_slider_get_value(preambleChirpsInput);
|
||||
configured &= (loraDevice->setParameter(PreambleLength, value) == Success);
|
||||
|
||||
buffer = lv_textarea_get_text(txPowInput);
|
||||
if (!buffer.empty()) {
|
||||
configured &= (loraDevice->setParameter(Power, std::stof(buffer)) == Success);
|
||||
}
|
||||
}
|
||||
|
||||
void enableDevice()
|
||||
{
|
||||
loraDevice = loraDevs[lv_dropdown_get_selected(loraDeviceInput)];
|
||||
if (loraDevice) {
|
||||
disableForm();
|
||||
loraDevice->setModulation(tt::hal::radio::RadioDevice::Modulation::LoRa);
|
||||
configureFromForm();
|
||||
loraDevice->start();
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
if (loraDevice->getState() != tt::hal::radio::RadioDevice::State::On) {
|
||||
lv_obj_clear_state(loraDeviceOn, LV_STATE_CHECKED);
|
||||
enableForm();
|
||||
} else {
|
||||
cbDevActive(loraDevice);
|
||||
}
|
||||
} else {
|
||||
lv_obj_clear_state(loraDeviceOn, LV_STATE_CHECKED);
|
||||
}
|
||||
}
|
||||
|
||||
void disableDevice()
|
||||
{
|
||||
if (loraDevice) {
|
||||
loraDevice->stop();
|
||||
cbDevInactive(loraDevice);
|
||||
}
|
||||
enableForm();
|
||||
}
|
||||
};
|
||||
|
||||
class ChirpChatterApp : public App {
|
||||
|
||||
lv_obj_t* sidebar = nullptr;
|
||||
lv_obj_t* mainView = nullptr;
|
||||
lv_obj_t* progressBar = nullptr;
|
||||
lv_obj_t* progressText = nullptr;
|
||||
|
||||
lv_obj_t* messageList = nullptr;
|
||||
lv_obj_t* inputField = nullptr;
|
||||
|
||||
lv_obj_t* messageView = nullptr;
|
||||
LoraView* loraView = nullptr;
|
||||
|
||||
hal::radio::RadioDevice::RxSubscriptionId rxSubId;
|
||||
std::shared_ptr<tt::hal::radio::RadioDevice> loraDevice;
|
||||
|
||||
template<CCViews T>
|
||||
lv_obj_t* createSidebarButton(lv_obj_t* parent, const char* image_file) {
|
||||
auto* sidebar_button = lv_button_create(parent);
|
||||
|
||||
lv_obj_set_size(sidebar_button, 32, 32);
|
||||
lv_obj_align(sidebar_button, LV_ALIGN_TOP_MID, 0, 0);
|
||||
lv_obj_set_style_pad_all(sidebar_button, 0, 0);
|
||||
//lv_obj_set_style_pad_top(sidebar_button, 36, 0);
|
||||
lv_obj_set_style_shadow_width(sidebar_button, 0, 0);
|
||||
lv_obj_set_style_border_width(sidebar_button, 0, 0);
|
||||
lv_obj_set_style_bg_opa(sidebar_button, 0, LV_PART_MAIN);
|
||||
|
||||
auto* button_image = lv_image_create(sidebar_button);
|
||||
lv_image_set_src(button_image, image_file);
|
||||
lv_obj_set_style_image_recolor(button_image, lv_theme_get_color_primary(parent), LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_image_recolor_opa(button_image, LV_OPA_COVER, LV_STATE_DEFAULT);
|
||||
// Ensure buttons are still tappable when asset fails to load
|
||||
lv_obj_set_size(button_image, 32, 32);
|
||||
|
||||
static lv_style_t style_focus;
|
||||
lv_style_init(&style_focus);
|
||||
lv_style_set_outline_width(&style_focus, 0);
|
||||
lv_obj_add_style(sidebar_button, &style_focus, LV_PART_MAIN | LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
lv_obj_add_style(button_image, &style_focus, LV_PART_MAIN | LV_STATE_FOCUSED | LV_STATE_FOCUS_KEY);
|
||||
|
||||
lv_obj_add_event_cb(button_image, changeViewHandler<T>, LV_EVENT_SHORT_CLICKED, (void*)this);
|
||||
lv_obj_add_event_cb(sidebar_button, changeViewHandler<T>, LV_EVENT_SHORT_CLICKED, (void*)this);
|
||||
|
||||
lv_obj_add_event_cb(sidebar_button, buttonRecolorFocus, LV_EVENT_FOCUSED, button_image);
|
||||
lv_obj_add_event_cb(sidebar_button, buttonRecolorDefocus, LV_EVENT_DEFOCUSED, button_image);
|
||||
|
||||
return sidebar_button;
|
||||
}
|
||||
|
||||
void addDummyMessage(const char* const message) {
|
||||
auto* msg_container = lv_obj_create(messageList);
|
||||
lv_obj_set_flex_flow(msg_container, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_grow(msg_container, 0);
|
||||
lv_obj_set_style_pad_all(msg_container, 1, 0);
|
||||
lv_obj_add_flag(msg_container, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
lv_obj_t* msg_label = lv_label_create(msg_container);
|
||||
lv_label_set_text(msg_label, message);
|
||||
lv_obj_set_width(msg_label, lv_pct(100));
|
||||
lv_label_set_long_mode(msg_label, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_label, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_label, 0, 0);
|
||||
|
||||
lv_obj_t* msg_info = lv_label_create(msg_container);
|
||||
lv_label_set_text(msg_info, "RX/2024-07-06+15:04");
|
||||
lv_obj_set_width(msg_info, lv_pct(100));
|
||||
lv_label_set_long_mode(msg_info, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_info, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_info, 0, 0);
|
||||
lv_obj_set_style_text_font(msg_info, &lv_font_montserrat_10, 0);
|
||||
|
||||
|
||||
lv_obj_set_width(msg_container, lv_pct(100));
|
||||
lv_obj_set_height(msg_container, LV_SIZE_CONTENT);
|
||||
|
||||
lv_obj_scroll_to_y(messageList, lv_obj_get_scroll_y(messageList) + 1000, LV_ANIM_ON);
|
||||
|
||||
/*auto* group = lv_group_get_default();
|
||||
lv_group_add_obj(group, msg_container);*/
|
||||
}
|
||||
|
||||
void addPacketMessage(const hal::radio::RxPacket& packet) {
|
||||
auto* msg_container = lv_obj_create(messageList);
|
||||
lv_obj_set_flex_flow(msg_container, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_flex_grow(msg_container, 0);
|
||||
lv_obj_set_style_pad_all(msg_container, 1, 0);
|
||||
lv_obj_add_flag(msg_container, LV_OBJ_FLAG_CLICKABLE);
|
||||
|
||||
lv_obj_t* msg_label = lv_label_create(msg_container);
|
||||
|
||||
std::string messageBuf = "";
|
||||
if (isPrintableData(packet.data)) {
|
||||
messageBuf = std::string(packet.data.begin(), packet.data.end());
|
||||
} else {
|
||||
messageBuf = hexdump(packet.data);
|
||||
}
|
||||
lv_label_set_text(msg_label, messageBuf.c_str());
|
||||
lv_obj_set_width(msg_label, lv_pct(100));
|
||||
lv_label_set_long_mode(msg_label, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_label, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_label, 0, 0);
|
||||
|
||||
lv_obj_t* msg_info = lv_label_create(msg_container);
|
||||
|
||||
auto t = std::time(nullptr);
|
||||
auto tm = *std::localtime(&t);
|
||||
std::stringstream ss;
|
||||
ss << "RX/RAW ";
|
||||
ss << std::put_time(&tm, "%Y-%m-%d %H:%M:%S");
|
||||
ss << " ";
|
||||
ss << "RSSI:" << packet.rssi;
|
||||
ss << " ";
|
||||
ss << "SNR:" << packet.snr;
|
||||
|
||||
lv_label_set_text(msg_info, ss.str().c_str());
|
||||
lv_obj_set_width(msg_info, lv_pct(100));
|
||||
lv_label_set_long_mode(msg_info, LV_LABEL_LONG_WRAP);
|
||||
lv_obj_set_style_text_align(msg_info, LV_TEXT_ALIGN_LEFT, 0);
|
||||
lv_obj_set_style_pad_all(msg_info, 0, 0);
|
||||
lv_obj_set_style_text_font(msg_info, &lv_font_montserrat_10, 0);
|
||||
|
||||
|
||||
lv_obj_set_width(msg_container, lv_pct(100));
|
||||
lv_obj_set_height(msg_container, LV_SIZE_CONTENT);
|
||||
|
||||
lv_obj_scroll_to_y(messageList, lv_obj_get_scroll_y(messageList) + 1000, LV_ANIM_ON);
|
||||
|
||||
/*auto* group = lv_group_get_default();
|
||||
* lv_group_add_obj(group, msg_container);*/
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
void onCreate(AppContext& appContext) override {
|
||||
#ifdef ESP_PLATFORM
|
||||
esp_log_level_set("*", ESP_LOG_DEBUG);
|
||||
#endif
|
||||
}
|
||||
|
||||
void onDestroy(AppContext& appContext) override {
|
||||
|
||||
}
|
||||
|
||||
void onShow(AppContext& context, lv_obj_t* parent) override {
|
||||
|
||||
static lv_coord_t grid_col_dsc[] = {36, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
static lv_coord_t grid_row_dsc[] = {40, LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST};
|
||||
|
||||
lv_obj_t * grid = lv_obj_create(parent);
|
||||
lv_obj_set_grid_dsc_array(grid, grid_col_dsc, grid_row_dsc);
|
||||
lv_obj_set_size(grid, lv_pct(100), lv_pct(100));
|
||||
|
||||
static lv_style_t style_grid;
|
||||
lv_style_init(&style_grid);
|
||||
lv_style_set_pad_row(&style_grid, 0);
|
||||
lv_style_set_pad_column(&style_grid, 0);
|
||||
lv_style_set_pad_all(&style_grid, 0);
|
||||
|
||||
lv_obj_add_style(grid, &style_grid, LV_PART_MAIN);
|
||||
|
||||
// Create toolbar
|
||||
auto* toolbar = tt::lvgl::toolbar_create(grid, "Welcome to ChirpChatter!");
|
||||
lv_obj_set_size(toolbar, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_obj_set_grid_cell(toolbar, LV_GRID_ALIGN_STRETCH, 0, 2,
|
||||
LV_GRID_ALIGN_STRETCH, 0, 1);
|
||||
|
||||
progressText = lv_obj_get_child_by_type(toolbar, 0, &lv_label_class);
|
||||
lv_obj_align(progressText, LV_ALIGN_TOP_LEFT, 0, 0);
|
||||
lv_obj_set_style_text_font(progressText, &lv_font_montserrat_12, 0);
|
||||
lv_obj_set_size(progressText, lv_pct(75), LV_SIZE_CONTENT);
|
||||
|
||||
// Create sidebar
|
||||
sidebar = lv_obj_create(grid);
|
||||
lv_obj_set_size(sidebar, LV_SIZE_CONTENT, LV_SIZE_CONTENT);
|
||||
lv_obj_set_grid_cell(sidebar, LV_GRID_ALIGN_START, 0, 1,
|
||||
LV_GRID_ALIGN_START, 1, 1);
|
||||
|
||||
lv_obj_set_scrollbar_mode(sidebar, LV_SCROLLBAR_MODE_OFF);
|
||||
lv_obj_set_style_pad_all(sidebar, 2, 0);
|
||||
lv_obj_set_style_border_width(sidebar, 0, 0);
|
||||
lv_obj_set_flex_flow(sidebar, LV_FLEX_FLOW_COLUMN);
|
||||
|
||||
// Create progress bar
|
||||
progressBar = lv_bar_create(toolbar);
|
||||
//lv_obj_set_flex_flow(toolbar, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_align(progressBar, LV_ALIGN_RIGHT_MID, 0, 0);
|
||||
lv_obj_set_size(progressBar, lv_pct(25), 36);
|
||||
lv_obj_set_style_radius(progressBar, 0, LV_PART_MAIN | LV_STATE_DEFAULT);
|
||||
lv_obj_set_style_radius(progressBar, 0, LV_PART_INDICATOR | LV_STATE_DEFAULT);
|
||||
lv_bar_set_range(progressBar, 0, 100);
|
||||
lv_bar_set_value(progressBar, 100, LV_ANIM_OFF);
|
||||
|
||||
auto paths = context.getPaths();
|
||||
auto icon_msgs_path = paths->getSystemPathLvgl("icon_msgs.png");
|
||||
createSidebarButton<CCView_Msgs>(sidebar, icon_msgs_path.c_str());
|
||||
auto icon_lora_path = paths->getSystemPathLvgl("icon_lora.png");
|
||||
createSidebarButton<CCView_LoraSettings>(sidebar, icon_lora_path.c_str());
|
||||
auto icon_proto_path = paths->getSystemPathLvgl("icon_proto.png");
|
||||
createSidebarButton<CCView_ProtoSettings>(sidebar, icon_proto_path.c_str());
|
||||
|
||||
|
||||
// Main view
|
||||
/*mainView = lv_obj_create(grid);
|
||||
lv_obj_set_size(mainView, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_grid_cell(mainView, LV_GRID_ALIGN_STRETCH, 1, 1,
|
||||
LV_GRID_ALIGN_STRETCH, 1, 1);
|
||||
//lv_obj_set_flex_flow(mainView, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_set_style_bg_color(mainView, lv_color_hex(0x00FF00), 0);
|
||||
lv_obj_set_style_border_width(mainView, 0, 0);
|
||||
lv_obj_set_style_pad_all(mainView, 0, 0);
|
||||
*/
|
||||
// Message view
|
||||
messageView = lv_obj_create(grid);
|
||||
//lv_obj_set_size(messageView, lv_disp_get_hor_res(NULL) - 40, lv_disp_get_ver_res(NULL) - toolbar_height*2);
|
||||
lv_obj_set_size(messageView, lv_pct(100), lv_pct(100));
|
||||
//lv_obj_set_flex_flow(messageView, LV_FLEX_FLOW_COLUMN);
|
||||
//lv_obj_set_flex_grow(messageView, 1);
|
||||
lv_obj_set_size(messageView, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_grid_cell(messageView, LV_GRID_ALIGN_STRETCH, 1, 1,
|
||||
LV_GRID_ALIGN_STRETCH, 1, 1);
|
||||
|
||||
lv_obj_set_style_pad_all(messageView, 0, 0);
|
||||
|
||||
|
||||
messageList = lv_obj_create(messageView);
|
||||
lv_obj_set_size(messageList, lv_pct(100), lv_pct(80));
|
||||
lv_obj_set_flex_flow(messageList, LV_FLEX_FLOW_COLUMN);
|
||||
lv_obj_align(messageList, LV_ALIGN_TOP_MID, 0, 0);
|
||||
///lv_obj_set_style_bg_color(mainView, lv_color_hex(0xFF0000), 0);
|
||||
lv_obj_set_style_border_width(messageList, 0, 0);
|
||||
lv_obj_set_style_pad_all(messageList, 0, 0);
|
||||
lv_obj_add_flag(messageList, (lv_obj_flag_t)(LV_OBJ_FLAG_CLICKABLE | LV_OBJ_FLAG_SCROLL_ON_FOCUS));
|
||||
|
||||
auto* group = lv_group_get_default();
|
||||
lv_group_add_obj(group, messageList);
|
||||
|
||||
lv_obj_add_event_cb(messageList, buttonRecolorFocus, LV_EVENT_FOCUSED, nullptr);
|
||||
lv_obj_add_event_cb(messageList, buttonRecolorDefocus, LV_EVENT_DEFOCUSED, nullptr);
|
||||
|
||||
/*
|
||||
messageList = lv_page_create(messageView, nullptr);
|
||||
lv_obj_set_size(messageList, lv_pct(100), lv_pct(80));
|
||||
lv_obj_set_style_border_width(messageList, 0, 0);
|
||||
lv_obj_set_style_pad_all(messageList, 0, 0);
|
||||
*/
|
||||
// Input panel
|
||||
auto* input_panel = lv_obj_create(messageView);
|
||||
lv_obj_set_flex_flow(input_panel, LV_FLEX_FLOW_ROW);
|
||||
lv_obj_set_size(input_panel, lv_pct(100), LV_SIZE_CONTENT);
|
||||
lv_obj_align(input_panel, LV_ALIGN_BOTTOM_MID, 0, 0);
|
||||
lv_obj_set_flex_align(input_panel, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);
|
||||
lv_obj_set_style_pad_all(input_panel, 5, 0);
|
||||
|
||||
// Input field
|
||||
inputField = lv_textarea_create(input_panel);
|
||||
lv_obj_set_flex_grow(inputField, 1);
|
||||
lv_obj_set_height(inputField, LV_PCT(100));
|
||||
lv_textarea_set_placeholder_text(inputField, "Type a message...");
|
||||
lv_textarea_set_one_line(inputField, true);
|
||||
|
||||
// Send button
|
||||
auto* send_btn = lv_btn_create(input_panel);
|
||||
lv_obj_set_size(send_btn, 50, LV_SIZE_CONTENT);
|
||||
//lv_obj_add_event_cb(send_btn, onSendClicked, LV_EVENT_CLICKED, this);
|
||||
|
||||
auto* btn_label = lv_label_create(send_btn);
|
||||
lv_label_set_text(btn_label, "SEND");
|
||||
lv_obj_center(btn_label);
|
||||
|
||||
lv_obj_set_flex_grow(messageList, 1);
|
||||
lv_obj_set_flex_grow(input_panel, 0);
|
||||
|
||||
//lv_obj_set_style_bg_color(messageList, lv_color_hex(0xFF0000), 0);
|
||||
//lv_obj_set_style_bg_color(input_panel, lv_color_hex(0x00FF00), 0);
|
||||
|
||||
//addDummyMessage("HELLO CHIRPCHAT!");
|
||||
//addDummyMessage("How's biz?");
|
||||
//addDummyMessage("Test");
|
||||
//addDummyMessage("Test empfangen in Linz");
|
||||
|
||||
// LoRa settings view
|
||||
loraView = new LoraView(grid);
|
||||
lv_obj_set_grid_cell(loraView->container, LV_GRID_ALIGN_STRETCH, 1, 1,
|
||||
LV_GRID_ALIGN_STRETCH, 1, 1);
|
||||
|
||||
//loraView->onDeviceActivation(std::bind(&ChirpChatterApp::onDeviceActivation, this));
|
||||
//loraView->onDeviceDeactivation(std::bind(&ChirpChatterApp::onDeviceDeactivation, this));
|
||||
|
||||
loraView->onDeviceActivation([this](std::shared_ptr<tt::hal::radio::RadioDevice> dev) { this->onDeviceActivation(dev); });
|
||||
loraView->onDeviceDeactivation([this](std::shared_ptr<tt::hal::radio::RadioDevice> dev) { this->onDeviceDeactivation(dev); });
|
||||
|
||||
lv_obj_add_event_cb(send_btn, [](lv_event_t * e) {
|
||||
lv_obj_t* input = lv_event_get_target_obj(e);
|
||||
ChirpChatterApp* self = (ChirpChatterApp*)lv_event_get_user_data(e);
|
||||
self->sendMessage();
|
||||
}, LV_EVENT_SHORT_CLICKED, (void*)this);
|
||||
|
||||
changeView(CCView_Msgs);
|
||||
}
|
||||
|
||||
void onRxPacket(hal::Device::Id id, const hal::radio::RxPacket& packet) {
|
||||
addPacketMessage(packet);
|
||||
}
|
||||
|
||||
void onDeviceActivation(std::shared_ptr<tt::hal::radio::RadioDevice> dev) {
|
||||
rxSubId = dev->subscribeRx([this](hal::Device::Id id, const hal::radio::RxPacket& packet) {
|
||||
this->onRxPacket(id, packet);
|
||||
});
|
||||
loraDevice = dev;
|
||||
std::ostringstream oss;
|
||||
oss << "Device \"" << dev->getName() << "\" online";
|
||||
|
||||
lv_label_set_text(progressText, oss.str().c_str());
|
||||
}
|
||||
|
||||
void onDeviceDeactivation(std::shared_ptr<tt::hal::radio::RadioDevice> dev) {
|
||||
dev->unsubscribeRx(rxSubId);
|
||||
loraDevice = nullptr;
|
||||
|
||||
lv_label_set_text(progressText, "Offline");
|
||||
}
|
||||
|
||||
void sendMessage() {
|
||||
std::string message = lv_textarea_get_text(inputField);
|
||||
std::vector<uint8_t> data;
|
||||
if (message == "!test1") {
|
||||
parseHexString("ffffffff1147fec0c60940e5810800009671ad09dd2a0e7841ce266a3d759e967dc32a16bf4d5eecafde28d82b690f22eccf968a", data);
|
||||
} else if (message == "!ack") {
|
||||
parseHexString("ffffffff1147fec0f1dee9ab81080000922bf53364151a15", data);
|
||||
} else if (message == "!gdn8") {
|
||||
parseHexString("ffffffff1147fec025ffdd7a81080000768023f848619a3782ddadb5f686dc", data);
|
||||
} else if (message == "!gm") {
|
||||
parseHexString("ffffffff1147fec08a27ff4b810800003185053566e837fb0b88ade5fc84d9a13e", data);
|
||||
} else if (message == "!ptest1") {
|
||||
parseHexString("ffffffff1147fec0ef0e5bd48108000035f4be1f4bf703b3cce235423dd218a0c9ec745032a1f04be19c", data);
|
||||
} else {
|
||||
data = std::vector<uint8_t>(message.begin(), message.end());
|
||||
}
|
||||
|
||||
loraDevice->transmit(tt::hal::radio::TxPacket{.data = data}, [this](hal::radio::RadioDevice::TxId id, hal::radio::RadioDevice::TransmissionState state) {
|
||||
this->onTxStatus(id, state);
|
||||
});
|
||||
}
|
||||
|
||||
void onTxStatus(hal::radio::RadioDevice::TxId id, hal::radio::RadioDevice::TransmissionState state) {
|
||||
using enum hal::radio::RadioDevice::TransmissionState;
|
||||
|
||||
switch (state) {
|
||||
case Queued:
|
||||
lv_label_set_text(progressText, "Message queued...");
|
||||
lv_bar_set_value(progressBar, 25, LV_ANIM_ON);
|
||||
break;
|
||||
case PendingTransmit:
|
||||
lv_label_set_text(progressText, "Message transmitting...");
|
||||
lv_bar_set_value(progressBar, 50, LV_ANIM_ON);
|
||||
break;
|
||||
case Transmitted:
|
||||
lv_label_set_text(progressText, "Message transmitted!\nReturn to receive.");
|
||||
lv_bar_set_value(progressBar, 100, LV_ANIM_ON);
|
||||
break;
|
||||
case Timeout:
|
||||
lv_label_set_text(progressText, "Message transmit timed out!");
|
||||
lv_bar_set_value(progressBar, 100, LV_ANIM_ON);
|
||||
break;
|
||||
case Error:
|
||||
lv_label_set_text(progressText, "Error transmitting message!");
|
||||
lv_bar_set_value(progressBar, 100, LV_ANIM_ON);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void changeView(const CCViews view) {
|
||||
lv_obj_add_flag(messageView, LV_OBJ_FLAG_HIDDEN);
|
||||
lv_obj_add_flag(loraView->container, LV_OBJ_FLAG_HIDDEN);
|
||||
|
||||
switch (view) {
|
||||
case CCView_Msgs:
|
||||
lv_obj_clear_flag(messageView, LV_OBJ_FLAG_HIDDEN);
|
||||
break;
|
||||
case CCView_LoraSettings:
|
||||
lv_obj_clear_flag(loraView->container, LV_OBJ_FLAG_HIDDEN);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
~ChirpChatterApp() override = default;
|
||||
};
|
||||
|
||||
extern const AppManifest manifest = {
|
||||
.id = "ChirpChatter",
|
||||
.name = "ChirpChatter",
|
||||
.icon = TT_ASSETS_APP_ICON_CHAT,
|
||||
.createApp = create<ChirpChatterApp>
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//#endif
|
||||
102
Tactility/Source/hal/radio/RadioDevice.cpp
Normal file
102
Tactility/Source/hal/radio/RadioDevice.cpp
Normal file
@ -0,0 +1,102 @@
|
||||
#include "Tactility/hal/radio/RadioDevice.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace tt::hal::radio {
|
||||
|
||||
constexpr const char* TAG = "RadioDevice";
|
||||
|
||||
bool RadioDevice::setModulation(const RadioDevice::Modulation newModulation) {
|
||||
// A bool is chosen over an enum class because:
|
||||
// - this is not tied to user input and
|
||||
// - the programmer can infer why it didn't work using
|
||||
// other methods such as getState() and canTransmit/Receive()
|
||||
const auto state = getState();
|
||||
if ((state == State::PendingOn) || (state == State::On)) {
|
||||
return false;
|
||||
} else if (!((newModulation == Modulation::None) || canTransmit(newModulation) || canReceive(newModulation))) {
|
||||
return false;
|
||||
} else {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
modulation = newModulation;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RadioDevice::Modulation RadioDevice::getModulation() const {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return modulation;
|
||||
}
|
||||
|
||||
RadioDevice::State RadioDevice::getState() const {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
return state; // Make copy because of thread safety
|
||||
}
|
||||
|
||||
void RadioDevice::setState(State newState) {
|
||||
auto lock = mutex.asScopedLock();
|
||||
lock.lock();
|
||||
|
||||
if (state != newState) {
|
||||
statePubSub.publish(getId(), newState);
|
||||
}
|
||||
|
||||
state = newState;
|
||||
}
|
||||
|
||||
void RadioDevice::publishRx(const RxPacket& packet) {
|
||||
mutex.lock();
|
||||
rxPubSub.publish(getId(), packet);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
const char* toString(RadioDevice::Modulation modulation) {
|
||||
using enum RadioDevice::Modulation;
|
||||
switch (modulation) {
|
||||
case None:
|
||||
return "none";
|
||||
case Fsk:
|
||||
return "FSK";
|
||||
case LoRa:
|
||||
return "LoRa";
|
||||
case LrFhss:
|
||||
return "LR-FHSS";
|
||||
default:
|
||||
return "Unkown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* toString(RadioDevice::Parameter parameter) {
|
||||
using enum RadioDevice::Parameter;
|
||||
switch (parameter) {
|
||||
case Power:
|
||||
return TT_STRINGIFY(Power);
|
||||
case Frequency:
|
||||
return TT_STRINGIFY(Frequency);
|
||||
case Bandwidth:
|
||||
return TT_STRINGIFY(Bandwidth);
|
||||
case SpreadFactor:
|
||||
return TT_STRINGIFY(SpreadFactor);
|
||||
case CodingRate:
|
||||
return TT_STRINGIFY(CodingRate);
|
||||
case SyncWord:
|
||||
return TT_STRINGIFY(SyncWord);
|
||||
case PreambleLength:
|
||||
return TT_STRINGIFY(PreambleLength);
|
||||
case FrequencyDeviation:
|
||||
return TT_STRINGIFY(FrequencyDeviation);
|
||||
case DataRate:
|
||||
return TT_STRINGIFY(DataRate);
|
||||
case AddressWidth:
|
||||
return TT_STRINGIFY(AddressWidth);
|
||||
case NarrowGrid:
|
||||
return TT_STRINGIFY(NarrowGrid);
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tt::hal::radio
|
||||
61
Tactility/Source/hal/radio/Unit.cpp
Normal file
61
Tactility/Source/hal/radio/Unit.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
#include "Tactility/hal/radio/Unit.h"
|
||||
#include <cstring>
|
||||
|
||||
namespace tt::hal::radio {
|
||||
|
||||
std::string Unit::toString() const {
|
||||
using tt::hal::radio::toString;
|
||||
return std::string(toString(prefix))+std::string(toString(unit));
|
||||
}
|
||||
|
||||
const char* toString(const Unit::Prefix prefix) {
|
||||
using enum Unit::Prefix;
|
||||
|
||||
switch (prefix) {
|
||||
case Femto:
|
||||
return "f";
|
||||
case Pico:
|
||||
return "p";
|
||||
case Nano:
|
||||
return "n";
|
||||
case Milli:
|
||||
return "m";
|
||||
case None:
|
||||
return "";
|
||||
case Kilo:
|
||||
return "k";
|
||||
case Mega:
|
||||
return "M";
|
||||
case Giga:
|
||||
return "G";
|
||||
case Terra:
|
||||
return "T";
|
||||
case Peta:
|
||||
return "P";
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
||||
|
||||
const char* toString(const Unit::Name unit) {
|
||||
using enum Unit::Name;
|
||||
|
||||
switch (unit) {
|
||||
case None:
|
||||
return "";
|
||||
case BitsPerSecond:
|
||||
return "bps";
|
||||
case BytesPerSecond:
|
||||
return "Bps";
|
||||
case Herz:
|
||||
return "Hz";
|
||||
case Decibel:
|
||||
return "dB";
|
||||
case DecibelMilliwatts:
|
||||
return "dBm";
|
||||
}
|
||||
|
||||
return "?";
|
||||
}
|
||||
|
||||
}
|
||||
@ -13,7 +13,8 @@ enum DeviceType {
|
||||
DEVICE_TYPE_SDCARD,
|
||||
DEVICE_TYPE_KEYBOARD,
|
||||
DEVICE_TYPE_POWER,
|
||||
DEVICE_TYPE_GPS
|
||||
DEVICE_TYPE_GPS,
|
||||
DEVICE_TYPE_RADIO
|
||||
};
|
||||
|
||||
typedef uint32_t DeviceId;
|
||||
|
||||
225
TactilityC/Include/tt_hal_radio.h
Normal file
225
TactilityC/Include/tt_hal_radio.h
Normal file
@ -0,0 +1,225 @@
|
||||
#pragma once
|
||||
|
||||
#include "tt_hal_device.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef void* RadioHandle;
|
||||
|
||||
enum RadioState {
|
||||
RADIO_PENDING_ON,
|
||||
RADIO_ON,
|
||||
RADIO_ERROR,
|
||||
RADIO_PENDING_OFF,
|
||||
RADIO_OFF
|
||||
};
|
||||
|
||||
enum Modulation {
|
||||
MODULATION_NONE,
|
||||
MODULATION_LORA,
|
||||
MODULATION_FSK,
|
||||
MODULATION_LRFHSS
|
||||
};
|
||||
|
||||
enum RadioParameter {
|
||||
RADIO_POWER,
|
||||
RADIO_FREQUENCY,
|
||||
RADIO_BANDWIDTH,
|
||||
RADIO_SPREADFACTOR,
|
||||
RADIO_CODINGRATE,
|
||||
RADIO_SYNCWORD,
|
||||
RADIO_PREAMBLES,
|
||||
RADIO_FREQDIV,
|
||||
RADIO_DATARATE,
|
||||
RADIO_ADDRWIDTH,
|
||||
RADIO_NARROWGRID
|
||||
};
|
||||
|
||||
enum RadioParameterStatus {
|
||||
RADIO_PARAM_UNAVAILABLE,
|
||||
RADIO_PARAM_VALERROR,
|
||||
RADIO_PARAM_SUCCESS
|
||||
};
|
||||
|
||||
enum RadioTxState {
|
||||
RADIO_TX_QUEUED,
|
||||
RADIO_TX_PENDING_TRANSMIT,
|
||||
RADIO_TX_TRANSMITTED,
|
||||
RADIO_TX_TIMEOUT,
|
||||
RADIO_TX_ERROR
|
||||
};
|
||||
|
||||
typedef int32_t RadioRxSubscriptionId;
|
||||
typedef int32_t RadioStateSubscriptionId;
|
||||
typedef int32_t RadioTxId;
|
||||
|
||||
struct RadioRxPacket {
|
||||
const uint8_t *data;
|
||||
uint32_t size;
|
||||
float rssi;
|
||||
float snr;
|
||||
};
|
||||
|
||||
struct RadioTxPacket {
|
||||
uint8_t *data;
|
||||
uint32_t size;
|
||||
uint32_t address;
|
||||
};
|
||||
|
||||
typedef void (*RadioStateCallback)(DeviceId id, RadioState state);
|
||||
typedef void (*RadioTxStateCallback)(RadioTxId id, RadioTxState state);
|
||||
typedef void (*RadioOnReceiveCallback)(DeviceId id, const RadioRxPacket* packet);
|
||||
|
||||
/**
|
||||
* Allocate a radio driver object for the specified radioId.
|
||||
* @param[in] radioId the identifier of the radio device
|
||||
* @return the radio handle
|
||||
*/
|
||||
RadioHandle tt_hal_radio_alloc(DeviceId radioId);
|
||||
|
||||
/**
|
||||
* Free the memory for the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
*/
|
||||
void tt_hal_radio_free(RadioHandle handle);
|
||||
|
||||
/**
|
||||
* Get the name for the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @return the name of the radio
|
||||
*/
|
||||
const char* tt_hal_radio_get_name(RadioHandle handle);
|
||||
|
||||
/**
|
||||
* Get the description for the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @return the description for the radio
|
||||
*/
|
||||
const char* tt_hal_radio_get_desc(RadioHandle handle);
|
||||
|
||||
|
||||
/**
|
||||
* Get the state for the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @return the state of the radio
|
||||
*/
|
||||
RadioState tt_hal_radio_get_state(RadioHandle handle);
|
||||
|
||||
/**
|
||||
* Set the modulation for the radio driver object.
|
||||
* The radio must not be started and it must be either capable
|
||||
* of reception or transmission of passed modulation.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] modulation the modulation type
|
||||
* @return true if the modulation could be set, false otherwise
|
||||
*/
|
||||
bool tt_hal_radio_set_modulation(RadioHandle handle, Modulation modulation);
|
||||
|
||||
/**
|
||||
* Get the modulation for the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @return the modulation type
|
||||
*/
|
||||
Modulation tt_hal_radio_get_modulation(RadioHandle handle);
|
||||
|
||||
/**
|
||||
* Try to set a parameter for the radio driver object.
|
||||
* The radio must not be started and it must be in the modulation mode
|
||||
* for the respective parameter.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] parameter the parameter
|
||||
* @param[in] value the value to set
|
||||
* @return status of the parameter set operation
|
||||
*/
|
||||
RadioParameterStatus tt_hal_radio_set_parameter(RadioHandle handle, RadioParameter parameter, float value);
|
||||
|
||||
/**
|
||||
* Try to get a parameter for the radio driver object.
|
||||
* The radio must be in the modulation mode for the respective parameter,
|
||||
* else the parameter is unavailable.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] parameter the parameter
|
||||
* @param[out] value retrieved value will be stored at this pointer
|
||||
* @return status of the parameter get operation
|
||||
*/
|
||||
RadioParameterStatus tt_hal_radio_get_parameter(RadioHandle handle, RadioParameter parameter, float *value);
|
||||
|
||||
/**
|
||||
* Get the unit string of a parameter.
|
||||
* If the parameter isn't available, the returned string is empty.
|
||||
* If the unit string does not fit into the provided character array,
|
||||
* it is truncated but always null terminated.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] parameter the parameter
|
||||
* @param[out] str character array to store the unit string into
|
||||
* @param[in] maxSize the maximum size the array str can hold
|
||||
*/
|
||||
void tt_hal_radio_get_parameter_unit_str(RadioHandle handle, RadioParameter parameter, char str[], unsigned maxSize);
|
||||
|
||||
/**
|
||||
* Check whenever the radio driver object can transmit a certain modulation.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] modulation the modulation type
|
||||
* @return true if capable, false otherwise
|
||||
*/
|
||||
bool tt_hal_radio_can_transmit(RadioHandle handle, Modulation modulation);
|
||||
|
||||
/**
|
||||
* Check whenever the radio driver object can receive a certain modulation.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] modulation the modulation type
|
||||
* @return true if capable, false otherwise
|
||||
*/
|
||||
bool tt_hal_radio_can_receive(RadioHandle handle, Modulation modulation);
|
||||
|
||||
/**
|
||||
* Starts the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @return true if the radio could be started, false otherwise
|
||||
*/
|
||||
bool tt_hal_radio_start(RadioHandle handle);
|
||||
|
||||
/**
|
||||
* Stops the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @return true if the radio could be stopped, false otherwise
|
||||
*/
|
||||
bool tt_hal_radio_stop(RadioHandle handle);
|
||||
|
||||
/**
|
||||
* Put a packet in the transmission queue of the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] packet packet to send (no special requirement for memory of data)
|
||||
* @param[in] callback function to call on transmission state change for the packet
|
||||
* @return the identifier for the transmission
|
||||
*/
|
||||
RadioTxId tt_hal_radio_transmit(RadioHandle handle, RadioTxPacket packet, RadioTxStateCallback callback);
|
||||
|
||||
/**
|
||||
* Subscribe for any received packet that the radio driver object receives.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] callback function to call on reception of a packet
|
||||
* @return the identifier for the subscription
|
||||
*/
|
||||
RadioRxSubscriptionId tt_hal_radio_subscribe_receive(RadioHandle handle, RadioOnReceiveCallback callback);
|
||||
|
||||
/**
|
||||
* Subscribe for any state change of the radio driver object.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] callback function to call when the state of the radio changes
|
||||
* @return the identifier for the subscription
|
||||
*/
|
||||
RadioStateSubscriptionId tt_hal_radio_subscribe_state(RadioHandle handle, RadioStateCallback callback);
|
||||
|
||||
/**
|
||||
* Unsubscribe for any received packet that the radio driver object receives.
|
||||
* @param[in] handle the radio driver handle
|
||||
* @param[in] id the identifier for the subscription
|
||||
*/
|
||||
void tt_hal_radio_unsubscribe_receive(RadioHandle handle, RadioRxSubscriptionId id);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@ -20,6 +20,8 @@ static tt::hal::Device::Type toTactilityDeviceType(DeviceType type) {
|
||||
return tt::hal::Device::Type::Power;
|
||||
case DEVICE_TYPE_GPS:
|
||||
return tt::hal::Device::Type::Gps;
|
||||
case DEVICE_TYPE_RADIO:
|
||||
return tt::hal::Device::Type::Radio;
|
||||
default:
|
||||
tt_crash("Device::Type not supported");
|
||||
}
|
||||
|
||||
352
TactilityC/Source/tt_hal_radio.cpp
Normal file
352
TactilityC/Source/tt_hal_radio.cpp
Normal file
@ -0,0 +1,352 @@
|
||||
#include "tt_hal_radio.h"
|
||||
|
||||
#include "Tactility/Check.h"
|
||||
#include "Tactility/hal/Device.h"
|
||||
#include "Tactility/hal/radio/RadioDevice.h"
|
||||
|
||||
auto constexpr TAG = "tt_hal_radio";
|
||||
|
||||
static RadioState fromCpp(tt::hal::radio::RadioDevice::State state);
|
||||
static tt::hal::radio::RadioDevice::State toCpp(RadioState state);
|
||||
static Modulation fromCpp(tt::hal::radio::RadioDevice::Modulation modulation);
|
||||
static tt::hal::radio::RadioDevice::Modulation toCpp(Modulation modulation);
|
||||
static RadioParameter fromCpp(tt::hal::radio::RadioDevice::Parameter parameter);
|
||||
static tt::hal::radio::RadioDevice::Parameter toCpp(RadioParameter parameter);
|
||||
static RadioParameterStatus fromCpp(tt::hal::radio::RadioDevice::ParameterStatus status);
|
||||
static tt::hal::radio::RadioDevice::ParameterStatus toCpp(RadioParameterStatus status);
|
||||
static RadioTxState fromCpp(tt::hal::radio::RadioDevice::TransmissionState state);
|
||||
static tt::hal::radio::RadioDevice::TransmissionState toCpp(RadioTxState state);
|
||||
|
||||
struct DeviceWrapper {
|
||||
std::shared_ptr<tt::hal::radio::RadioDevice> device;
|
||||
std::string name;
|
||||
std::string description;
|
||||
DeviceWrapper(std::shared_ptr<tt::hal::radio::RadioDevice> device)
|
||||
: device(device)
|
||||
, name(device->getName())
|
||||
, description(device->getDescription()) {}
|
||||
};
|
||||
|
||||
static std::shared_ptr<tt::hal::radio::RadioDevice> findValidRadioDevice(tt::hal::Device::Id id) {
|
||||
auto device = tt::hal::findDevice(id);
|
||||
if (device == nullptr || device->getType() != tt::hal::Device::Type::Radio) {
|
||||
return nullptr;
|
||||
}
|
||||
return std::reinterpret_pointer_cast<tt::hal::radio::RadioDevice>(device);
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
RadioHandle tt_hal_radio_alloc(DeviceId radioId) {
|
||||
auto radio = findValidRadioDevice(radioId);
|
||||
return new DeviceWrapper(radio);
|
||||
}
|
||||
|
||||
void tt_hal_radio_free(RadioHandle handle) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
delete wrapper;
|
||||
}
|
||||
|
||||
const char* tt_hal_radio_get_name(RadioHandle handle) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->name.c_str();
|
||||
}
|
||||
|
||||
const char* tt_hal_radio_get_desc(RadioHandle handle) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->description.c_str();
|
||||
}
|
||||
|
||||
RadioState tt_hal_radio_get_state(RadioHandle handle) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return fromCpp(wrapper->device->getState());
|
||||
}
|
||||
|
||||
bool tt_hal_radio_set_modulation(RadioHandle handle, Modulation modulation) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->setModulation(toCpp(modulation));
|
||||
}
|
||||
|
||||
Modulation tt_hal_radio_get_modulation(RadioHandle handle) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return fromCpp(wrapper->device->getModulation());
|
||||
}
|
||||
|
||||
RadioParameterStatus tt_hal_radio_set_parameter(RadioHandle handle, RadioParameter parameter, float value) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return fromCpp(wrapper->device->setParameter(toCpp(parameter), value));
|
||||
}
|
||||
|
||||
RadioParameterStatus tt_hal_radio_get_parameter(RadioHandle handle, RadioParameter parameter, float *value) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
// This is a programming error not an input error, thus assert.
|
||||
// TODO: Does TactC even know assert? Maybe putting a crash is the optimal solution.
|
||||
assert(value);
|
||||
return fromCpp(wrapper->device->getParameter(toCpp(parameter), *value));
|
||||
}
|
||||
|
||||
void tt_hal_radio_get_parameter_unit_str(RadioHandle handle, RadioParameter parameter, char str[], unsigned maxSize) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
assert(str);
|
||||
std::string unitString = wrapper->device->getParameterUnit(toCpp(parameter)).toString();
|
||||
size_t i = 0;
|
||||
for (; i < (maxSize - 1); ++i) {
|
||||
str[i] = unitString[i];
|
||||
}
|
||||
str[i] = '\0';
|
||||
}
|
||||
|
||||
bool tt_hal_radio_can_transmit(RadioHandle handle, Modulation modulation) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->canTransmit(toCpp(modulation));
|
||||
}
|
||||
|
||||
bool tt_hal_radio_can_receive(RadioHandle handle, Modulation modulation) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->canReceive(toCpp(modulation));
|
||||
}
|
||||
|
||||
bool tt_hal_radio_start(RadioHandle handle) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->start();
|
||||
}
|
||||
|
||||
bool tt_hal_radio_stop(RadioHandle handle) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->stop();
|
||||
}
|
||||
|
||||
RadioTxId tt_hal_radio_transmit(RadioHandle handle, RadioTxPacket packet, RadioTxStateCallback callback) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
auto ttPacket = tt::hal::radio::TxPacket{
|
||||
.data = std::vector<uint8_t>(packet.data, packet.data + packet.size),
|
||||
.address = packet.address
|
||||
};
|
||||
return wrapper->device->transmit(ttPacket, [callback](tt::hal::radio::RadioDevice::TxId id, tt::hal::radio::RadioDevice::TransmissionState state) {
|
||||
if (callback) {
|
||||
callback(id, fromCpp(state));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RadioStateSubscriptionId tt_hal_radio_subscribe_state(RadioHandle handle, RadioStateCallback callback) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->subscribeStateChange([callback](tt::hal::Device::Id id, tt::hal::radio::RadioDevice::State state) {
|
||||
if (callback) {
|
||||
callback(id, fromCpp(state));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RadioRxSubscriptionId tt_hal_radio_subscribe_receive(RadioHandle handle, RadioOnReceiveCallback callback) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
return wrapper->device->subscribeRx([callback](tt::hal::Device::Id id, const tt::hal::radio::RxPacket& ttPacket) {
|
||||
if (callback) {
|
||||
auto ttcPacket = RadioRxPacket{
|
||||
.data = ttPacket.data.data(),
|
||||
.size = ttPacket.data.size(),
|
||||
.rssi = ttPacket.rssi,
|
||||
.snr = ttPacket.snr
|
||||
};
|
||||
callback(id, &ttcPacket);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tt_hal_radio_unsubscribe_receive(RadioHandle handle, RadioRxSubscriptionId id) {
|
||||
auto wrapper = static_cast<DeviceWrapper*>(handle);
|
||||
wrapper->device->unsubscribeRx(id);
|
||||
}
|
||||
}
|
||||
|
||||
static RadioState fromCpp(tt::hal::radio::RadioDevice::State state) {
|
||||
switch (state) {
|
||||
case tt::hal::radio::RadioDevice::State::PendingOn:
|
||||
return RADIO_PENDING_ON;
|
||||
case tt::hal::radio::RadioDevice::State::On:
|
||||
return RADIO_ON;
|
||||
case tt::hal::radio::RadioDevice::State::Error:
|
||||
return RADIO_ERROR;
|
||||
case tt::hal::radio::RadioDevice::State::PendingOff:
|
||||
return RADIO_PENDING_OFF;
|
||||
case tt::hal::radio::RadioDevice::State::Off:
|
||||
return RADIO_OFF;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", state);
|
||||
tt_crash("Radio state not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static tt::hal::radio::RadioDevice::State toCpp(RadioState state) {
|
||||
switch (state) {
|
||||
case RADIO_PENDING_ON:
|
||||
return tt::hal::radio::RadioDevice::State::PendingOn;
|
||||
case RADIO_ON:
|
||||
return tt::hal::radio::RadioDevice::State::On;
|
||||
case RADIO_ERROR:
|
||||
return tt::hal::radio::RadioDevice::State::Error;
|
||||
case RADIO_PENDING_OFF:
|
||||
return tt::hal::radio::RadioDevice::State::PendingOff;
|
||||
case RADIO_OFF:
|
||||
return tt::hal::radio::RadioDevice::State::Off;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", state);
|
||||
tt_crash("Radio state not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static Modulation fromCpp(tt::hal::radio::RadioDevice::Modulation modulation) {
|
||||
switch (modulation) {
|
||||
case tt::hal::radio::RadioDevice::Modulation::None:
|
||||
return MODULATION_NONE;
|
||||
case tt::hal::radio::RadioDevice::Modulation::LoRa:
|
||||
return MODULATION_LORA;
|
||||
case tt::hal::radio::RadioDevice::Modulation::Fsk:
|
||||
return MODULATION_FSK;
|
||||
case tt::hal::radio::RadioDevice::Modulation::LrFhss:
|
||||
return MODULATION_LRFHSS;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", modulation);
|
||||
tt_crash("Modulation not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static tt::hal::radio::RadioDevice::Modulation toCpp(Modulation modulation) {
|
||||
switch (modulation) {
|
||||
case MODULATION_NONE:
|
||||
return tt::hal::radio::RadioDevice::Modulation::None;
|
||||
case MODULATION_LORA:
|
||||
return tt::hal::radio::RadioDevice::Modulation::LoRa;
|
||||
case MODULATION_FSK:
|
||||
return tt::hal::radio::RadioDevice::Modulation::Fsk;
|
||||
case MODULATION_LRFHSS:
|
||||
return tt::hal::radio::RadioDevice::Modulation::LrFhss;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", modulation);
|
||||
tt_crash("Modulation not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static RadioParameter fromCpp(tt::hal::radio::RadioDevice::Parameter parameter) {
|
||||
switch (parameter) {
|
||||
case tt::hal::radio::RadioDevice::Parameter::Power:
|
||||
return RADIO_POWER;
|
||||
case tt::hal::radio::RadioDevice::Parameter::Frequency:
|
||||
return RADIO_FREQUENCY;
|
||||
case tt::hal::radio::RadioDevice::Parameter::Bandwidth:
|
||||
return RADIO_BANDWIDTH;
|
||||
case tt::hal::radio::RadioDevice::Parameter::SpreadFactor:
|
||||
return RADIO_SPREADFACTOR;
|
||||
case tt::hal::radio::RadioDevice::Parameter::CodingRate:
|
||||
return RADIO_CODINGRATE;
|
||||
case tt::hal::radio::RadioDevice::Parameter::SyncWord:
|
||||
return RADIO_SYNCWORD;
|
||||
case tt::hal::radio::RadioDevice::Parameter::PreambleLength:
|
||||
return RADIO_PREAMBLES;
|
||||
case tt::hal::radio::RadioDevice::Parameter::FrequencyDeviation:
|
||||
return RADIO_FREQDIV;
|
||||
case tt::hal::radio::RadioDevice::Parameter::DataRate:
|
||||
return RADIO_DATARATE;
|
||||
case tt::hal::radio::RadioDevice::Parameter::AddressWidth:
|
||||
return RADIO_ADDRWIDTH;
|
||||
case tt::hal::radio::RadioDevice::Parameter::NarrowGrid:
|
||||
return RADIO_NARROWGRID;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", parameter);
|
||||
tt_crash("Parameter not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static tt::hal::radio::RadioDevice::Parameter toCpp(RadioParameter parameter) {
|
||||
switch (parameter) {
|
||||
case RADIO_POWER:
|
||||
return tt::hal::radio::RadioDevice::Parameter::Power;
|
||||
case RADIO_FREQUENCY:
|
||||
return tt::hal::radio::RadioDevice::Parameter::Frequency;
|
||||
case RADIO_BANDWIDTH:
|
||||
return tt::hal::radio::RadioDevice::Parameter::Bandwidth;
|
||||
case RADIO_SPREADFACTOR:
|
||||
return tt::hal::radio::RadioDevice::Parameter::SpreadFactor;
|
||||
case RADIO_CODINGRATE:
|
||||
return tt::hal::radio::RadioDevice::Parameter::CodingRate;
|
||||
case RADIO_SYNCWORD:
|
||||
return tt::hal::radio::RadioDevice::Parameter::SyncWord;
|
||||
case RADIO_PREAMBLES:
|
||||
return tt::hal::radio::RadioDevice::Parameter::PreambleLength;
|
||||
case RADIO_FREQDIV:
|
||||
return tt::hal::radio::RadioDevice::Parameter::FrequencyDeviation;
|
||||
case RADIO_DATARATE:
|
||||
return tt::hal::radio::RadioDevice::Parameter::DataRate;
|
||||
case RADIO_ADDRWIDTH:
|
||||
return tt::hal::radio::RadioDevice::Parameter::AddressWidth;
|
||||
case RADIO_NARROWGRID:
|
||||
return tt::hal::radio::RadioDevice::Parameter::NarrowGrid;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", parameter);
|
||||
tt_crash("Parameter not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static RadioParameterStatus fromCpp(tt::hal::radio::RadioDevice::ParameterStatus status) {
|
||||
switch (status) {
|
||||
case tt::hal::radio::RadioDevice::ParameterStatus::Unavailable:
|
||||
return RADIO_PARAM_UNAVAILABLE;
|
||||
case tt::hal::radio::RadioDevice::ParameterStatus::ValueError:
|
||||
return RADIO_PARAM_VALERROR;
|
||||
case tt::hal::radio::RadioDevice::ParameterStatus::Success:
|
||||
return RADIO_PARAM_SUCCESS;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", status);
|
||||
tt_crash("Parameter status not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static tt::hal::radio::RadioDevice::ParameterStatus toCpp(RadioParameterStatus status) {
|
||||
switch (status) {
|
||||
case RADIO_PARAM_UNAVAILABLE:
|
||||
return tt::hal::radio::RadioDevice::ParameterStatus::Unavailable;
|
||||
case RADIO_PARAM_VALERROR:
|
||||
return tt::hal::radio::RadioDevice::ParameterStatus::ValueError;
|
||||
case RADIO_PARAM_SUCCESS:
|
||||
return tt::hal::radio::RadioDevice::ParameterStatus::Success;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", status);
|
||||
tt_crash("Parameter status not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static RadioTxState fromCpp(tt::hal::radio::RadioDevice::TransmissionState state) {
|
||||
switch (state) {
|
||||
case tt::hal::radio::RadioDevice::TransmissionState::Queued:
|
||||
return RADIO_TX_QUEUED;
|
||||
case tt::hal::radio::RadioDevice::TransmissionState::PendingTransmit:
|
||||
return RADIO_TX_PENDING_TRANSMIT;
|
||||
case tt::hal::radio::RadioDevice::TransmissionState::Transmitted:
|
||||
return RADIO_TX_TRANSMITTED;
|
||||
case tt::hal::radio::RadioDevice::TransmissionState::Timeout:
|
||||
return RADIO_TX_TIMEOUT;
|
||||
case tt::hal::radio::RadioDevice::TransmissionState::Error:
|
||||
return RADIO_TX_ERROR;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", state);
|
||||
tt_crash("Transmission state not supported");
|
||||
}
|
||||
}
|
||||
|
||||
static tt::hal::radio::RadioDevice::TransmissionState toCpp(RadioTxState state) {
|
||||
switch (state) {
|
||||
case RADIO_TX_QUEUED:
|
||||
return tt::hal::radio::RadioDevice::TransmissionState::Queued;
|
||||
case RADIO_TX_PENDING_TRANSMIT:
|
||||
return tt::hal::radio::RadioDevice::TransmissionState::PendingTransmit;
|
||||
case RADIO_TX_TRANSMITTED:
|
||||
return tt::hal::radio::RadioDevice::TransmissionState::Transmitted;
|
||||
case RADIO_TX_TIMEOUT:
|
||||
return tt::hal::radio::RadioDevice::TransmissionState::Timeout;
|
||||
case RADIO_TX_ERROR:
|
||||
return tt::hal::radio::RadioDevice::TransmissionState::Error;
|
||||
default:
|
||||
TT_LOG_W(TAG, "Unknown enum \"%d\" passed!", state);
|
||||
tt_crash("Transmission state not supported");
|
||||
}
|
||||
}
|
||||
@ -10,6 +10,7 @@
|
||||
#include "tt_hal_display.h"
|
||||
#include "tt_hal_i2c.h"
|
||||
#include "tt_hal_touch.h"
|
||||
#include "tt_hal_radio.h"
|
||||
#include "tt_kernel.h"
|
||||
#include "tt_lvgl.h"
|
||||
#include "tt_lvgl_keyboard.h"
|
||||
@ -30,6 +31,7 @@
|
||||
#include <esp_log.h>
|
||||
#include <esp_http_client.h>
|
||||
#include <cassert>
|
||||
#include <cstdio>
|
||||
|
||||
#include <lvgl.h>
|
||||
|
||||
@ -108,6 +110,52 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(isxdigit),
|
||||
ESP_ELFSYM_EXPORT(tolower),
|
||||
ESP_ELFSYM_EXPORT(toupper),
|
||||
// <cstdio> - TODO: a clanker made this, properly vet this list!
|
||||
ESP_ELFSYM_EXPORT(remove),
|
||||
ESP_ELFSYM_EXPORT(rename),
|
||||
ESP_ELFSYM_EXPORT(tmpfile),
|
||||
ESP_ELFSYM_EXPORT(fclose),
|
||||
ESP_ELFSYM_EXPORT(fflush),
|
||||
ESP_ELFSYM_EXPORT(fopen),
|
||||
ESP_ELFSYM_EXPORT(freopen),
|
||||
ESP_ELFSYM_EXPORT(setbuf),
|
||||
ESP_ELFSYM_EXPORT(setvbuf),
|
||||
ESP_ELFSYM_EXPORT(fprintf),
|
||||
ESP_ELFSYM_EXPORT(fscanf),
|
||||
ESP_ELFSYM_EXPORT(printf),
|
||||
ESP_ELFSYM_EXPORT(scanf),
|
||||
ESP_ELFSYM_EXPORT(snprintf),
|
||||
ESP_ELFSYM_EXPORT(sprintf),
|
||||
ESP_ELFSYM_EXPORT(sscanf),
|
||||
ESP_ELFSYM_EXPORT(vfprintf),
|
||||
ESP_ELFSYM_EXPORT(vfscanf),
|
||||
ESP_ELFSYM_EXPORT(vprintf),
|
||||
ESP_ELFSYM_EXPORT(vscanf),
|
||||
ESP_ELFSYM_EXPORT(vsnprintf),
|
||||
ESP_ELFSYM_EXPORT(vsprintf),
|
||||
ESP_ELFSYM_EXPORT(vsscanf),
|
||||
ESP_ELFSYM_EXPORT(fgetc),
|
||||
ESP_ELFSYM_EXPORT(fgets),
|
||||
ESP_ELFSYM_EXPORT(fputc),
|
||||
ESP_ELFSYM_EXPORT(fputs),
|
||||
ESP_ELFSYM_EXPORT(getc),
|
||||
ESP_ELFSYM_EXPORT(getchar),
|
||||
ESP_ELFSYM_EXPORT(gets),
|
||||
ESP_ELFSYM_EXPORT(putc),
|
||||
ESP_ELFSYM_EXPORT(putchar),
|
||||
ESP_ELFSYM_EXPORT(puts),
|
||||
ESP_ELFSYM_EXPORT(ungetc),
|
||||
ESP_ELFSYM_EXPORT(fread),
|
||||
ESP_ELFSYM_EXPORT(fwrite),
|
||||
ESP_ELFSYM_EXPORT(fgetpos),
|
||||
ESP_ELFSYM_EXPORT(fseek),
|
||||
ESP_ELFSYM_EXPORT(fsetpos),
|
||||
ESP_ELFSYM_EXPORT(ftell),
|
||||
ESP_ELFSYM_EXPORT(rewind),
|
||||
ESP_ELFSYM_EXPORT(clearerr),
|
||||
ESP_ELFSYM_EXPORT(feof),
|
||||
ESP_ELFSYM_EXPORT(ferror),
|
||||
ESP_ELFSYM_EXPORT(perror),
|
||||
// ESP-IDF
|
||||
ESP_ELFSYM_EXPORT(esp_log),
|
||||
ESP_ELFSYM_EXPORT(esp_log_write),
|
||||
@ -220,6 +268,24 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_supported),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_alloc),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_free),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_alloc),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_free),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_get_name),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_get_desc),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_get_state),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_set_modulation),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_get_modulation),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_set_parameter),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_get_parameter),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_get_parameter_unit_str),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_can_transmit),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_can_receive),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_start),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_stop),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_transmit),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_subscribe_state),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_subscribe_receive),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_radio_unsubscribe_receive),
|
||||
ESP_ELFSYM_EXPORT(tt_hal_touch_driver_get_touched_points),
|
||||
ESP_ELFSYM_EXPORT(tt_kernel_delay_millis),
|
||||
ESP_ELFSYM_EXPORT(tt_kernel_delay_micros),
|
||||
@ -320,11 +386,16 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(lv_color_hex),
|
||||
ESP_ELFSYM_EXPORT(lv_color_make),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_create),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_clean),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_delete),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_add_event_cb),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_add_state),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_align_to),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_clear_state),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_parent),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_child),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_child_count),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_height),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_width),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_coords),
|
||||
@ -338,6 +409,8 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_user_data),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_user_data),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_remove_flag),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_remove_state),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_has_state),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_add_flag),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_pos),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_flex_align),
|
||||
@ -349,6 +422,7 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_bg_image_opa),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_bg_image_recolor),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_bg_image_recolor_opa),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_flex_grow),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_margin_hor),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_margin_ver),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_margin_top),
|
||||
@ -380,6 +454,7 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_text_outline_stroke_opa),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_text_outline_stroke_width),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_layout),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_x),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_y),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_size),
|
||||
@ -439,6 +514,7 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(lv_dropdown_get_option_count),
|
||||
ESP_ELFSYM_EXPORT(lv_dropdown_get_option_index),
|
||||
ESP_ELFSYM_EXPORT(lv_dropdown_get_options),
|
||||
ESP_ELFSYM_EXPORT(lv_dropdown_get_selected),
|
||||
ESP_ELFSYM_EXPORT(lv_dropdown_set_dir),
|
||||
ESP_ELFSYM_EXPORT(lv_dropdown_set_options),
|
||||
ESP_ELFSYM_EXPORT(lv_dropdown_set_options_static),
|
||||
@ -459,6 +535,7 @@ const esp_elfsym elf_symbols[] {
|
||||
ESP_ELFSYM_EXPORT(lv_textarea_get_label),
|
||||
ESP_ELFSYM_EXPORT(lv_textarea_get_max_length),
|
||||
ESP_ELFSYM_EXPORT(lv_textarea_get_one_line),
|
||||
ESP_ELFSYM_EXPORT(lv_textarea_get_text),
|
||||
ESP_ELFSYM_EXPORT(lv_textarea_set_one_line),
|
||||
ESP_ELFSYM_EXPORT(lv_textarea_set_accepted_chars),
|
||||
ESP_ELFSYM_EXPORT(lv_textarea_set_align),
|
||||
@ -480,6 +557,74 @@ const esp_elfsym elf_symbols[] {
|
||||
// lv_pct
|
||||
ESP_ELFSYM_EXPORT(lv_pct),
|
||||
ESP_ELFSYM_EXPORT(lv_pct_to_px),
|
||||
// grids - TODO: This slopmachine generated list should be properly integrated
|
||||
ESP_ELFSYM_EXPORT(lv_grid_init),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_grid_dsc_array),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_grid_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_grid_cell),
|
||||
ESP_ELFSYM_EXPORT(lv_grid_fr),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_row_dsc_array),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_column_dsc_array),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_row_align),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_column_align),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_cell_column_pos),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_cell_column_span),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_cell_row_pos),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_cell_row_span),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_cell_x_align),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_grid_cell_y_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_row_dsc_array),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_column_dsc_array),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_row_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_column_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_cell_column_pos),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_cell_column_span),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_cell_row_pos),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_cell_row_span),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_cell_x_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_set_style_grid_cell_y_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_row_dsc_array),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_column_dsc_array),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_row_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_column_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_cell_column_pos),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_cell_column_span),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_cell_row_pos),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_cell_row_span),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_cell_x_align),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_get_style_grid_cell_y_align),
|
||||
ESP_ELFSYM_EXPORT(lv_group_focus_obj),
|
||||
ESP_ELFSYM_EXPORT(lv_group_get_default),
|
||||
ESP_ELFSYM_EXPORT(lv_group_add_obj),
|
||||
// lv_style
|
||||
ESP_ELFSYM_EXPORT(lv_style_init),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_bg_color),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_bg_opa),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_border_width),
|
||||
ESP_ELFSYM_EXPORT(lv_style_set_border_color),
|
||||
ESP_ELFSYM_EXPORT(lv_color_black),
|
||||
ESP_ELFSYM_EXPORT(lv_obj_add_style),
|
||||
// lv_slider
|
||||
ESP_ELFSYM_EXPORT(lv_slider_create),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_set_value),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_set_start_value),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_set_range),
|
||||
//ESP_ELFSYM_EXPORT(lv_slider_set_min_value),
|
||||
//ESP_ELFSYM_EXPORT(lv_slider_set_max_value),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_set_mode),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_set_orientation),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_get_value),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_get_left_value),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_get_min_value),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_get_max_value),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_is_dragged),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_get_mode),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_get_orientation),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_is_symmetrical),
|
||||
ESP_ELFSYM_EXPORT(lv_slider_bind_value),
|
||||
//lv_snprintf
|
||||
ESP_ELFSYM_EXPORT(lv_snprintf),
|
||||
|
||||
// delimiter
|
||||
ESP_ELFSYM_END
|
||||
};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user