1 Commits
Author SHA1 Message Date
MightyPork c4efa5ddaa Enable double buffered mode in USB 2018-03-04 16:35:00 +01:00
42 changed files with 116 additions and 1380 deletions
+2 -1
View File
@@ -109,6 +109,7 @@ extern uint32_t SystemCoreClock;
#define configQUEUE_REGISTRY_SIZE 0
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configENABLE_BACKWARD_COMPATIBILITY 0
#define configUSE_COUNTING_SEMAPHORES 0
#define configUSE_TIMERS 0
#define configTIMER_TASK_PRIORITY TSK_TIMERS_PRIO // above normal
@@ -151,7 +152,7 @@ to exclude the API function. */
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 5
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#elif defined(STM32F072xB)
#elif defined(GEX_PLAT_F072_DISCOVERY)
// This is for F072
#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 3
#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 1
+7 -43
View File
@@ -4,11 +4,11 @@
// TinyFrame integration
//
#include <USB/usb_device.h>
#include "platform.h"
#include "task_main.h"
#include "USB/usbd_cdc_if.h"
#include "USB/usb_device.h"
#include "TinyFrame.h"
extern osSemaphoreId semVcomTxReadyHandle;
@@ -16,30 +16,6 @@ extern osMutexId mutTinyFrameTxHandle;
void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
{
#if 1
const uint32_t real_size = len;
// Padding to a multiple of 64 bytes - this is supposed to maximize the bulk transfer speed
if (len&0x3F) {
uint32_t pad = (64 - (len&0x3F));
memset((void *) (buff + len), 0, pad);
len += pad; // padding to a multiple of 64 (size of the endpoint)
}
// We bypass the USBD driver library's overhead by using the HAL function directly
assert_param(HAL_OK == HAL_PCD_EP_Transmit(hUsbDeviceFS.pData, CDC_IN_EP, (uint8_t *) buff, len));
// The buffer is the TF transmit buffer, we can't leave it to work asynchronously because
// the next call could modify it before it's been transmitted (in the case of a chunked / multi-part frame)
// the assumption here is that all until the last chunk use the full buffer capacity
if (real_size == TF_SENDBUF_LEN) {
if (pdTRUE != xSemaphoreTake(semVcomTxReadyHandle, 100)) {
TF_Error("Tx stalled in WriteImpl");
return;
}
}
#else
(void) tf;
#define CHUNK 64 // same as TF_SENDBUF_LEN, so we should always have only one run of the loop
int32_t total = (int32_t) len;
@@ -53,34 +29,24 @@ void TF_WriteImpl(TinyFrame *tf, const uint8_t *buff, uint32_t len)
const uint16_t chunksize = (uint16_t) MIN(total, CHUNK);
// this is an attempt to speed it up a little by removing a couple levels of indirection
assert_param(HAL_OK == HAL_PCD_EP_Transmit(hUsbDeviceFS.pData, CDC_IN_EP, (uint8_t *) buff, chunksize));
// assert_param(HAL_OK == HAL_PCD_EP_Transmit(hUsbDeviceFS.pData, CDC_IN_EP, (uint8_t *) buff, chunksize));
// USBD_LL_Transmit(&hUsbDeviceFS, CDC_IN_EP, (uint8_t *) buff, chunksize);
// assert_param(USBD_OK == CDC_Transmit_FS((uint8_t *) buff, chunksize));
assert_param(USBD_OK == CDC_Transmit_FS((uint8_t *) buff, chunksize));
buff += chunksize;
total -= chunksize;
}
#endif
}
/** Claim the TX interface before composing and sending a frame */
bool TF_ClaimTx(TinyFrame *tf)
{
(void) tf;
// assert_param(!inIRQ()); // useless delay
assert_param(pdTRUE == xSemaphoreTake(mutTinyFrameTxHandle, 5000)); // trips the wd
// The last chunk from some previous frame may still be being transmitted,
// wait for it to finish (the semaphore is given in the CDC tx done handler)
if (pdTRUE != xSemaphoreTake(semVcomTxReadyHandle, 100)) {
TF_Error("Tx stalled in Claim");
// release the guarding mutex again
assert_param(pdTRUE == xSemaphoreGive(mutTinyFrameTxHandle));
return false;
}
// assert_param(osThreadGetId() != tskMainHandle);
assert_param(!inIRQ());
assert_param(osOK == osMutexWait(mutTinyFrameTxHandle, 5000));
return true;
}
@@ -88,7 +54,5 @@ bool TF_ClaimTx(TinyFrame *tf)
void TF_ReleaseTx(TinyFrame *tf)
{
(void) tf;
assert_param(pdTRUE == xSemaphoreGive(mutTinyFrameTxHandle));
// the last payload is sent asynchronously
assert_param(osOK == osMutexRelease(mutTinyFrameTxHandle));
}
+3 -7
View File
@@ -870,11 +870,7 @@ static inline uint32_t _TF_FN TF_ComposeTail(uint8_t *outbuff, TF_CKSUM *cksum)
*/
static bool _TF_FN TF_SendFrame_Begin(TinyFrame *tf, TF_Msg *msg, TF_Listener listener, TF_TICKS timeout)
{
bool suc = TF_ClaimTx(tf);
if (!suc) {
TF_Error("TF lock not free");
return false;
}
TF_TRY(TF_ClaimTx(tf));
tf->tx_pos = (uint32_t) TF_ComposeHead(tf, tf->sendbuf, msg); // frame ID is incremented here if it's not a response
tf->tx_len = msg->len;
@@ -1035,10 +1031,10 @@ bool _TF_FN TF_Query_Multipart(TinyFrame *tf, TF_Msg *msg, TF_Listener listener,
return TF_Query(tf, msg, listener, timeout);
}
bool _TF_FN TF_Respond_Multipart(TinyFrame *tf, TF_Msg *msg)
void _TF_FN TF_Respond_Multipart(TinyFrame *tf, TF_Msg *msg)
{
msg->data = NULL;
return TF_Respond(tf, msg);
TF_Respond(tf, msg);
}
void _TF_FN TF_Multipart_Payload(TinyFrame *tf, const uint8_t *buff, uint32_t length)
+1 -1
View File
@@ -369,7 +369,7 @@ bool TF_Query_Multipart(TinyFrame *tf, TF_Msg *msg, TF_Listener listener, TF_TIC
* TF_Respond() with multipart payload.
* msg.data is ignored and set to NULL
*/
bool TF_Respond_Multipart(TinyFrame *tf, TF_Msg *msg);
void TF_Respond_Multipart(TinyFrame *tf, TF_Msg *msg);
/**
* Send the payload for a started multipart frame. This can be called multiple times
+3 -1
View File
@@ -313,8 +313,10 @@ void USBD_CDC_TransmitDone(USBD_HandleTypeDef *pdev)
assert_param(semVcomTxReadyHandle != NULL);
assert_param(inIRQ());
if (uxSemaphoreGetCount(semVcomTxReadyHandle) == 1) return;
portBASE_TYPE taskWoken = pdFALSE;
assert_param(pdTRUE == xSemaphoreGiveFromISR(semVcomTxReadyHandle, &taskWoken));
assert_param(xSemaphoreGiveFromISR(semVcomTxReadyHandle, &taskWoken) == pdTRUE);
portYIELD_FROM_ISR(taskWoken);
}
/* USER CODE END PRIVATE_FUNCTIONS_IMPLEMENTATION */
+16 -8
View File
@@ -84,13 +84,13 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef* pcdHandle)
__HAL_RCC_USB_CLK_ENABLE();
/* Peripheral interrupt init */
#if GEX_PLAT_F103_BLUEPILL
#if defined(GEX_PLAT_F103_BLUEPILL)
HAL_NVIC_SetPriority(USB_LP_CAN1_RX0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
#elif STM32F072xB
#elif defined(GEX_PLAT_F072_DISCOVERY)
HAL_NVIC_SetPriority(USB_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(USB_IRQn);
#elif GEX_PLAT_F303_DISCOVERY
#elif defined(GEX_PLAT_F303_DISCOVERY)
// Pins need to be configured here
/**USB GPIO Configuration
@@ -149,11 +149,11 @@ void HAL_PCD_MspDeInit(PCD_HandleTypeDef* pcdHandle)
__HAL_RCC_USB_CLK_DISABLE();
/* Peripheral interrupt Deinit*/
#if GEX_PLAT_F103_BLUEPILL
#if defined(GEX_PLAT_F103_BLUEPILL)
HAL_NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
#elif STM32F072xB
#elif defined(GEX_PLAT_F072_DISCOVERY)
HAL_NVIC_DisableIRQ(USB_IRQn);
#elif GEX_PLAT_F303_DISCOVERY
#elif defined(GEX_PLAT_F303_DISCOVERY)
HAL_NVIC_DisableIRQ(USB_LP_CAN_RX0_IRQn);
#else
#error "BAD PLATFORM"
@@ -397,8 +397,16 @@ USBD_StatusTypeDef USBD_LL_Init (USBD_HandleTypeDef *pdev)
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , MSC_EPOUT_ADDR , PCD_SNG_BUF, ptr += 64); // 64
// CDC endpoints, EP2 two-way and EP3 in-only
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_SNG_BUF, ptr += 64); // 64
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_SNG_BUF, ptr += 64); // 64
uint32_t buf1addr, buf2addr;
buf1addr = (ptr += 64);
buf2addr = (ptr += 64);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_IN_EP , PCD_DBL_BUF, buf1addr | (buf2addr << 16)); // 64
buf1addr = (ptr += 64);
buf2addr = (ptr += 64);
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_OUT_EP , PCD_DBL_BUF, buf1addr | (buf2addr << 16)); // 64
HAL_PCDEx_PMAConfig((PCD_HandleTypeDef*)pdev->pData , CDC_CMD_EP , PCD_SNG_BUF, ptr += 16); // 16
(void)ptr;
#endif
+1 -1
View File
@@ -99,7 +99,7 @@
#define CDC_CUSTOM_EPS
#define CDC_IN_EP 0x82 /* EP1 for data IN */
#define CDC_OUT_EP 0x02 /* EP1 for data OUT */
#define CDC_OUT_EP 0x04 /* EP1 for data OUT */
#define CDC_CMD_EP 0x83 /* EP2 for CDC commands */
/** @defgroup USBD_Exported_Macros
+4 -4
View File
@@ -65,7 +65,7 @@ static void settings_bulkread_cb(BulkRead *bulk, uint32_t chunk, uint8_t *buffer
if (buffer == NULL) {
free_ck(bulk);
iw_end();
// dbg("INI read complete.");
dbg("INI read complete.");
return;
}
@@ -81,7 +81,7 @@ static void settings_bulkread_cb(BulkRead *bulk, uint32_t chunk, uint8_t *buffer
*/
static TF_Result lst_ini_export(TinyFrame *tf, TF_Msg *msg)
{
// dbg("Bulk read INI file");
dbg("Bulk read INI file");
BulkRead *bulk = malloc_ck(sizeof(BulkRead));
assert_param(bulk != NULL);
@@ -114,7 +114,7 @@ static void settings_bulkwrite_cb(BulkWrite *bulk, const uint8_t *chunk, uint32_
if (bulk->offset > 0) {
settings_load_ini_end();
// dbg("INI write complete");
dbg("INI write complete");
} else {
dbg("INI write failed");
}
@@ -131,7 +131,7 @@ static void settings_bulkwrite_cb(BulkWrite *bulk, const uint8_t *chunk, uint32_
*/
static TF_Result lst_ini_import(TinyFrame *tf, TF_Msg *msg)
{
// dbg("Bulk write INI file");
dbg("Bulk write INI file");
BulkWrite *bulk = malloc_ck(sizeof(BulkWrite));
assert_param(bulk);
+1 -1
View File
@@ -12,7 +12,7 @@
X(SPI1) X(SPI2) X(SPI3) \
X(I2C1) X(I2C2) X(I2C3) \
X(ADC1) X(ADC2) X(ADC3) X(ADC4) \
X(DAC1) \
X(DAC1) X(DAC2) \
X(TSC) \
X(USART1) X(USART2) X(USART3) X(USART4) X(USART5) X(USART6) \
X(TIM1) X(TIM2) X(TIM3) X(TIM4) X(TIM5) \
+1 -1
View File
@@ -169,7 +169,7 @@ void MX_FREERTOS_Init(void) {
/* USER CODE BEGIN RTOS_SEMAPHORES */
/* add semaphores, ... */
xSemaphoreGive(semVcomTxReadyHandle);
assert_param(pdTRUE == xSemaphoreGive(semVcomTxReadyHandle));
/* USER CODE END RTOS_SEMAPHORES */
/* USER CODE BEGIN RTOS_TIMERS */
-1
View File
@@ -18,7 +18,6 @@ GEX_SRC_DIR = \
User/units/fcap \
User/units/touch \
User/units/simple_pwm \
User/units/dac \
User/TinyFrame \
User/CWPack \
User/tasks
+1 -1
View File
@@ -12,7 +12,7 @@
#define DEBUG_USART_BAUD 115200
#if GEX_PLAT_F072_DISCOVERY || GEX_PLAT_F072_HUB
#if GEX_PLAT_F072_DISCOVERY
#define DEBUG_USART USART1
#define DEBUG_USART_RSC R_USART1
+2 -2
View File
@@ -263,7 +263,7 @@ void hw_periph_clock_enable(void *periph)
else if (periph == TIM5) __HAL_RCC_TIM5_CLK_ENABLE();
#endif
#ifdef TIM6
else if (periph == TIM6) __HAL_RCC_TIM6_CLK_ENABLE();
else if (periph == TIM6) __HAL_RCC_TIM7_CLK_ENABLE();
#endif
#ifdef TIM7
else if (periph == TIM7) __HAL_RCC_TIM7_CLK_ENABLE();
@@ -374,7 +374,7 @@ void hw_periph_clock_disable(void *periph)
else if (periph == TIM5) __HAL_RCC_TIM5_CLK_DISABLE();
#endif
#ifdef TIM6
else if (periph == TIM6) __HAL_RCC_TIM6_CLK_DISABLE();
else if (periph == TIM6) __HAL_RCC_TIM7_CLK_DISABLE();
#endif
#ifdef TIM7
else if (periph == TIM7) __HAL_RCC_TIM7_CLK_DISABLE();
+1 -1
View File
@@ -113,7 +113,7 @@ void irqd_init(void)
// NVIC_EnableIRQ(TIM3_IRQn); /*!< TIM3 global Interrupt */
NVIC_EnableIRQ(TIM6_DAC_IRQn); /*!< TIM6 global and DAC channel underrun error Interrupt */
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, 2, 0); // Used for DAC timing
HAL_NVIC_SetPriority(TIM7_IRQn, 2, 0); // Used for DAC timing
NVIC_EnableIRQ(TIM7_IRQn); /*!< TIM7 global Interrupt */
HAL_NVIC_SetPriority(TIM7_IRQn, 2, 0);// this will be for dac (?)
+6 -27
View File
@@ -21,7 +21,7 @@
#endif
// 180 is normally enough if not doing extensive debug logging
#define TSK_STACK_MSG 220 // TF message handler task stack size (all unit commands run on this thread)
#define TSK_STACK_MSG 260 // TF message handler task stack size (all unit commands run on this thread)
#define TSK_STACK_IDLE 64 //configMINIMAL_STACK_SIZE
#define TSK_STACK_TIMERS 64 //configTIMER_TASK_STACK_DEPTH
@@ -30,7 +30,7 @@
#define BULK_READ_BUF_LEN 256 // Buffer for TF bulk reads
#define UNIT_TMP_LEN 256 // Buffer for internal unit operations
#define UNIT_TMP_LEN 512 // Buffer for internal unit operations
#define FLASH_SAVE_BUF_LEN 128 // Malloc'd buffer for saving to flash
@@ -38,7 +38,7 @@
#define RX_QUE_CAPACITY 16 // TinyFrame rx queue size (64 bytes each)
#define TF_MAX_PAYLOAD_RX 512 // TF max Rx payload
#define TF_SENDBUF_LEN 512 // TF transmit buffer (can be less than a full frame)
#define TF_SENDBUF_LEN 64 // TF transmit buffer (can be less than a full frame)
#define TF_MAX_ID_LST 4 // Frame ID listener count
#define TF_MAX_TYPE_LST 6 // Frame Type listener count
@@ -70,7 +70,6 @@
// PLAT_LOCK_BTN - use a lock button instead of a lock jumper (push to toggle)
// PLAT_LOCK_1CLOSED - lock jumper is active (closed / button pressed) in logical 1
// PLAT_NO_AFNUM - legacy platform without numbered AF alternatives
// PLAT_FULL_XTAL - use two-wire xtal attachment
#if defined(GEX_PLAT_F103_BLUEPILL)
@@ -125,8 +124,10 @@
#define STATUS_LED_PORT 'C'
#define STATUS_LED_PIN 13
#elif defined(STM32F072xB)
#elif defined(GEX_PLAT_F072_DISCOVERY)
// platform name for the version string
#define GEX_PLATFORM "STM32F072-Discovery"
#define PLAT_AHB_MHZ 48
#define PLAT_APB1_MHZ 48
@@ -161,10 +162,6 @@
// Number of GPIO ports A,B,C...
#define PORTS_COUNT 6
#if defined(GEX_PLAT_F072_DISCOVERY)
// platform name for the version string
#define GEX_PLATFORM "STM32F072-Discovery"
// Lock jumper config
#define LOCK_JUMPER_PORT 'A'
#define LOCK_JUMPER_PIN 0
@@ -174,24 +171,6 @@
// Status LED config
#define STATUS_LED_PORT 'C'
#define STATUS_LED_PIN 6 // RED LED "UP"
#elif defined(GEX_PLAT_F072_HUB)
// platform name for the version string
#define GEX_PLATFORM "STM32F072-HUB"
#define PLAT_FULL_XTAL 1
// Lock jumper config
#define LOCK_JUMPER_PORT 'D'
#define LOCK_JUMPER_PIN 2
#define PLAT_LOCK_BTN 1 // toggle button instead of a jumper
#define PLAT_LOCK_1CLOSED 0 // toggle button active in log. 1
// Status LED config
#define STATUS_LED_PORT 'A'
#define STATUS_LED_PIN 15 // RED LED "UP"
#else
#error Bad platform
#endif
#elif defined(GEX_PLAT_F303_DISCOVERY)
+5 -11
View File
@@ -2,7 +2,6 @@
// Created by MightyPork on 2017/11/26.
//
#include <units/dac/unit_dac.h>
#include "platform.h"
#include "usbd_core.h"
#include "USB/usb_device.h"
@@ -76,7 +75,7 @@ void plat_init_resources(void)
// BOOT pin(s)
rv |= rsc_claim(&UNIT_SYSTEM, R_PB2); // BOOT1
}
#elif defined(STM32F072xB)
#elif defined(GEX_PLAT_F072_DISCOVERY)
// Platform STM32F073RBT
// Additional GPIO ports
@@ -95,7 +94,6 @@ void plat_init_resources(void)
ureg_add_type(&UNIT_FCAP);
ureg_add_type(&UNIT_TOUCH);
ureg_add_type(&UNIT_PWMDIM);
ureg_add_type(&UNIT_DAC);
// Free all present resources
{
@@ -124,17 +122,13 @@ void plat_init_resources(void)
// Claim resources not available due to board layout or internal usage
{
// HAL timebase
rv |= rsc_claim(&UNIT_SYSTEM, R_TIM17);
rv |= rsc_claim(&UNIT_SYSTEM, R_TIM1);
// HSE crystal
rv |= rsc_claim(&UNIT_SYSTEM, R_PF0);
#if PLAT_FULL_XTAL
rv |= rsc_claim(&UNIT_SYSTEM, R_PF1); // - not used in BYPASS mode
#endif
//rv |= rsc_claim(&UNIT_SYSTEM, R_PF1); // - not used in BYPASS mode
// SWD
// rv |= rsc_claim(&UNIT_SYSTEM, R_PA13);
// rv |= rsc_claim(&UNIT_SYSTEM, R_PA14);
rv |= rsc_claim(&UNIT_SYSTEM, R_PA13);
rv |= rsc_claim(&UNIT_SYSTEM, R_PA14);
// USB
rv |= rsc_claim(&UNIT_SYSTEM, R_PA11);
rv |= rsc_claim(&UNIT_SYSTEM, R_PA12);
+7 -20
View File
@@ -7,6 +7,8 @@
// ---------------------------- HAL TIMEBASE -----------------------------
#define TIMEBASE_TIMER TIM17
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
// EDIT - used 17 instead because 14 was needed for fcap
@@ -100,36 +102,21 @@ uint64_t PTIM_GetMicrotime(void)
return (uint64_t) uwMillis * 1000 + uwMicros;
}
/** microsecond delay */
void PTIM_MicroDelayAligned(uint32_t usec, register const uint32_t start)
void PTIM_MicroDelay(uint16_t usec)
{
assert_param(usec < 1000);
register const uint32_t remain = (1000 - start);
const uint16_t start = (uint16_t) TIMEBASE_TIMER->CNT;
const uint16_t remain = (uint16_t) (999 - start);
if (remain > usec) {
// timer still has enough space going forward to pass the required wait time
register const uint32_t end = start + usec;
while (TIMEBASE_TIMER->CNT < end) {
__NOP();
__NOP();
__NOP();
}
return;
for (; TIMEBASE_TIMER->CNT < start + usec;);
}
else {
// timer is too close to the end
usec -= remain;
while (1) {
register const uint32_t t = TIMEBASE_TIMER->CNT;
if (t < start && t >= usec) return;
for (; TIMEBASE_TIMER->CNT >= start || TIMEBASE_TIMER->CNT < usec;);
}
}
}
/** microsecond delay */
void PTIM_MicroDelay(const uint32_t usec)
{
PTIM_MicroDelayAligned(usec, TIMEBASE_TIMER->CNT);
}
+1 -21
View File
@@ -13,8 +13,6 @@
#include "platform.h"
#define TIMEBASE_TIMER TIM17
/**
* Precision timer: get microtime as uint64_t
* This timestamp should be monotonously increasing with a precision of ±0.5µs
@@ -38,24 +36,6 @@ static inline uint32_t PTIM_GetTime(void)
*
* @param usec - max 998
*/
void PTIM_MicroDelay(uint32_t usec);
/**
* Microsecond busy delay with alignment (reduced length jitter but possible up to 1 us delay)
*
* @param usec
*/
void PTIM_MicroDelayAligned(uint32_t usec, uint32_t start);
/**
* Wait until the next micro timer tick
*/
static inline uint32_t PTIM_MicroDelayAlign(void)
{
const uint32_t c = TIMEBASE_TIMER->CNT;
uint32_t res;
while ((res = TIMEBASE_TIMER->CNT) == c);
return res;
}
void PTIM_MicroDelay(uint16_t usec);
#endif //GEX_F072_TIMEBASE_H
+2 -2
View File
@@ -89,7 +89,7 @@ enum PinCmd_ {
CMD_SEARCH_CONTINUE = 3, // continue the previously started scan, retrieving more devices
CMD_READ_ADDR = 4, // read the ROM code from a single device (for single-device bus)
CMD_QUERY = 10, // write multiple bytes using the SKIP_ROM command
CMD_WRITE = 10, // write multiple bytes using the SKIP_ROM command
CMD_READ = 11, // write multiple bytes using a ROM address
CMD_POLL_FOR_1 = 20,
@@ -194,7 +194,7 @@ static error_t OW_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, Pay
* addr:u64, rest:write_data
* if addr is 0, use SKIP_ROM
*/
case CMD_QUERY:
case CMD_WRITE:
addr = pp_u64(pp);
tail = pp_tail(pp, &remain);
TRY(UU_1WIRE_Write(unit, addr, tail, remain));
+5 -8
View File
@@ -40,8 +40,7 @@ static void UADC_JobSendBlockChunk(Job *job)
.len = (TF_LEN) (1 /*seq*/ + count * sizeof(uint16_t)),
.type = type,
};
assert_param(true == TF_Respond_Multipart(comm, &msg));
TF_Respond_Multipart(comm, &msg);
TF_Multipart_Payload(comm, &priv->stream_serial, 1);
TF_Multipart_Payload(comm, (uint8_t *) (priv->dma_buffer + start), count * sizeof(uint16_t));
TF_Multipart_Close(comm);
@@ -172,7 +171,7 @@ static void handle_httc(Unit *unit, bool tc)
const bool m_fixcpt = priv->opmode == ADC_OPMODE_BLCAP;
if (ht) {
end = (priv->buf_itemcount >> 1); // div2
end = (priv->buf_itemcount / 2);
}
else {
end = priv->buf_itemcount;
@@ -235,7 +234,7 @@ static void handle_httc(Unit *unit, bool tc)
priv->stream_startpos = 0;
}
else {
priv->stream_startpos = priv->buf_itemcount >> 1; // div2
priv->stream_startpos = priv->buf_itemcount / 2;
}
}
@@ -290,7 +289,7 @@ void UADC_DMA_Handler(void *arg)
const bool m_stream = priv->opmode == ADC_OPMODE_STREAM;
const bool m_fixcpt = priv->opmode == ADC_OPMODE_BLCAP;
if (m_trigd || m_stream || m_fixcpt) {
const uint32_t half = (uint32_t) (priv->buf_itemcount >> 1); // div2
const uint32_t half = (uint32_t) (priv->buf_itemcount / 2);
if (ht && tc) {
// dual event interrupt - may happen if we missed both and they were pending after
// interrupts became enabled again (this can happen due to the EOS or other higher prio irq's)
@@ -337,10 +336,8 @@ void UADC_ADC_EOS_Handler(void *arg)
if (priv->opmode == ADC_OPMODE_UNINIT) return;
// Wait for the DMA to complete copying the last sample
uint32_t dmapos = DMA_POS(priv);
if ((DMA_POS(priv) % priv->nb_channels) != 0) {
uint32_t dmapos;
hw_wait_while((dmapos = DMA_POS(priv)) % priv->nb_channels != 0, 100); // XXX this could be changed to reading it from the DR instead
}
uint32_t sample_pos;
if (dmapos == 0) {
-84
View File
@@ -1,84 +0,0 @@
//
// Created by MightyPork on 2018/02/03.
//
#include "platform.h"
#include "unit_base.h"
#include "unit_dac.h"
#define DAC_INTERNAL
#include "_dac_internal.h"
/**
* Re-configure the
* @param unit
*/
void UDAC_Reconfigure(Unit *unit)
{
struct priv *priv = unit->data;
// back-up IT state
bool IT_enabled = (bool) LL_TIM_IsEnabledIT_UPDATE(priv->TIMx);
if (IT_enabled) {
LL_TIM_DisableIT_UPDATE(priv->TIMx);
}
// ...
DAC->CR &= ~(DAC_CR_EN1 | DAC_CR_EN2);
uint32_t CR = 0;
if (priv->cfg.ch[0].enable) {
CR |=
(priv->cfg.ch[0].buffered ? 0 : DAC_CR_BOFF1) |
(priv->ch[0].noise_type << DAC_CR_WAVE1_Pos) |
(priv->ch[0].noise_level & 0xF) << DAC_CR_MAMP1_Pos |
DAC_CR_TEN1 |
(0b111 << DAC_CR_TSEL1_Pos); // software trigger;
CR |= DAC_CR_EN1;
}
if (priv->cfg.ch[1].enable) {
CR |=
(priv->cfg.ch[1].buffered ? 0 : DAC_CR_BOFF2) |
(priv->ch[1].noise_type << DAC_CR_WAVE2_Pos) |
(priv->ch[1].noise_level & 0xF) << DAC_CR_MAMP2_Pos |
DAC_CR_TEN2 |
(0b111 << DAC_CR_TSEL2_Pos); // software trigger
CR |= DAC_CR_EN2;
}
DAC->CR = CR;
// ...
if (IT_enabled) {
LL_TIM_EnableIT_UPDATE(priv->TIMx);
}
}
error_t UDAC_SetFreq(Unit *unit, int channel, float freq)
{
struct priv *priv = unit->data;
priv->ch[channel].increment = (uint32_t) roundf(25.0f * freq * UDAC_VALUE_COUNT * // FIXME constant seems derived from the divide ...?
((float)UDAC_TIM_FREQ_DIVIDER / PLAT_AHB_MHZ)
);
// dbg("Ch %d: Computed increment: %d", channel+1, (int)priv->ch[channel].increment);
return E_SUCCESS;
}
void UDAC_ToggleTimerIfNeeded(Unit *unit)
{
struct priv *priv = unit->data;
if (priv->ch[0].waveform == UDAC_WAVE_DC && priv->ch[1].waveform == UDAC_WAVE_DC) {
LL_TIM_DisableCounter(priv->TIMx);
// manually call the interrupt function to update the level
UDAC_HandleIT(unit);
} else {
LL_TIM_EnableCounter(priv->TIMx);
}
}
-392
View File
@@ -1,392 +0,0 @@
//
// Created by MightyPork on 2018/03/10.
//
#include "platform.h"
#include "unit_dac.h"
#define DAC_INTERNAL
#include "_dac_internal.h"
#pragma GCC push_options
#pragma GCC optimize ("O2")
void UDAC_HandleIT(void *arg)
{
Unit *unit = arg;
struct priv *priv = unit->data;
LL_TIM_ClearFlag_UPDATE(priv->TIMx);
// TODO optimize to allow faster update speed
uint16_t vals[2];
for (int i = 0; i < 2; i++) {
struct udac_channel_live *const ch = &priv->ch[i];
if (ch->waveform == UDAC_WAVE_DC) {
// skip the whole counter thing for DC
vals[i] = ch->dc_level;
continue;
}
ch->counter += ch->increment;
const uint16_t index = (uint16_t) (ch->counter >> UDAC_INDEX_SHIFT);
switch (ch->waveform) {
case UDAC_WAVE_SINE: {
const uint32_t phase = index >> (UDAC_INDEX_WIDTH - 2);
uint32_t pos = (uint32_t) index & (((1<<(UDAC_INDEX_WIDTH - 2)) - 1));
if (phase & 0b01) {
// 2nd and 4th quarter (01, 11)
pos = (UDAC_VALUE_COUNT/4 - 1) - pos;
}
uint32_t value;
/* unpack */
const uint32_t nthbyte = (pos * 3) / 2;
const uint8_t topbyte = LUT_sine_8192_quad_packed[nthbyte];
const uint8_t botbyte = LUT_sine_8192_quad_packed[nthbyte + 1];
if (pos & 1) {
// odd index
value = (uint32_t) (((topbyte & 0xF) << 8) | botbyte);
}
else {
value = (uint32_t) ((topbyte << 4) | ((botbyte & 0xF0) >> 4));
}
/* end unpack -> value */
if (phase & 0b10) {
// 3rd and 4th quarter (10, 11)
value = 2047 - value;
}
else {
// 1st and 2nd quarter (00, 01)
value = 2048 + value;
}
vals[i] = (uint16_t) value;
break;
}
case UDAC_WAVE_RECTANGLE:
if (index < ch->rectangle_ontime) {
vals[i] = ch->rectangle_high;
} else {
vals[i] = ch->rectangle_low;
}
break;
case UDAC_WAVE_SAWTOOTH_UP:
vals[i] = (uint16_t) (index / 2); // for 8192 steps, this will produce 0-4095
break;
case UDAC_WAVE_SAWTOOTH_DOWN:
vals[i] = (uint16_t) (4095 - (index / 2)); // for 8192 steps, this will produce 0-4095
break;
case UDAC_WAVE_TRIANGLE: {
if (index < 4096) {
vals[i] = index;
}
else {
vals[i] = (uint16_t) (8191 - index);
}
break;
}
default:
vals[i] = 0; // this shouldn't happen
break;
} // end select waveform
} // end for 0,1
DAC->DHR12RD = (vals[1] << 16) | vals[0];
// Trigger a conversion
DAC->SWTRIGR = (DAC_SWTR_CH1 | DAC_SWTR_CH2);
}
#pragma GCC pop_options
/**
* This is the first 1/4 of a 12-bit sine wave sampled in 8192 points, each two points packed into three bytes (saves 1/4 of space used by uint16_t's)
* The array holds 2048 data points which can be easily offset / flipped to cover the entire waveform.
*
* |<-->|
* _---_
* / \
* / \
* /---------\---------/
* \ /
* \_ _/
* ---
*/
#if 0 // this is rail to rail, but the dac doesn't work well at the rails and it gets flattened
const uint8_t LUT_sine_8192_quad_packed[] = {
0x00, 0x00, 0x02, 0x00, 0x30, 0x05, 0x00, 0x60, 0x08, 0x00, 0x90, 0x0B, 0x00, 0xD0, 0x0E, 0x01, 0x00, 0x11, 0x01, 0x30, 0x14, 0x01, 0x60, 0x18,
0x01, 0x90, 0x1B, 0x01, 0xC0, 0x1E, 0x01, 0xF0, 0x21, 0x02, 0x30, 0x24, 0x02, 0x60, 0x27, 0x02, 0x90, 0x2A, 0x02, 0xC0, 0x2E, 0x02, 0xF0, 0x31,
0x03, 0x20, 0x34, 0x03, 0x50, 0x37, 0x03, 0x90, 0x3A, 0x03, 0xC0, 0x3D, 0x03, 0xF0, 0x40, 0x04, 0x20, 0x43, 0x04, 0x50, 0x47, 0x04, 0x80, 0x4A,
0x04, 0xB0, 0x4D, 0x04, 0xE0, 0x50, 0x05, 0x20, 0x53, 0x05, 0x50, 0x56, 0x05, 0x80, 0x59, 0x05, 0xB0, 0x5D, 0x05, 0xE0, 0x60, 0x06, 0x10, 0x63,
0x06, 0x40, 0x66, 0x06, 0x80, 0x69, 0x06, 0xB0, 0x6C, 0x06, 0xE0, 0x6F, 0x07, 0x10, 0x73, 0x07, 0x40, 0x76, 0x07, 0x70, 0x79, 0x07, 0xA0, 0x7C,
0x07, 0xE0, 0x7F, 0x08, 0x10, 0x82, 0x08, 0x40, 0x85, 0x08, 0x70, 0x88, 0x08, 0xA0, 0x8C, 0x08, 0xD0, 0x8F, 0x09, 0x00, 0x92, 0x09, 0x30, 0x95,
0x09, 0x70, 0x98, 0x09, 0xA0, 0x9B, 0x09, 0xD0, 0x9E, 0x0A, 0x00, 0xA2, 0x0A, 0x30, 0xA5, 0x0A, 0x60, 0xA8, 0x0A, 0x90, 0xAB, 0x0A, 0xC0, 0xAE,
0x0B, 0x00, 0xB1, 0x0B, 0x30, 0xB4, 0x0B, 0x60, 0xB7, 0x0B, 0x90, 0xBB, 0x0B, 0xC0, 0xBE, 0x0B, 0xF0, 0xC1, 0x0C, 0x20, 0xC4, 0x0C, 0x60, 0xC7,
0x0C, 0x90, 0xCA, 0x0C, 0xC0, 0xCD, 0x0C, 0xF0, 0xD0, 0x0D, 0x20, 0xD4, 0x0D, 0x50, 0xD7, 0x0D, 0x80, 0xDA, 0x0D, 0xB0, 0xDD, 0x0D, 0xF0, 0xE0,
0x0E, 0x20, 0xE3, 0x0E, 0x50, 0xE6, 0x0E, 0x80, 0xE9, 0x0E, 0xB0, 0xED, 0x0E, 0xE0, 0xF0, 0x0F, 0x10, 0xF3, 0x0F, 0x40, 0xF6, 0x0F, 0x70, 0xF9,
0x0F, 0xB0, 0xFC, 0x0F, 0xE0, 0xFF, 0x10, 0x11, 0x02, 0x10, 0x41, 0x05, 0x10, 0x71, 0x09, 0x10, 0xA1, 0x0C, 0x10, 0xD1, 0x0F, 0x11, 0x01, 0x12,
0x11, 0x31, 0x15, 0x11, 0x71, 0x18, 0x11, 0xA1, 0x1B, 0x11, 0xD1, 0x1E, 0x12, 0x01, 0x21, 0x12, 0x31, 0x25, 0x12, 0x61, 0x28, 0x12, 0x91, 0x2B,
0x12, 0xC1, 0x2E, 0x12, 0xF1, 0x31, 0x13, 0x31, 0x34, 0x13, 0x61, 0x37, 0x13, 0x91, 0x3A, 0x13, 0xC1, 0x3D, 0x13, 0xF1, 0x41, 0x14, 0x21, 0x44,
0x14, 0x51, 0x47, 0x14, 0x81, 0x4A, 0x14, 0xB1, 0x4D, 0x14, 0xE1, 0x50, 0x15, 0x21, 0x53, 0x15, 0x51, 0x56, 0x15, 0x81, 0x59, 0x15, 0xB1, 0x5C,
0x15, 0xE1, 0x60, 0x16, 0x11, 0x63, 0x16, 0x41, 0x66, 0x16, 0x71, 0x69, 0x16, 0xA1, 0x6C, 0x16, 0xD1, 0x6F, 0x17, 0x11, 0x72, 0x17, 0x41, 0x75,
0x17, 0x71, 0x78, 0x17, 0xA1, 0x7B, 0x17, 0xD1, 0x7E, 0x18, 0x01, 0x81, 0x18, 0x31, 0x85, 0x18, 0x61, 0x88, 0x18, 0x91, 0x8B, 0x18, 0xC1, 0x8E,
0x18, 0xF1, 0x91, 0x19, 0x21, 0x94, 0x19, 0x61, 0x97, 0x19, 0x91, 0x9A, 0x19, 0xC1, 0x9D, 0x19, 0xF1, 0xA0, 0x1A, 0x21, 0xA3, 0x1A, 0x51, 0xA6,
0x1A, 0x81, 0xA9, 0x1A, 0xB1, 0xAD, 0x1A, 0xE1, 0xB0, 0x1B, 0x11, 0xB3, 0x1B, 0x41, 0xB6, 0x1B, 0x71, 0xB9, 0x1B, 0xA1, 0xBC, 0x1B, 0xD1, 0xBF,
0x1C, 0x11, 0xC2, 0x1C, 0x41, 0xC5, 0x1C, 0x71, 0xC8, 0x1C, 0xA1, 0xCB, 0x1C, 0xD1, 0xCE, 0x1D, 0x01, 0xD1, 0x1D, 0x31, 0xD4, 0x1D, 0x61, 0xD7,
0x1D, 0x91, 0xDB, 0x1D, 0xC1, 0xDE, 0x1D, 0xF1, 0xE1, 0x1E, 0x21, 0xE4, 0x1E, 0x51, 0xE7, 0x1E, 0x81, 0xEA, 0x1E, 0xB1, 0xED, 0x1E, 0xE1, 0xF0,
0x1F, 0x11, 0xF3, 0x1F, 0x41, 0xF6, 0x1F, 0x71, 0xF9, 0x1F, 0xB1, 0xFC, 0x1F, 0xE1, 0xFF, 0x20, 0x12, 0x02, 0x20, 0x42, 0x05, 0x20, 0x72, 0x08,
0x20, 0xA2, 0x0B, 0x20, 0xD2, 0x0E, 0x21, 0x02, 0x11, 0x21, 0x32, 0x14, 0x21, 0x62, 0x17, 0x21, 0x92, 0x1A, 0x21, 0xC2, 0x1D, 0x21, 0xF2, 0x20,
0x22, 0x22, 0x23, 0x22, 0x52, 0x26, 0x22, 0x82, 0x2A, 0x22, 0xB2, 0x2D, 0x22, 0xE2, 0x30, 0x23, 0x12, 0x33, 0x23, 0x42, 0x36, 0x23, 0x72, 0x39,
0x23, 0xA2, 0x3C, 0x23, 0xD2, 0x3F, 0x24, 0x02, 0x42, 0x24, 0x32, 0x45, 0x24, 0x62, 0x48, 0x24, 0x92, 0x4B, 0x24, 0xC2, 0x4E, 0x24, 0xF2, 0x51,
0x25, 0x22, 0x54, 0x25, 0x52, 0x57, 0x25, 0x82, 0x5A, 0x25, 0xB2, 0x5D, 0x25, 0xE2, 0x60, 0x26, 0x12, 0x63, 0x26, 0x42, 0x66, 0x26, 0x72, 0x69,
0x26, 0xA2, 0x6C, 0x26, 0xD2, 0x6F, 0x27, 0x02, 0x72, 0x27, 0x32, 0x75, 0x27, 0x62, 0x78, 0x27, 0x92, 0x7B, 0x27, 0xC2, 0x7E, 0x27, 0xF2, 0x81,
0x28, 0x22, 0x84, 0x28, 0x52, 0x87, 0x28, 0x82, 0x8A, 0x28, 0xB2, 0x8D, 0x28, 0xE2, 0x90, 0x29, 0x12, 0x92, 0x29, 0x42, 0x95, 0x29, 0x72, 0x98,
0x29, 0xA2, 0x9B, 0x29, 0xD2, 0x9E, 0x2A, 0x02, 0xA1, 0x2A, 0x32, 0xA4, 0x2A, 0x62, 0xA7, 0x2A, 0x92, 0xAA, 0x2A, 0xC2, 0xAD, 0x2A, 0xF2, 0xB0,
0x2B, 0x22, 0xB3, 0x2B, 0x52, 0xB6, 0x2B, 0x82, 0xB9, 0x2B, 0xA2, 0xBC, 0x2B, 0xD2, 0xBF, 0x2C, 0x02, 0xC2, 0x2C, 0x32, 0xC5, 0x2C, 0x62, 0xC8,
0x2C, 0x92, 0xCB, 0x2C, 0xC2, 0xCE, 0x2C, 0xF2, 0xD1, 0x2D, 0x22, 0xD4, 0x2D, 0x52, 0xD6, 0x2D, 0x82, 0xD9, 0x2D, 0xB2, 0xDC, 0x2D, 0xE2, 0xDF,
0x2E, 0x12, 0xE2, 0x2E, 0x42, 0xE5, 0x2E, 0x72, 0xE8, 0x2E, 0x92, 0xEB, 0x2E, 0xC2, 0xEE, 0x2E, 0xF2, 0xF1, 0x2F, 0x22, 0xF4, 0x2F, 0x52, 0xF7,
0x2F, 0x82, 0xFA, 0x2F, 0xB2, 0xFC, 0x2F, 0xE2, 0xFF, 0x30, 0x13, 0x02, 0x30, 0x43, 0x05, 0x30, 0x73, 0x08, 0x30, 0xA3, 0x0B, 0x30, 0xC3, 0x0E,
0x30, 0xF3, 0x11, 0x31, 0x23, 0x14, 0x31, 0x53, 0x17, 0x31, 0x83, 0x19, 0x31, 0xB3, 0x1C, 0x31, 0xE3, 0x1F, 0x32, 0x13, 0x22, 0x32, 0x43, 0x25,
0x32, 0x73, 0x28, 0x32, 0x93, 0x2B, 0x32, 0xC3, 0x2E, 0x32, 0xF3, 0x31, 0x33, 0x23, 0x33, 0x33, 0x53, 0x36, 0x33, 0x83, 0x39, 0x33, 0xB3, 0x3C,
0x33, 0xE3, 0x3F, 0x34, 0x03, 0x42, 0x34, 0x33, 0x45, 0x34, 0x63, 0x48, 0x34, 0x93, 0x4A, 0x34, 0xC3, 0x4D, 0x34, 0xF3, 0x50, 0x35, 0x23, 0x53,
0x35, 0x43, 0x56, 0x35, 0x73, 0x59, 0x35, 0xA3, 0x5C, 0x35, 0xD3, 0x5E, 0x36, 0x03, 0x61, 0x36, 0x33, 0x64, 0x36, 0x63, 0x67, 0x36, 0x83, 0x6A,
0x36, 0xB3, 0x6D, 0x36, 0xE3, 0x6F, 0x37, 0x13, 0x72, 0x37, 0x43, 0x75, 0x37, 0x73, 0x78, 0x37, 0x93, 0x7B, 0x37, 0xC3, 0x7E, 0x37, 0xF3, 0x80,
0x38, 0x23, 0x83, 0x38, 0x53, 0x86, 0x38, 0x73, 0x89, 0x38, 0xA3, 0x8C, 0x38, 0xD3, 0x8F, 0x39, 0x03, 0x91, 0x39, 0x33, 0x94, 0x39, 0x63, 0x97,
0x39, 0x83, 0x9A, 0x39, 0xB3, 0x9D, 0x39, 0xE3, 0x9F, 0x3A, 0x13, 0xA2, 0x3A, 0x43, 0xA5, 0x3A, 0x63, 0xA8, 0x3A, 0x93, 0xAB, 0x3A, 0xC3, 0xAD,
0x3A, 0xF3, 0xB0, 0x3B, 0x23, 0xB3, 0x3B, 0x43, 0xB6, 0x3B, 0x73, 0xB8, 0x3B, 0xA3, 0xBB, 0x3B, 0xD3, 0xBE, 0x3B, 0xF3, 0xC1, 0x3C, 0x23, 0xC4,
0x3C, 0x53, 0xC6, 0x3C, 0x83, 0xC9, 0x3C, 0xA3, 0xCC, 0x3C, 0xD3, 0xCF, 0x3D, 0x03, 0xD1, 0x3D, 0x33, 0xD4, 0x3D, 0x63, 0xD7, 0x3D, 0x83, 0xDA,
0x3D, 0xB3, 0xDC, 0x3D, 0xE3, 0xDF, 0x3E, 0x13, 0xE2, 0x3E, 0x33, 0xE5, 0x3E, 0x63, 0xE7, 0x3E, 0x93, 0xEA, 0x3E, 0xB3, 0xED, 0x3E, 0xE3, 0xF0,
0x3F, 0x13, 0xF2, 0x3F, 0x43, 0xF5, 0x3F, 0x63, 0xF8, 0x3F, 0x93, 0xFB, 0x3F, 0xC3, 0xFD, 0x3F, 0xF4, 0x00, 0x40, 0x14, 0x03, 0x40, 0x44, 0x05,
0x40, 0x74, 0x08, 0x40, 0x94, 0x0B, 0x40, 0xC4, 0x0E, 0x40, 0xF4, 0x10, 0x41, 0x24, 0x13, 0x41, 0x44, 0x16, 0x41, 0x74, 0x18, 0x41, 0xA4, 0x1B,
0x41, 0xC4, 0x1E, 0x41, 0xF4, 0x20, 0x42, 0x24, 0x23, 0x42, 0x44, 0x26, 0x42, 0x74, 0x28, 0x42, 0xA4, 0x2B, 0x42, 0xC4, 0x2E, 0x42, 0xF4, 0x30,
0x43, 0x24, 0x33, 0x43, 0x54, 0x36, 0x43, 0x74, 0x39, 0x43, 0xA4, 0x3B, 0x43, 0xD4, 0x3E, 0x43, 0xF4, 0x40, 0x44, 0x24, 0x43, 0x44, 0x44, 0x46,
0x44, 0x74, 0x48, 0x44, 0xA4, 0x4B, 0x44, 0xC4, 0x4E, 0x44, 0xF4, 0x50, 0x45, 0x24, 0x53, 0x45, 0x44, 0x56, 0x45, 0x74, 0x58, 0x45, 0xA4, 0x5B,
0x45, 0xC4, 0x5E, 0x45, 0xF4, 0x60, 0x46, 0x24, 0x63, 0x46, 0x44, 0x65, 0x46, 0x74, 0x68, 0x46, 0x94, 0x6B, 0x46, 0xC4, 0x6D, 0x46, 0xF4, 0x70,
0x47, 0x14, 0x73, 0x47, 0x44, 0x75, 0x47, 0x64, 0x78, 0x47, 0x94, 0x7A, 0x47, 0xC4, 0x7D, 0x47, 0xE4, 0x80, 0x48, 0x14, 0x82, 0x48, 0x34, 0x85,
0x48, 0x64, 0x87, 0x48, 0x94, 0x8A, 0x48, 0xB4, 0x8D, 0x48, 0xE4, 0x8F, 0x49, 0x04, 0x92, 0x49, 0x34, 0x94, 0x49, 0x64, 0x97, 0x49, 0x84, 0x99,
0x49, 0xB4, 0x9C, 0x49, 0xD4, 0x9F, 0x4A, 0x04, 0xA1, 0x4A, 0x24, 0xA4, 0x4A, 0x54, 0xA6, 0x4A, 0x74, 0xA9, 0x4A, 0xA4, 0xAB, 0x4A, 0xD4, 0xAE,
0x4A, 0xF4, 0xB0, 0x4B, 0x24, 0xB3, 0x4B, 0x44, 0xB5, 0x4B, 0x74, 0xB8, 0x4B, 0x94, 0xBB, 0x4B, 0xC4, 0xBD, 0x4B, 0xE4, 0xC0, 0x4C, 0x14, 0xC2,
0x4C, 0x34, 0xC5, 0x4C, 0x64, 0xC7, 0x4C, 0x84, 0xCA, 0x4C, 0xB4, 0xCC, 0x4C, 0xD4, 0xCF, 0x4D, 0x04, 0xD1, 0x4D, 0x24, 0xD4, 0x4D, 0x54, 0xD6,
0x4D, 0x74, 0xD9, 0x4D, 0xA4, 0xDB, 0x4D, 0xC4, 0xDE, 0x4D, 0xF4, 0xE0, 0x4E, 0x14, 0xE3, 0x4E, 0x44, 0xE5, 0x4E, 0x64, 0xE8, 0x4E, 0x94, 0xEA,
0x4E, 0xB4, 0xED, 0x4E, 0xE4, 0xEF, 0x4F, 0x04, 0xF2, 0x4F, 0x34, 0xF4, 0x4F, 0x54, 0xF6, 0x4F, 0x84, 0xF9, 0x4F, 0xA4, 0xFB, 0x4F, 0xD4, 0xFE,
0x4F, 0xF5, 0x00, 0x50, 0x25, 0x03, 0x50, 0x45, 0x05, 0x50, 0x65, 0x08, 0x50, 0x95, 0x0A, 0x50, 0xB5, 0x0D, 0x50, 0xE5, 0x0F, 0x51, 0x05, 0x11,
0x51, 0x35, 0x14, 0x51, 0x55, 0x16, 0x51, 0x75, 0x19, 0x51, 0xA5, 0x1B, 0x51, 0xC5, 0x1D, 0x51, 0xF5, 0x20, 0x52, 0x15, 0x22, 0x52, 0x45, 0x25,
0x52, 0x65, 0x27, 0x52, 0x85, 0x2A, 0x52, 0xB5, 0x2C, 0x52, 0xD5, 0x2E, 0x53, 0x05, 0x31, 0x53, 0x25, 0x33, 0x53, 0x45, 0x35, 0x53, 0x75, 0x38,
0x53, 0x95, 0x3A, 0x53, 0xB5, 0x3D, 0x53, 0xE5, 0x3F, 0x54, 0x05, 0x41, 0x54, 0x35, 0x44, 0x54, 0x55, 0x46, 0x54, 0x75, 0x48, 0x54, 0xA5, 0x4B,
0x54, 0xC5, 0x4D, 0x54, 0xE5, 0x4F, 0x55, 0x15, 0x52, 0x55, 0x35, 0x54, 0x55, 0x55, 0x57, 0x55, 0x85, 0x59, 0x55, 0xA5, 0x5B, 0x55, 0xC5, 0x5E,
0x55, 0xF5, 0x60, 0x56, 0x15, 0x62, 0x56, 0x35, 0x64, 0x56, 0x65, 0x67, 0x56, 0x85, 0x69, 0x56, 0xA5, 0x6B, 0x56, 0xD5, 0x6E, 0x56, 0xF5, 0x70,
0x57, 0x15, 0x72, 0x57, 0x35, 0x75, 0x57, 0x65, 0x77, 0x57, 0x85, 0x79, 0x57, 0xA5, 0x7C, 0x57, 0xD5, 0x7E, 0x57, 0xF5, 0x80, 0x58, 0x15, 0x82,
0x58, 0x35, 0x85, 0x58, 0x65, 0x87, 0x58, 0x85, 0x89, 0x58, 0xA5, 0x8B, 0x58, 0xD5, 0x8E, 0x58, 0xF5, 0x90, 0x59, 0x15, 0x92, 0x59, 0x35, 0x94,
0x59, 0x65, 0x97, 0x59, 0x85, 0x99, 0x59, 0xA5, 0x9B, 0x59, 0xC5, 0x9D, 0x59, 0xF5, 0xA0, 0x5A, 0x15, 0xA2, 0x5A, 0x35, 0xA4, 0x5A, 0x55, 0xA6,
0x5A, 0x75, 0xA9, 0x5A, 0xA5, 0xAB, 0x5A, 0xC5, 0xAD, 0x5A, 0xE5, 0xAF, 0x5B, 0x05, 0xB1, 0x5B, 0x35, 0xB4, 0x5B, 0x55, 0xB6, 0x5B, 0x75, 0xB8,
0x5B, 0x95, 0xBA, 0x5B, 0xB5, 0xBC, 0x5B, 0xD5, 0xBF, 0x5C, 0x05, 0xC1, 0x5C, 0x25, 0xC3, 0x5C, 0x45, 0xC5, 0x5C, 0x65, 0xC7, 0x5C, 0x85, 0xC9,
0x5C, 0xB5, 0xCC, 0x5C, 0xD5, 0xCE, 0x5C, 0xF5, 0xD0, 0x5D, 0x15, 0xD2, 0x5D, 0x35, 0xD4, 0x5D, 0x55, 0xD6, 0x5D, 0x75, 0xD9, 0x5D, 0xA5, 0xDB,
0x5D, 0xC5, 0xDD, 0x5D, 0xE5, 0xDF, 0x5E, 0x05, 0xE1, 0x5E, 0x25, 0xE3, 0x5E, 0x45, 0xE5, 0x5E, 0x65, 0xE7, 0x5E, 0x95, 0xEA, 0x5E, 0xB5, 0xEC,
0x5E, 0xD5, 0xEE, 0x5E, 0xF5, 0xF0, 0x5F, 0x15, 0xF2, 0x5F, 0x35, 0xF4, 0x5F, 0x55, 0xF6, 0x5F, 0x75, 0xF8, 0x5F, 0x95, 0xFA, 0x5F, 0xB5, 0xFC,
0x5F, 0xD5, 0xFF, 0x60, 0x06, 0x01, 0x60, 0x26, 0x03, 0x60, 0x46, 0x05, 0x60, 0x66, 0x07, 0x60, 0x86, 0x09, 0x60, 0xA6, 0x0B, 0x60, 0xC6, 0x0D,
0x60, 0xE6, 0x0F, 0x61, 0x06, 0x11, 0x61, 0x26, 0x13, 0x61, 0x46, 0x15, 0x61, 0x66, 0x17, 0x61, 0x86, 0x19, 0x61, 0xA6, 0x1B, 0x61, 0xC6, 0x1D,
0x61, 0xE6, 0x1F, 0x62, 0x06, 0x21, 0x62, 0x26, 0x23, 0x62, 0x46, 0x25, 0x62, 0x66, 0x27, 0x62, 0x86, 0x29, 0x62, 0xA6, 0x2B, 0x62, 0xC6, 0x2D,
0x62, 0xE6, 0x2F, 0x63, 0x06, 0x31, 0x63, 0x26, 0x33, 0x63, 0x46, 0x35, 0x63, 0x66, 0x37, 0x63, 0x86, 0x39, 0x63, 0xA6, 0x3B, 0x63, 0xC6, 0x3D,
0x63, 0xE6, 0x3F, 0x64, 0x06, 0x41, 0x64, 0x26, 0x43, 0x64, 0x46, 0x45, 0x64, 0x66, 0x47, 0x64, 0x86, 0x49, 0x64, 0xA6, 0x4B, 0x64, 0xC6, 0x4D,
0x64, 0xE6, 0x4F, 0x65, 0x06, 0x51, 0x65, 0x26, 0x53, 0x65, 0x46, 0x54, 0x65, 0x56, 0x56, 0x65, 0x76, 0x58, 0x65, 0x96, 0x5A, 0x65, 0xB6, 0x5C,
0x65, 0xD6, 0x5E, 0x65, 0xF6, 0x60, 0x66, 0x16, 0x62, 0x66, 0x36, 0x64, 0x66, 0x56, 0x66, 0x66, 0x76, 0x67, 0x66, 0x86, 0x69, 0x66, 0xA6, 0x6B,
0x66, 0xC6, 0x6D, 0x66, 0xE6, 0x6F, 0x67, 0x06, 0x71, 0x67, 0x26, 0x73, 0x67, 0x46, 0x75, 0x67, 0x56, 0x76, 0x67, 0x76, 0x78, 0x67, 0x96, 0x7A,
0x67, 0xB6, 0x7C, 0x67, 0xD6, 0x7E, 0x67, 0xF6, 0x80, 0x68, 0x16, 0x81, 0x68, 0x26, 0x83, 0x68, 0x46, 0x85, 0x68, 0x66, 0x87, 0x68, 0x86, 0x89,
0x68, 0xA6, 0x8A, 0x68, 0xB6, 0x8C, 0x68, 0xD6, 0x8E, 0x68, 0xF6, 0x90, 0x69, 0x16, 0x92, 0x69, 0x36, 0x93, 0x69, 0x46, 0x95, 0x69, 0x66, 0x97,
0x69, 0x86, 0x99, 0x69, 0xA6, 0x9B, 0x69, 0xB6, 0x9C, 0x69, 0xD6, 0x9E, 0x69, 0xF6, 0xA0, 0x6A, 0x16, 0xA2, 0x6A, 0x36, 0xA3, 0x6A, 0x46, 0xA5,
0x6A, 0x66, 0xA7, 0x6A, 0x86, 0xA9, 0x6A, 0x96, 0xAA, 0x6A, 0xB6, 0xAC, 0x6A, 0xD6, 0xAE, 0x6A, 0xF6, 0xB0, 0x6B, 0x06, 0xB1, 0x6B, 0x26, 0xB3,
0x6B, 0x46, 0xB5, 0x6B, 0x66, 0xB6, 0x6B, 0x76, 0xB8, 0x6B, 0x96, 0xBA, 0x6B, 0xB6, 0xBC, 0x6B, 0xC6, 0xBD, 0x6B, 0xE6, 0xBF, 0x6C, 0x06, 0xC1,
0x6C, 0x16, 0xC2, 0x6C, 0x36, 0xC4, 0x6C, 0x56, 0xC6, 0x6C, 0x66, 0xC7, 0x6C, 0x86, 0xC9, 0x6C, 0xA6, 0xCB, 0x6C, 0xB6, 0xCC, 0x6C, 0xD6, 0xCE,
0x6C, 0xF6, 0xD0, 0x6D, 0x06, 0xD1, 0x6D, 0x26, 0xD3, 0x6D, 0x46, 0xD4, 0x6D, 0x56, 0xD6, 0x6D, 0x76, 0xD8, 0x6D, 0x96, 0xD9, 0x6D, 0xA6, 0xDB,
0x6D, 0xC6, 0xDD, 0x6D, 0xD6, 0xDE, 0x6D, 0xF6, 0xE0, 0x6E, 0x16, 0xE1, 0x6E, 0x26, 0xE3, 0x6E, 0x46, 0xE5, 0x6E, 0x56, 0xE6, 0x6E, 0x76, 0xE8,
0x6E, 0x96, 0xE9, 0x6E, 0xA6, 0xEB, 0x6E, 0xC6, 0xEC, 0x6E, 0xD6, 0xEE, 0x6E, 0xF6, 0xF0, 0x6F, 0x06, 0xF1, 0x6F, 0x26, 0xF3, 0x6F, 0x46, 0xF4,
0x6F, 0x56, 0xF6, 0x6F, 0x76, 0xF7, 0x6F, 0x86, 0xF9, 0x6F, 0xA6, 0xFA, 0x6F, 0xB6, 0xFC, 0x6F, 0xD6, 0xFE, 0x6F, 0xE6, 0xFF, 0x70, 0x07, 0x01,
0x70, 0x17, 0x02, 0x70, 0x37, 0x04, 0x70, 0x47, 0x05, 0x70, 0x67, 0x07, 0x70, 0x77, 0x08, 0x70, 0x97, 0x0A, 0x70, 0xA7, 0x0B, 0x70, 0xC7, 0x0D,
0x70, 0xD7, 0x0E, 0x70, 0xF7, 0x10, 0x71, 0x07, 0x11, 0x71, 0x27, 0x12, 0x71, 0x37, 0x14, 0x71, 0x57, 0x15, 0x71, 0x67, 0x17, 0x71, 0x87, 0x18,
0x71, 0x97, 0x1A, 0x71, 0xA7, 0x1B, 0x71, 0xC7, 0x1D, 0x71, 0xD7, 0x1E, 0x71, 0xF7, 0x1F, 0x72, 0x07, 0x21, 0x72, 0x27, 0x22, 0x72, 0x37, 0x24,
0x72, 0x47, 0x25, 0x72, 0x67, 0x27, 0x72, 0x77, 0x28, 0x72, 0x97, 0x29, 0x72, 0xA7, 0x2B, 0x72, 0xB7, 0x2C, 0x72, 0xD7, 0x2E, 0x72, 0xE7, 0x2F,
0x73, 0x07, 0x30, 0x73, 0x17, 0x32, 0x73, 0x27, 0x33, 0x73, 0x47, 0x34, 0x73, 0x57, 0x36, 0x73, 0x67, 0x37, 0x73, 0x87, 0x38, 0x73, 0x97, 0x3A,
0x73, 0xA7, 0x3B, 0x73, 0xC7, 0x3C, 0x73, 0xD7, 0x3E, 0x73, 0xE7, 0x3F, 0x74, 0x07, 0x40, 0x74, 0x17, 0x42, 0x74, 0x27, 0x43, 0x74, 0x47, 0x44,
0x74, 0x57, 0x46, 0x74, 0x67, 0x47, 0x74, 0x87, 0x48, 0x74, 0x97, 0x4A, 0x74, 0xA7, 0x4B, 0x74, 0xC7, 0x4C, 0x74, 0xD7, 0x4D, 0x74, 0xE7, 0x4F,
0x74, 0xF7, 0x50, 0x75, 0x17, 0x51, 0x75, 0x27, 0x53, 0x75, 0x37, 0x54, 0x75, 0x47, 0x55, 0x75, 0x67, 0x56, 0x75, 0x77, 0x58, 0x75, 0x87, 0x59,
0x75, 0x97, 0x5A, 0x75, 0xB7, 0x5B, 0x75, 0xC7, 0x5D, 0x75, 0xD7, 0x5E, 0x75, 0xE7, 0x5F, 0x76, 0x07, 0x60, 0x76, 0x17, 0x61, 0x76, 0x27, 0x63,
0x76, 0x37, 0x64, 0x76, 0x47, 0x65, 0x76, 0x67, 0x66, 0x76, 0x77, 0x67, 0x76, 0x87, 0x69, 0x76, 0x97, 0x6A, 0x76, 0xA7, 0x6B, 0x76, 0xB7, 0x6C,
0x76, 0xD7, 0x6D, 0x76, 0xE7, 0x6E, 0x76, 0xF7, 0x70, 0x77, 0x07, 0x71, 0x77, 0x17, 0x72, 0x77, 0x27, 0x73, 0x77, 0x47, 0x74, 0x77, 0x57, 0x75,
0x77, 0x67, 0x76, 0x77, 0x77, 0x78, 0x77, 0x87, 0x79, 0x77, 0x97, 0x7A, 0x77, 0xA7, 0x7B, 0x77, 0xB7, 0x7C, 0x77, 0xD7, 0x7D, 0x77, 0xE7, 0x7E,
0x77, 0xF7, 0x7F, 0x78, 0x07, 0x80, 0x78, 0x17, 0x81, 0x78, 0x27, 0x83, 0x78, 0x37, 0x84, 0x78, 0x47, 0x85, 0x78, 0x57, 0x86, 0x78, 0x67, 0x87,
0x78, 0x77, 0x88, 0x78, 0x87, 0x89, 0x78, 0x97, 0x8A, 0x78, 0xA7, 0x8B, 0x78, 0xC7, 0x8C, 0x78, 0xD7, 0x8D, 0x78, 0xE7, 0x8E, 0x78, 0xF7, 0x8F,
0x79, 0x07, 0x90, 0x79, 0x17, 0x91, 0x79, 0x27, 0x92, 0x79, 0x37, 0x93, 0x79, 0x47, 0x94, 0x79, 0x57, 0x95, 0x79, 0x67, 0x96, 0x79, 0x77, 0x97,
0x79, 0x87, 0x98, 0x79, 0x97, 0x99, 0x79, 0xA7, 0x9A, 0x79, 0xB7, 0x9B, 0x79, 0xC7, 0x9C, 0x79, 0xD7, 0x9D, 0x79, 0xE7, 0x9E, 0x79, 0xE7, 0x9F,
0x79, 0xF7, 0xA0, 0x7A, 0x07, 0xA1, 0x7A, 0x17, 0xA2, 0x7A, 0x27, 0xA3, 0x7A, 0x37, 0xA4, 0x7A, 0x47, 0xA5, 0x7A, 0x57, 0xA5, 0x7A, 0x67, 0xA6,
0x7A, 0x77, 0xA7, 0x7A, 0x87, 0xA8, 0x7A, 0x97, 0xA9, 0x7A, 0xA7, 0xAA, 0x7A, 0xA7, 0xAB, 0x7A, 0xB7, 0xAC, 0x7A, 0xC7, 0xAD, 0x7A, 0xD7, 0xAE,
0x7A, 0xE7, 0xAE, 0x7A, 0xF7, 0xAF, 0x7B, 0x07, 0xB0, 0x7B, 0x17, 0xB1, 0x7B, 0x17, 0xB2, 0x7B, 0x27, 0xB3, 0x7B, 0x37, 0xB4, 0x7B, 0x47, 0xB4,
0x7B, 0x57, 0xB5, 0x7B, 0x67, 0xB6, 0x7B, 0x77, 0xB7, 0x7B, 0x77, 0xB8, 0x7B, 0x87, 0xB9, 0x7B, 0x97, 0xB9, 0x7B, 0xA7, 0xBA, 0x7B, 0xB7, 0xBB,
0x7B, 0xB7, 0xBC, 0x7B, 0xC7, 0xBD, 0x7B, 0xD7, 0xBD, 0x7B, 0xE7, 0xBE, 0x7B, 0xF7, 0xBF, 0x7B, 0xF7, 0xC0, 0x7C, 0x07, 0xC1, 0x7C, 0x17, 0xC1,
0x7C, 0x27, 0xC2, 0x7C, 0x27, 0xC3, 0x7C, 0x37, 0xC4, 0x7C, 0x47, 0xC4, 0x7C, 0x57, 0xC5, 0x7C, 0x57, 0xC6, 0x7C, 0x67, 0xC7, 0x7C, 0x77, 0xC7,
0x7C, 0x87, 0xC8, 0x7C, 0x87, 0xC9, 0x7C, 0x97, 0xC9, 0x7C, 0xA7, 0xCA, 0x7C, 0xA7, 0xCB, 0x7C, 0xB7, 0xCC, 0x7C, 0xC7, 0xCC, 0x7C, 0xD7, 0xCD,
0x7C, 0xD7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x17, 0xD1, 0x7D, 0x17, 0xD2, 0x7D, 0x27, 0xD2,
0x7D, 0x37, 0xD3, 0x7D, 0x37, 0xD4, 0x7D, 0x47, 0xD4, 0x7D, 0x57, 0xD5, 0x7D, 0x57, 0xD5, 0x7D, 0x67, 0xD6, 0x7D, 0x67, 0xD7, 0x7D, 0x77, 0xD7,
0x7D, 0x87, 0xD8, 0x7D, 0x87, 0xD9, 0x7D, 0x97, 0xD9, 0x7D, 0x97, 0xDA, 0x7D, 0xA7, 0xDA, 0x7D, 0xB7, 0xDB, 0x7D, 0xB7, 0xDC, 0x7D, 0xC7, 0xDC,
0x7D, 0xC7, 0xDD, 0x7D, 0xD7, 0xDD, 0x7D, 0xE7, 0xDE, 0x7D, 0xE7, 0xDE, 0x7D, 0xF7, 0xDF, 0x7D, 0xF7, 0xE0, 0x7E, 0x07, 0xE0, 0x7E, 0x07, 0xE1,
0x7E, 0x17, 0xE1, 0x7E, 0x17, 0xE2, 0x7E, 0x27, 0xE2, 0x7E, 0x27, 0xE3, 0x7E, 0x37, 0xE3, 0x7E, 0x37, 0xE4, 0x7E, 0x47, 0xE4, 0x7E, 0x57, 0xE5,
0x7E, 0x57, 0xE5, 0x7E, 0x67, 0xE6, 0x7E, 0x67, 0xE6, 0x7E, 0x67, 0xE7, 0x7E, 0x77, 0xE7, 0x7E, 0x77, 0xE8, 0x7E, 0x87, 0xE8, 0x7E, 0x87, 0xE9,
0x7E, 0x97, 0xE9, 0x7E, 0x97, 0xEA, 0x7E, 0xA7, 0xEA, 0x7E, 0xA7, 0xEA, 0x7E, 0xB7, 0xEB, 0x7E, 0xB7, 0xEB, 0x7E, 0xC7, 0xEC, 0x7E, 0xC7, 0xEC,
0x7E, 0xC7, 0xED, 0x7E, 0xD7, 0xED, 0x7E, 0xD7, 0xED, 0x7E, 0xE7, 0xEE, 0x7E, 0xE7, 0xEE, 0x7E, 0xE7, 0xEF, 0x7E, 0xF7, 0xEF, 0x7E, 0xF7, 0xEF,
0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF0, 0x7F, 0x07, 0xF1, 0x7F, 0x17, 0xF1, 0x7F, 0x17, 0xF1, 0x7F, 0x17, 0xF2, 0x7F, 0x27, 0xF2, 0x7F, 0x27, 0xF2,
0x7F, 0x37, 0xF3, 0x7F, 0x37, 0xF3, 0x7F, 0x37, 0xF3, 0x7F, 0x47, 0xF4, 0x7F, 0x47, 0xF4, 0x7F, 0x47, 0xF4, 0x7F, 0x57, 0xF5, 0x7F, 0x57, 0xF5,
0x7F, 0x57, 0xF5, 0x7F, 0x57, 0xF6, 0x7F, 0x67, 0xF6, 0x7F, 0x67, 0xF6, 0x7F, 0x67, 0xF6, 0x7F, 0x77, 0xF7, 0x7F, 0x77, 0xF7, 0x7F, 0x77, 0xF7,
0x7F, 0x77, 0xF8, 0x7F, 0x87, 0xF8, 0x7F, 0x87, 0xF8, 0x7F, 0x87, 0xF8, 0x7F, 0x87, 0xF9, 0x7F, 0x97, 0xF9, 0x7F, 0x97, 0xF9, 0x7F, 0x97, 0xF9,
0x7F, 0x97, 0xFA, 0x7F, 0xA7, 0xFA, 0x7F, 0xA7, 0xFA, 0x7F, 0xA7, 0xFA, 0x7F, 0xA7, 0xFA, 0x7F, 0xB7, 0xFB, 0x7F, 0xB7, 0xFB, 0x7F, 0xB7, 0xFB,
0x7F, 0xB7, 0xFB, 0x7F, 0xB7, 0xFB, 0x7F, 0xC7, 0xFC, 0x7F, 0xC7, 0xFC, 0x7F, 0xC7, 0xFC, 0x7F, 0xC7, 0xFC, 0x7F, 0xC7, 0xFC, 0x7F, 0xC7, 0xFC,
0x7F, 0xD7, 0xFD, 0x7F, 0xD7, 0xFD, 0x7F, 0xD7, 0xFD, 0x7F, 0xD7, 0xFD, 0x7F, 0xD7, 0xFD, 0x7F, 0xD7, 0xFD, 0x7F, 0xD7, 0xFD, 0x7F, 0xD7, 0xFE,
0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE,
0x7F, 0xE7, 0xFE, 0x7F, 0xE7, 0xFE, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF,
0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF, 0x7F, 0xF7, 0xFF,
};
#else
// range 2000
const uint8_t LUT_sine_8192_quad_packed[3072] = {
0x00, 0x00, 0x02, 0x00, 0x30, 0x05, 0x00, 0x60, 0x08, 0x00, 0x90, 0x0B, 0x00, 0xC0, 0x0E, 0x00, 0xF0, 0x11, 0x01, 0x20, 0x14, 0x01, 0x50, 0x17,
0x01, 0x90, 0x1A, 0x01, 0xC0, 0x1D, 0x01, 0xF0, 0x20, 0x02, 0x20, 0x23, 0x02, 0x50, 0x26, 0x02, 0x80, 0x29, 0x02, 0xB0, 0x2C, 0x02, 0xE0, 0x30,
0x03, 0x10, 0x33, 0x03, 0x40, 0x36, 0x03, 0x70, 0x39, 0x03, 0xA0, 0x3C, 0x03, 0xD0, 0x3F, 0x04, 0x00, 0x42, 0x04, 0x30, 0x45, 0x04, 0x70, 0x48,
0x04, 0xA0, 0x4B, 0x04, 0xD0, 0x4E, 0x05, 0x00, 0x51, 0x05, 0x30, 0x54, 0x05, 0x60, 0x57, 0x05, 0x90, 0x5A, 0x05, 0xC0, 0x5E, 0x05, 0xF0, 0x61,
0x06, 0x20, 0x64, 0x06, 0x50, 0x67, 0x06, 0x80, 0x6A, 0x06, 0xB0, 0x6D, 0x06, 0xE0, 0x70, 0x07, 0x10, 0x73, 0x07, 0x50, 0x76, 0x07, 0x80, 0x79,
0x07, 0xB0, 0x7C, 0x07, 0xE0, 0x7F, 0x08, 0x10, 0x82, 0x08, 0x40, 0x85, 0x08, 0x70, 0x88, 0x08, 0xA0, 0x8B, 0x08, 0xD0, 0x8F, 0x09, 0x00, 0x92,
0x09, 0x30, 0x95, 0x09, 0x60, 0x98, 0x09, 0x90, 0x9B, 0x09, 0xC0, 0x9E, 0x09, 0xF0, 0xA1, 0x0A, 0x20, 0xA4, 0x0A, 0x50, 0xA7, 0x0A, 0x90, 0xAA,
0x0A, 0xC0, 0xAD, 0x0A, 0xF0, 0xB0, 0x0B, 0x20, 0xB3, 0x0B, 0x50, 0xB6, 0x0B, 0x80, 0xB9, 0x0B, 0xB0, 0xBC, 0x0B, 0xE0, 0xBF, 0x0C, 0x10, 0xC3,
0x0C, 0x40, 0xC6, 0x0C, 0x70, 0xC9, 0x0C, 0xA0, 0xCC, 0x0C, 0xD0, 0xCF, 0x0D, 0x00, 0xD2, 0x0D, 0x30, 0xD5, 0x0D, 0x60, 0xD8, 0x0D, 0x90, 0xDB,
0x0D, 0xC0, 0xDE, 0x0D, 0xF0, 0xE1, 0x0E, 0x30, 0xE4, 0x0E, 0x60, 0xE7, 0x0E, 0x90, 0xEA, 0x0E, 0xC0, 0xED, 0x0E, 0xF0, 0xF0, 0x0F, 0x20, 0xF3,
0x0F, 0x50, 0xF6, 0x0F, 0x80, 0xF9, 0x0F, 0xB0, 0xFC, 0x0F, 0xE0, 0xFF, 0x10, 0x11, 0x03, 0x10, 0x41, 0x06, 0x10, 0x71, 0x09, 0x10, 0xA1, 0x0C,
0x10, 0xD1, 0x0F, 0x11, 0x01, 0x12, 0x11, 0x31, 0x15, 0x11, 0x61, 0x18, 0x11, 0x91, 0x1B, 0x11, 0xC1, 0x1E, 0x11, 0xF1, 0x21, 0x12, 0x21, 0x24,
0x12, 0x51, 0x27, 0x12, 0x81, 0x2A, 0x12, 0xC1, 0x2D, 0x12, 0xF1, 0x30, 0x13, 0x21, 0x33, 0x13, 0x51, 0x36, 0x13, 0x81, 0x39, 0x13, 0xB1, 0x3C,
0x13, 0xE1, 0x3F, 0x14, 0x11, 0x42, 0x14, 0x41, 0x45, 0x14, 0x71, 0x48, 0x14, 0xA1, 0x4B, 0x14, 0xD1, 0x4E, 0x15, 0x01, 0x51, 0x15, 0x31, 0x54,
0x15, 0x61, 0x57, 0x15, 0x91, 0x5A, 0x15, 0xC1, 0x5D, 0x15, 0xF1, 0x60, 0x16, 0x21, 0x64, 0x16, 0x51, 0x67, 0x16, 0x81, 0x6A, 0x16, 0xB1, 0x6D,
0x16, 0xE1, 0x70, 0x17, 0x11, 0x73, 0x17, 0x41, 0x76, 0x17, 0x71, 0x79, 0x17, 0xA1, 0x7C, 0x17, 0xD1, 0x7F, 0x18, 0x01, 0x82, 0x18, 0x31, 0x85,
0x18, 0x61, 0x88, 0x18, 0x91, 0x8B, 0x18, 0xC1, 0x8E, 0x18, 0xF1, 0x91, 0x19, 0x21, 0x94, 0x19, 0x51, 0x97, 0x19, 0x81, 0x9A, 0x19, 0xB1, 0x9D,
0x19, 0xE1, 0xA0, 0x1A, 0x11, 0xA3, 0x1A, 0x41, 0xA6, 0x1A, 0x71, 0xA9, 0x1A, 0xA1, 0xAC, 0x1A, 0xD1, 0xAF, 0x1B, 0x01, 0xB2, 0x1B, 0x31, 0xB5,
0x1B, 0x61, 0xB8, 0x1B, 0x91, 0xBB, 0x1B, 0xC1, 0xBE, 0x1B, 0xF1, 0xC1, 0x1C, 0x21, 0xC4, 0x1C, 0x51, 0xC7, 0x1C, 0x81, 0xCA, 0x1C, 0xB1, 0xCD,
0x1C, 0xE1, 0xD0, 0x1D, 0x11, 0xD3, 0x1D, 0x41, 0xD6, 0x1D, 0x71, 0xD9, 0x1D, 0xA1, 0xDC, 0x1D, 0xD1, 0xDF, 0x1E, 0x01, 0xE1, 0x1E, 0x31, 0xE4,
0x1E, 0x61, 0xE7, 0x1E, 0x91, 0xEA, 0x1E, 0xC1, 0xED, 0x1E, 0xF1, 0xF0, 0x1F, 0x21, 0xF3, 0x1F, 0x51, 0xF6, 0x1F, 0x81, 0xF9, 0x1F, 0xB1, 0xFC,
0x1F, 0xE1, 0xFF, 0x20, 0x12, 0x02, 0x20, 0x42, 0x05, 0x20, 0x72, 0x08, 0x20, 0xA2, 0x0B, 0x20, 0xD2, 0x0E, 0x21, 0x02, 0x11, 0x21, 0x22, 0x14,
0x21, 0x52, 0x17, 0x21, 0x82, 0x1A, 0x21, 0xB2, 0x1D, 0x21, 0xE2, 0x20, 0x22, 0x12, 0x23, 0x22, 0x42, 0x26, 0x22, 0x72, 0x29, 0x22, 0xA2, 0x2C,
0x22, 0xD2, 0x2F, 0x23, 0x02, 0x31, 0x23, 0x32, 0x34, 0x23, 0x62, 0x37, 0x23, 0x92, 0x3A, 0x23, 0xC2, 0x3D, 0x23, 0xF2, 0x40, 0x24, 0x22, 0x43,
0x24, 0x52, 0x46, 0x24, 0x82, 0x49, 0x24, 0xA2, 0x4C, 0x24, 0xD2, 0x4F, 0x25, 0x02, 0x52, 0x25, 0x32, 0x55, 0x25, 0x62, 0x58, 0x25, 0x92, 0x5B,
0x25, 0xC2, 0x5D, 0x25, 0xF2, 0x60, 0x26, 0x22, 0x63, 0x26, 0x52, 0x66, 0x26, 0x82, 0x69, 0x26, 0xB2, 0x6C, 0x26, 0xE2, 0x6F, 0x27, 0x02, 0x72,
0x27, 0x32, 0x75, 0x27, 0x62, 0x78, 0x27, 0x92, 0x7B, 0x27, 0xC2, 0x7E, 0x27, 0xF2, 0x80, 0x28, 0x22, 0x83, 0x28, 0x52, 0x86, 0x28, 0x82, 0x89,
0x28, 0xB2, 0x8C, 0x28, 0xE2, 0x8F, 0x29, 0x02, 0x92, 0x29, 0x32, 0x95, 0x29, 0x62, 0x98, 0x29, 0x92, 0x9B, 0x29, 0xC2, 0x9D, 0x29, 0xF2, 0xA0,
0x2A, 0x22, 0xA3, 0x2A, 0x52, 0xA6, 0x2A, 0x82, 0xA9, 0x2A, 0xA2, 0xAC, 0x2A, 0xD2, 0xAF, 0x2B, 0x02, 0xB2, 0x2B, 0x32, 0xB5, 0x2B, 0x62, 0xB7,
0x2B, 0x92, 0xBA, 0x2B, 0xC2, 0xBD, 0x2B, 0xF2, 0xC0, 0x2C, 0x12, 0xC3, 0x2C, 0x42, 0xC6, 0x2C, 0x72, 0xC9, 0x2C, 0xA2, 0xCB, 0x2C, 0xD2, 0xCE,
0x2D, 0x02, 0xD1, 0x2D, 0x32, 0xD4, 0x2D, 0x62, 0xD7, 0x2D, 0x82, 0xDA, 0x2D, 0xB2, 0xDD, 0x2D, 0xE2, 0xE0, 0x2E, 0x12, 0xE2, 0x2E, 0x42, 0xE5,
0x2E, 0x72, 0xE8, 0x2E, 0x92, 0xEB, 0x2E, 0xC2, 0xEE, 0x2E, 0xF2, 0xF1, 0x2F, 0x22, 0xF3, 0x2F, 0x52, 0xF6, 0x2F, 0x82, 0xF9, 0x2F, 0xB2, 0xFC,
0x2F, 0xD2, 0xFF, 0x30, 0x03, 0x02, 0x30, 0x33, 0x04, 0x30, 0x63, 0x07, 0x30, 0x93, 0x0A, 0x30, 0xC3, 0x0D, 0x30, 0xE3, 0x10, 0x31, 0x13, 0x13,
0x31, 0x43, 0x15, 0x31, 0x73, 0x18, 0x31, 0xA3, 0x1B, 0x31, 0xC3, 0x1E, 0x31, 0xF3, 0x21, 0x32, 0x23, 0x23, 0x32, 0x53, 0x26, 0x32, 0x83, 0x29,
0x32, 0xA3, 0x2C, 0x32, 0xD3, 0x2F, 0x33, 0x03, 0x31, 0x33, 0x33, 0x34, 0x33, 0x63, 0x37, 0x33, 0x83, 0x3A, 0x33, 0xB3, 0x3D, 0x33, 0xE3, 0x3F,
0x34, 0x13, 0x42, 0x34, 0x43, 0x45, 0x34, 0x63, 0x48, 0x34, 0x93, 0x4B, 0x34, 0xC3, 0x4D, 0x34, 0xF3, 0x50, 0x35, 0x23, 0x53, 0x35, 0x43, 0x56,
0x35, 0x73, 0x58, 0x35, 0xA3, 0x5B, 0x35, 0xD3, 0x5E, 0x35, 0xF3, 0x61, 0x36, 0x23, 0x64, 0x36, 0x53, 0x66, 0x36, 0x83, 0x69, 0x36, 0xA3, 0x6C,
0x36, 0xD3, 0x6F, 0x37, 0x03, 0x71, 0x37, 0x33, 0x74, 0x37, 0x53, 0x77, 0x37, 0x83, 0x7A, 0x37, 0xB3, 0x7C, 0x37, 0xE3, 0x7F, 0x38, 0x03, 0x82,
0x38, 0x33, 0x85, 0x38, 0x63, 0x87, 0x38, 0x93, 0x8A, 0x38, 0xB3, 0x8D, 0x38, 0xE3, 0x90, 0x39, 0x13, 0x92, 0x39, 0x43, 0x95, 0x39, 0x63, 0x98,
0x39, 0x93, 0x9A, 0x39, 0xC3, 0x9D, 0x39, 0xF3, 0xA0, 0x3A, 0x13, 0xA3, 0x3A, 0x43, 0xA5, 0x3A, 0x73, 0xA8, 0x3A, 0x93, 0xAB, 0x3A, 0xC3, 0xAD,
0x3A, 0xF3, 0xB0, 0x3B, 0x13, 0xB3, 0x3B, 0x43, 0xB6, 0x3B, 0x73, 0xB8, 0x3B, 0xA3, 0xBB, 0x3B, 0xC3, 0xBE, 0x3B, 0xF3, 0xC0, 0x3C, 0x23, 0xC3,
0x3C, 0x43, 0xC6, 0x3C, 0x73, 0xC8, 0x3C, 0xA3, 0xCB, 0x3C, 0xC3, 0xCE, 0x3C, 0xF3, 0xD0, 0x3D, 0x23, 0xD3, 0x3D, 0x43, 0xD6, 0x3D, 0x73, 0xD8,
0x3D, 0xA3, 0xDB, 0x3D, 0xC3, 0xDE, 0x3D, 0xF3, 0xE0, 0x3E, 0x23, 0xE3, 0x3E, 0x43, 0xE6, 0x3E, 0x73, 0xE8, 0x3E, 0xA3, 0xEB, 0x3E, 0xC3, 0xEE,
0x3E, 0xF3, 0xF0, 0x3F, 0x23, 0xF3, 0x3F, 0x43, 0xF6, 0x3F, 0x73, 0xF8, 0x3F, 0xA3, 0xFB, 0x3F, 0xC3, 0xFE, 0x3F, 0xF4, 0x00, 0x40, 0x24, 0x03,
0x40, 0x44, 0x06, 0x40, 0x74, 0x08, 0x40, 0x94, 0x0B, 0x40, 0xC4, 0x0D, 0x40, 0xF4, 0x10, 0x41, 0x14, 0x13, 0x41, 0x44, 0x15, 0x41, 0x74, 0x18,
0x41, 0x94, 0x1A, 0x41, 0xC4, 0x1D, 0x41, 0xE4, 0x20, 0x42, 0x14, 0x22, 0x42, 0x44, 0x25, 0x42, 0x64, 0x28, 0x42, 0x94, 0x2A, 0x42, 0xB4, 0x2D,
0x42, 0xE4, 0x2F, 0x43, 0x14, 0x32, 0x43, 0x34, 0x34, 0x43, 0x64, 0x37, 0x43, 0x84, 0x3A, 0x43, 0xB4, 0x3C, 0x43, 0xE4, 0x3F, 0x44, 0x04, 0x41,
0x44, 0x34, 0x44, 0x44, 0x54, 0x47, 0x44, 0x84, 0x49, 0x44, 0xA4, 0x4C, 0x44, 0xD4, 0x4E, 0x44, 0xF4, 0x51, 0x45, 0x24, 0x53, 0x45, 0x54, 0x56,
0x45, 0x74, 0x58, 0x45, 0xA4, 0x5B, 0x45, 0xC4, 0x5E, 0x45, 0xF4, 0x60, 0x46, 0x14, 0x63, 0x46, 0x44, 0x65, 0x46, 0x64, 0x68, 0x46, 0x94, 0x6A,
0x46, 0xB4, 0x6D, 0x46, 0xE4, 0x6F, 0x47, 0x14, 0x72, 0x47, 0x34, 0x74, 0x47, 0x64, 0x77, 0x47, 0x84, 0x79, 0x47, 0xB4, 0x7C, 0x47, 0xD4, 0x7E,
0x48, 0x04, 0x81, 0x48, 0x24, 0x83, 0x48, 0x54, 0x86, 0x48, 0x74, 0x88, 0x48, 0xA4, 0x8B, 0x48, 0xC4, 0x8D, 0x48, 0xF4, 0x90, 0x49, 0x14, 0x92,
0x49, 0x44, 0x95, 0x49, 0x64, 0x97, 0x49, 0x94, 0x9A, 0x49, 0xB4, 0x9C, 0x49, 0xE4, 0x9F, 0x4A, 0x04, 0xA1, 0x4A, 0x24, 0xA4, 0x4A, 0x54, 0xA6,
0x4A, 0x74, 0xA9, 0x4A, 0xA4, 0xAB, 0x4A, 0xC4, 0xAE, 0x4A, 0xF4, 0xB0, 0x4B, 0x14, 0xB2, 0x4B, 0x44, 0xB5, 0x4B, 0x64, 0xB7, 0x4B, 0x94, 0xBA,
0x4B, 0xB4, 0xBC, 0x4B, 0xD4, 0xBF, 0x4C, 0x04, 0xC1, 0x4C, 0x24, 0xC4, 0x4C, 0x54, 0xC6, 0x4C, 0x74, 0xC8, 0x4C, 0xA4, 0xCB, 0x4C, 0xC4, 0xCD,
0x4C, 0xE4, 0xD0, 0x4D, 0x14, 0xD2, 0x4D, 0x34, 0xD5, 0x4D, 0x64, 0xD7, 0x4D, 0x84, 0xD9, 0x4D, 0xB4, 0xDC, 0x4D, 0xD4, 0xDE, 0x4D, 0xF4, 0xE1,
0x4E, 0x24, 0xE3, 0x4E, 0x44, 0xE5, 0x4E, 0x74, 0xE8, 0x4E, 0x94, 0xEA, 0x4E, 0xB4, 0xEC, 0x4E, 0xE4, 0xEF, 0x4F, 0x04, 0xF1, 0x4F, 0x24, 0xF4,
0x4F, 0x54, 0xF6, 0x4F, 0x74, 0xF8, 0x4F, 0xA4, 0xFB, 0x4F, 0xC4, 0xFD, 0x4F, 0xE4, 0xFF, 0x50, 0x15, 0x02, 0x50, 0x35, 0x04, 0x50, 0x55, 0x06,
0x50, 0x85, 0x09, 0x50, 0xA5, 0x0B, 0x50, 0xC5, 0x0E, 0x50, 0xF5, 0x10, 0x51, 0x15, 0x12, 0x51, 0x35, 0x15, 0x51, 0x65, 0x17, 0x51, 0x85, 0x19,
0x51, 0xA5, 0x1C, 0x51, 0xD5, 0x1E, 0x51, 0xF5, 0x20, 0x52, 0x15, 0x22, 0x52, 0x45, 0x25, 0x52, 0x65, 0x27, 0x52, 0x85, 0x29, 0x52, 0xB5, 0x2C,
0x52, 0xD5, 0x2E, 0x52, 0xF5, 0x30, 0x53, 0x15, 0x33, 0x53, 0x45, 0x35, 0x53, 0x65, 0x37, 0x53, 0x85, 0x39, 0x53, 0xB5, 0x3C, 0x53, 0xD5, 0x3E,
0x53, 0xF5, 0x40, 0x54, 0x15, 0x43, 0x54, 0x45, 0x45, 0x54, 0x65, 0x47, 0x54, 0x85, 0x49, 0x54, 0xA5, 0x4C, 0x54, 0xD5, 0x4E, 0x54, 0xF5, 0x50,
0x55, 0x15, 0x52, 0x55, 0x35, 0x55, 0x55, 0x65, 0x57, 0x55, 0x85, 0x59, 0x55, 0xA5, 0x5B, 0x55, 0xC5, 0x5E, 0x55, 0xF5, 0x60, 0x56, 0x15, 0x62,
0x56, 0x35, 0x64, 0x56, 0x55, 0x66, 0x56, 0x85, 0x69, 0x56, 0xA5, 0x6B, 0x56, 0xC5, 0x6D, 0x56, 0xE5, 0x6F, 0x57, 0x05, 0x71, 0x57, 0x35, 0x74,
0x57, 0x55, 0x76, 0x57, 0x75, 0x78, 0x57, 0x95, 0x7A, 0x57, 0xB5, 0x7C, 0x57, 0xE5, 0x7F, 0x58, 0x05, 0x81, 0x58, 0x25, 0x83, 0x58, 0x45, 0x85,
0x58, 0x65, 0x87, 0x58, 0x85, 0x89, 0x58, 0xB5, 0x8C, 0x58, 0xD5, 0x8E, 0x58, 0xF5, 0x90, 0x59, 0x15, 0x92, 0x59, 0x35, 0x94, 0x59, 0x55, 0x96,
0x59, 0x75, 0x99, 0x59, 0xA5, 0x9B, 0x59, 0xC5, 0x9D, 0x59, 0xE5, 0x9F, 0x5A, 0x05, 0xA1, 0x5A, 0x25, 0xA3, 0x5A, 0x45, 0xA5, 0x5A, 0x65, 0xA7,
0x5A, 0x85, 0xAA, 0x5A, 0xB5, 0xAC, 0x5A, 0xD5, 0xAE, 0x5A, 0xF5, 0xB0, 0x5B, 0x15, 0xB2, 0x5B, 0x35, 0xB4, 0x5B, 0x55, 0xB6, 0x5B, 0x75, 0xB8,
0x5B, 0x95, 0xBA, 0x5B, 0xB5, 0xBC, 0x5B, 0xD5, 0xBF, 0x5C, 0x05, 0xC1, 0x5C, 0x25, 0xC3, 0x5C, 0x45, 0xC5, 0x5C, 0x65, 0xC7, 0x5C, 0x85, 0xC9,
0x5C, 0xA5, 0xCB, 0x5C, 0xC5, 0xCD, 0x5C, 0xE5, 0xCF, 0x5D, 0x05, 0xD1, 0x5D, 0x25, 0xD3, 0x5D, 0x45, 0xD5, 0x5D, 0x65, 0xD7, 0x5D, 0x85, 0xD9,
0x5D, 0xA5, 0xDB, 0x5D, 0xC5, 0xDD, 0x5D, 0xE5, 0xDF, 0x5E, 0x05, 0xE1, 0x5E, 0x25, 0xE3, 0x5E, 0x45, 0xE5, 0x5E, 0x65, 0xE7, 0x5E, 0x85, 0xE9,
0x5E, 0xA5, 0xEB, 0x5E, 0xC5, 0xED, 0x5E, 0xE5, 0xEF, 0x5F, 0x05, 0xF1, 0x5F, 0x25, 0xF3, 0x5F, 0x45, 0xF5, 0x5F, 0x65, 0xF7, 0x5F, 0x85, 0xF9,
0x5F, 0xA5, 0xFB, 0x5F, 0xC5, 0xFD, 0x5F, 0xE5, 0xFF, 0x60, 0x06, 0x01, 0x60, 0x26, 0x03, 0x60, 0x46, 0x05, 0x60, 0x66, 0x07, 0x60, 0x86, 0x09,
0x60, 0xA6, 0x0B, 0x60, 0xC6, 0x0D, 0x60, 0xE6, 0x0F, 0x61, 0x06, 0x11, 0x61, 0x26, 0x13, 0x61, 0x46, 0x15, 0x61, 0x66, 0x17, 0x61, 0x86, 0x19,
0x61, 0x96, 0x1A, 0x61, 0xB6, 0x1C, 0x61, 0xD6, 0x1E, 0x61, 0xF6, 0x20, 0x62, 0x16, 0x22, 0x62, 0x36, 0x24, 0x62, 0x56, 0x26, 0x62, 0x76, 0x28,
0x62, 0x96, 0x2A, 0x62, 0xB6, 0x2C, 0x62, 0xC6, 0x2D, 0x62, 0xE6, 0x2F, 0x63, 0x06, 0x31, 0x63, 0x26, 0x33, 0x63, 0x46, 0x35, 0x63, 0x66, 0x37,
0x63, 0x86, 0x39, 0x63, 0xA6, 0x3A, 0x63, 0xB6, 0x3C, 0x63, 0xD6, 0x3E, 0x63, 0xF6, 0x40, 0x64, 0x16, 0x42, 0x64, 0x36, 0x44, 0x64, 0x56, 0x46,
0x64, 0x66, 0x47, 0x64, 0x86, 0x49, 0x64, 0xA6, 0x4B, 0x64, 0xC6, 0x4D, 0x64, 0xE6, 0x4F, 0x65, 0x06, 0x50, 0x65, 0x16, 0x52, 0x65, 0x36, 0x54,
0x65, 0x56, 0x56, 0x65, 0x76, 0x58, 0x65, 0x96, 0x59, 0x65, 0xA6, 0x5B, 0x65, 0xC6, 0x5D, 0x65, 0xE6, 0x5F, 0x66, 0x06, 0x61, 0x66, 0x16, 0x62,
0x66, 0x36, 0x64, 0x66, 0x56, 0x66, 0x66, 0x76, 0x68, 0x66, 0x86, 0x69, 0x66, 0xA6, 0x6B, 0x66, 0xC6, 0x6D, 0x66, 0xE6, 0x6F, 0x66, 0xF6, 0x70,
0x67, 0x16, 0x72, 0x67, 0x36, 0x74, 0x67, 0x56, 0x76, 0x67, 0x66, 0x77, 0x67, 0x86, 0x79, 0x67, 0xA6, 0x7B, 0x67, 0xC6, 0x7C, 0x67, 0xD6, 0x7E,
0x67, 0xF6, 0x80, 0x68, 0x16, 0x81, 0x68, 0x26, 0x83, 0x68, 0x46, 0x85, 0x68, 0x66, 0x87, 0x68, 0x76, 0x88, 0x68, 0x96, 0x8A, 0x68, 0xB6, 0x8C,
0x68, 0xC6, 0x8D, 0x68, 0xE6, 0x8F, 0x69, 0x06, 0x91, 0x69, 0x16, 0x92, 0x69, 0x36, 0x94, 0x69, 0x56, 0x96, 0x69, 0x66, 0x97, 0x69, 0x86, 0x99,
0x69, 0xA6, 0x9B, 0x69, 0xB6, 0x9C, 0x69, 0xD6, 0x9E, 0x69, 0xF6, 0x9F, 0x6A, 0x06, 0xA1, 0x6A, 0x26, 0xA3, 0x6A, 0x36, 0xA4, 0x6A, 0x56, 0xA6,
0x6A, 0x76, 0xA8, 0x6A, 0x86, 0xA9, 0x6A, 0xA6, 0xAB, 0x6A, 0xC6, 0xAC, 0x6A, 0xD6, 0xAE, 0x6A, 0xF6, 0xB0, 0x6B, 0x06, 0xB1, 0x6B, 0x26, 0xB3,
0x6B, 0x36, 0xB4, 0x6B, 0x56, 0xB6, 0x6B, 0x76, 0xB7, 0x6B, 0x86, 0xB9, 0x6B, 0xA6, 0xBB, 0x6B, 0xB6, 0xBC, 0x6B, 0xD6, 0xBE, 0x6B, 0xE6, 0xBF,
0x6C, 0x06, 0xC1, 0x6C, 0x16, 0xC2, 0x6C, 0x36, 0xC4, 0x6C, 0x56, 0xC5, 0x6C, 0x66, 0xC7, 0x6C, 0x86, 0xC8, 0x6C, 0x96, 0xCA, 0x6C, 0xB6, 0xCB,
0x6C, 0xC6, 0xCD, 0x6C, 0xE6, 0xCE, 0x6C, 0xF6, 0xD0, 0x6D, 0x16, 0xD1, 0x6D, 0x26, 0xD3, 0x6D, 0x46, 0xD4, 0x6D, 0x56, 0xD6, 0x6D, 0x76, 0xD7,
0x6D, 0x86, 0xD9, 0x6D, 0xA6, 0xDA, 0x6D, 0xB6, 0xDC, 0x6D, 0xD6, 0xDD, 0x6D, 0xE6, 0xDF, 0x6D, 0xF6, 0xE0, 0x6E, 0x16, 0xE2, 0x6E, 0x26, 0xE3,
0x6E, 0x46, 0xE5, 0x6E, 0x56, 0xE6, 0x6E, 0x76, 0xE7, 0x6E, 0x86, 0xE9, 0x6E, 0xA6, 0xEA, 0x6E, 0xB6, 0xEC, 0x6E, 0xC6, 0xED, 0x6E, 0xE6, 0xEF,
0x6E, 0xF6, 0xF0, 0x6F, 0x16, 0xF1, 0x6F, 0x26, 0xF3, 0x6F, 0x36, 0xF4, 0x6F, 0x56, 0xF6, 0x6F, 0x66, 0xF7, 0x6F, 0x86, 0xF8, 0x6F, 0x96, 0xFA,
0x6F, 0xA6, 0xFB, 0x6F, 0xC6, 0xFD, 0x6F, 0xD6, 0xFE, 0x6F, 0xF6, 0xFF, 0x70, 0x07, 0x01, 0x70, 0x17, 0x02, 0x70, 0x37, 0x03, 0x70, 0x47, 0x05,
0x70, 0x57, 0x06, 0x70, 0x77, 0x07, 0x70, 0x87, 0x09, 0x70, 0x97, 0x0A, 0x70, 0xB7, 0x0B, 0x70, 0xC7, 0x0D, 0x70, 0xD7, 0x0E, 0x70, 0xF7, 0x0F,
0x71, 0x07, 0x11, 0x71, 0x17, 0x12, 0x71, 0x37, 0x13, 0x71, 0x47, 0x15, 0x71, 0x57, 0x16, 0x71, 0x67, 0x17, 0x71, 0x87, 0x18, 0x71, 0x97, 0x1A,
0x71, 0xA7, 0x1B, 0x71, 0xC7, 0x1C, 0x71, 0xD7, 0x1E, 0x71, 0xE7, 0x1F, 0x71, 0xF7, 0x20, 0x72, 0x17, 0x21, 0x72, 0x27, 0x23, 0x72, 0x37, 0x24,
0x72, 0x47, 0x25, 0x72, 0x67, 0x26, 0x72, 0x77, 0x28, 0x72, 0x87, 0x29, 0x72, 0x97, 0x2A, 0x72, 0xB7, 0x2B, 0x72, 0xC7, 0x2C, 0x72, 0xD7, 0x2E,
0x72, 0xE7, 0x2F, 0x72, 0xF7, 0x30, 0x73, 0x17, 0x31, 0x73, 0x27, 0x32, 0x73, 0x37, 0x34, 0x73, 0x47, 0x35, 0x73, 0x57, 0x36, 0x73, 0x77, 0x37,
0x73, 0x87, 0x38, 0x73, 0x97, 0x3A, 0x73, 0xA7, 0x3B, 0x73, 0xB7, 0x3C, 0x73, 0xC7, 0x3D, 0x73, 0xE7, 0x3E, 0x73, 0xF7, 0x3F, 0x74, 0x07, 0x40,
0x74, 0x17, 0x42, 0x74, 0x27, 0x43, 0x74, 0x37, 0x44, 0x74, 0x47, 0x45, 0x74, 0x67, 0x46, 0x74, 0x77, 0x47, 0x74, 0x87, 0x48, 0x74, 0x97, 0x49,
0x74, 0xA7, 0x4B, 0x74, 0xB7, 0x4C, 0x74, 0xC7, 0x4D, 0x74, 0xD7, 0x4E, 0x74, 0xE7, 0x4F, 0x74, 0xF7, 0x50, 0x75, 0x17, 0x51, 0x75, 0x27, 0x52,
0x75, 0x37, 0x53, 0x75, 0x47, 0x54, 0x75, 0x57, 0x55, 0x75, 0x67, 0x56, 0x75, 0x77, 0x57, 0x75, 0x87, 0x58, 0x75, 0x97, 0x5A, 0x75, 0xA7, 0x5B,
0x75, 0xB7, 0x5C, 0x75, 0xC7, 0x5D, 0x75, 0xD7, 0x5E, 0x75, 0xE7, 0x5F, 0x75, 0xF7, 0x60, 0x76, 0x07, 0x61, 0x76, 0x17, 0x62, 0x76, 0x27, 0x63,
0x76, 0x37, 0x64, 0x76, 0x47, 0x65, 0x76, 0x57, 0x66, 0x76, 0x67, 0x67, 0x76, 0x77, 0x68, 0x76, 0x87, 0x69, 0x76, 0x97, 0x6A, 0x76, 0xA7, 0x6B,
0x76, 0xB7, 0x6C, 0x76, 0xC7, 0x6C, 0x76, 0xD7, 0x6D, 0x76, 0xE7, 0x6E, 0x76, 0xF7, 0x6F, 0x77, 0x07, 0x70, 0x77, 0x17, 0x71, 0x77, 0x27, 0x72,
0x77, 0x37, 0x73, 0x77, 0x47, 0x74, 0x77, 0x47, 0x75, 0x77, 0x57, 0x76, 0x77, 0x67, 0x77, 0x77, 0x77, 0x78, 0x77, 0x87, 0x79, 0x77, 0x97, 0x79,
0x77, 0xA7, 0x7A, 0x77, 0xB7, 0x7B, 0x77, 0xC7, 0x7C, 0x77, 0xD7, 0x7D, 0x77, 0xD7, 0x7E, 0x77, 0xE7, 0x7F, 0x77, 0xF7, 0x80, 0x78, 0x07, 0x80,
0x78, 0x17, 0x81, 0x78, 0x27, 0x82, 0x78, 0x37, 0x83, 0x78, 0x37, 0x84, 0x78, 0x47, 0x85, 0x78, 0x57, 0x85, 0x78, 0x67, 0x86, 0x78, 0x77, 0x87,
0x78, 0x87, 0x88, 0x78, 0x87, 0x89, 0x78, 0x97, 0x8A, 0x78, 0xA7, 0x8A, 0x78, 0xB7, 0x8B, 0x78, 0xC7, 0x8C, 0x78, 0xC7, 0x8D, 0x78, 0xD7, 0x8E,
0x78, 0xE7, 0x8E, 0x78, 0xF7, 0x8F, 0x79, 0x07, 0x90, 0x79, 0x07, 0x91, 0x79, 0x17, 0x91, 0x79, 0x27, 0x92, 0x79, 0x37, 0x93, 0x79, 0x37, 0x94,
0x79, 0x47, 0x94, 0x79, 0x57, 0x95, 0x79, 0x67, 0x96, 0x79, 0x67, 0x97, 0x79, 0x77, 0x97, 0x79, 0x87, 0x98, 0x79, 0x87, 0x99, 0x79, 0x97, 0x9A,
0x79, 0xA7, 0x9A, 0x79, 0xB7, 0x9B, 0x79, 0xB7, 0x9C, 0x79, 0xC7, 0x9C, 0x79, 0xD7, 0x9D, 0x79, 0xD7, 0x9E, 0x79, 0xE7, 0x9E, 0x79, 0xF7, 0x9F,
0x79, 0xF7, 0xA0, 0x7A, 0x07, 0xA0, 0x7A, 0x17, 0xA1, 0x7A, 0x17, 0xA2, 0x7A, 0x27, 0xA2, 0x7A, 0x37, 0xA3, 0x7A, 0x37, 0xA4, 0x7A, 0x47, 0xA4,
0x7A, 0x57, 0xA5, 0x7A, 0x57, 0xA6, 0x7A, 0x67, 0xA6, 0x7A, 0x77, 0xA7, 0x7A, 0x77, 0xA7, 0x7A, 0x87, 0xA8, 0x7A, 0x87, 0xA9, 0x7A, 0x97, 0xA9,
0x7A, 0xA7, 0xAA, 0x7A, 0xA7, 0xAA, 0x7A, 0xB7, 0xAB, 0x7A, 0xB7, 0xAC, 0x7A, 0xC7, 0xAC, 0x7A, 0xD7, 0xAD, 0x7A, 0xD7, 0xAD, 0x7A, 0xE7, 0xAE,
0x7A, 0xE7, 0xAE, 0x7A, 0xF7, 0xAF, 0x7A, 0xF7, 0xB0, 0x7B, 0x07, 0xB0, 0x7B, 0x07, 0xB1, 0x7B, 0x17, 0xB1, 0x7B, 0x17, 0xB2, 0x7B, 0x27, 0xB2,
0x7B, 0x37, 0xB3, 0x7B, 0x37, 0xB3, 0x7B, 0x47, 0xB4, 0x7B, 0x47, 0xB4, 0x7B, 0x57, 0xB5, 0x7B, 0x57, 0xB5, 0x7B, 0x67, 0xB6, 0x7B, 0x67, 0xB6,
0x7B, 0x77, 0xB7, 0x7B, 0x77, 0xB7, 0x7B, 0x87, 0xB8, 0x7B, 0x87, 0xB8, 0x7B, 0x97, 0xB9, 0x7B, 0x97, 0xB9, 0x7B, 0x97, 0xBA, 0x7B, 0xA7, 0xBA,
0x7B, 0xA7, 0xBB, 0x7B, 0xB7, 0xBB, 0x7B, 0xB7, 0xBB, 0x7B, 0xC7, 0xBC, 0x7B, 0xC7, 0xBC, 0x7B, 0xD7, 0xBD, 0x7B, 0xD7, 0xBD, 0x7B, 0xD7, 0xBE,
0x7B, 0xE7, 0xBE, 0x7B, 0xE7, 0xBE, 0x7B, 0xF7, 0xBF, 0x7B, 0xF7, 0xBF, 0x7B, 0xF7, 0xC0, 0x7C, 0x07, 0xC0, 0x7C, 0x07, 0xC0, 0x7C, 0x17, 0xC1,
0x7C, 0x17, 0xC1, 0x7C, 0x17, 0xC2, 0x7C, 0x27, 0xC2, 0x7C, 0x27, 0xC2, 0x7C, 0x27, 0xC3, 0x7C, 0x37, 0xC3, 0x7C, 0x37, 0xC3, 0x7C, 0x37, 0xC4,
0x7C, 0x47, 0xC4, 0x7C, 0x47, 0xC4, 0x7C, 0x47, 0xC5, 0x7C, 0x57, 0xC5, 0x7C, 0x57, 0xC5, 0x7C, 0x57, 0xC6, 0x7C, 0x67, 0xC6, 0x7C, 0x67, 0xC6,
0x7C, 0x67, 0xC7, 0x7C, 0x77, 0xC7, 0x7C, 0x77, 0xC7, 0x7C, 0x77, 0xC7, 0x7C, 0x87, 0xC8, 0x7C, 0x87, 0xC8, 0x7C, 0x87, 0xC8, 0x7C, 0x87, 0xC8,
0x7C, 0x97, 0xC9, 0x7C, 0x97, 0xC9, 0x7C, 0x97, 0xC9, 0x7C, 0x97, 0xCA, 0x7C, 0xA7, 0xCA, 0x7C, 0xA7, 0xCA, 0x7C, 0xA7, 0xCA, 0x7C, 0xA7, 0xCA,
0x7C, 0xB7, 0xCB, 0x7C, 0xB7, 0xCB, 0x7C, 0xB7, 0xCB, 0x7C, 0xB7, 0xCB, 0x7C, 0xB7, 0xCC, 0x7C, 0xC7, 0xCC, 0x7C, 0xC7, 0xCC, 0x7C, 0xC7, 0xCC,
0x7C, 0xC7, 0xCC, 0x7C, 0xC7, 0xCD, 0x7C, 0xD7, 0xCD, 0x7C, 0xD7, 0xCD, 0x7C, 0xD7, 0xCD, 0x7C, 0xD7, 0xCD, 0x7C, 0xD7, 0xCD, 0x7C, 0xD7, 0xCE,
0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xE7, 0xCE, 0x7C, 0xF7, 0xCF,
0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xCF,
0x7C, 0xF7, 0xCF, 0x7C, 0xF7, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0,
0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0, 0x7D, 0x07, 0xD0,
};
#endif
-147
View File
@@ -1,147 +0,0 @@
//
// Created by MightyPork on 2018/02/03.
//
#include "platform.h"
#include "unit_base.h"
#define DAC_INTERNAL
#include "_dac_internal.h"
/** Allocate data structure and set defaults */
error_t UDAC_preInit(Unit *unit)
{
struct priv *priv = unit->data = calloc_ck(1, sizeof(struct priv));
if (priv == NULL) return E_OUT_OF_MEM;
for (int i = 0; i < 2; i++) {
priv->cfg.ch[i].buffered = true;
priv->cfg.ch[i].enable = true;
priv->cfg.ch[i].noise_level = 2;
priv->cfg.ch[i].noise_type = NOISE_NONE;
priv->ch[i].waveform = UDAC_WAVE_DC;
priv->ch[i].dc_level = 2047;
priv->ch[i].rectangle_ontime = 4096; // half
priv->ch[i].rectangle_high = 4095;
priv->ch[i].rectangle_low = 0;
priv->ch[i].counter = 0;
priv->ch[i].increment = 0; // stopped
priv->ch[i].phase = 0;
}
UDAC_SetFreq(unit, 0, 1000);
UDAC_SetFreq(unit, 1, 1000);
return E_SUCCESS;
}
/** Finalize unit set-up */
error_t UDAC_init(Unit *unit)
{
bool suc = true;
struct priv *priv = unit->data;
// copy noise config
priv->ch[0].noise_type = priv->cfg.ch[0].noise_type;
priv->ch[0].noise_level = priv->cfg.ch[0].noise_level;
priv->ch[1].noise_type = priv->cfg.ch[1].noise_type;
priv->ch[1].noise_level = priv->cfg.ch[1].noise_level;
// this may change for different devices
const Resource r_ch1 = R_PA4;
const Resource r_ch2 = R_PA5;
TRY(rsc_claim(unit, R_TIM6));
priv->TIMx = TIM6;
const bool e1 = priv->cfg.ch[0].enable;
const bool e2 = priv->cfg.ch[1].enable;
if (e1) {
TRY(rsc_claim(unit, r_ch1));
}
if (e2) {
TRY(rsc_claim(unit, r_ch2));
}
TRY(rsc_claim(unit, R_DAC1));
// ensure the peripheral is clean (this may be redundant)
__HAL_RCC_DAC1_FORCE_RESET();
__HAL_RCC_DAC1_RELEASE_RESET();
hw_periph_clock_enable(DAC1);
hw_periph_clock_enable(priv->TIMx);
GPIO_TypeDef *port;
uint32_t ll;
if (e1) {
assert_param(hw_pinrsc2ll(r_ch1, &port, &ll));
LL_GPIO_SetPinMode(port, ll, LL_GPIO_MODE_ANALOG);
}
if (e2) {
assert_param(hw_pinrsc2ll(r_ch1, &port, &ll));
LL_GPIO_SetPinMode(port, ll, LL_GPIO_MODE_ANALOG);
}
uint16_t presc = 1;
// presets... TODO pick the highest useable one (or find a new one)
#if UDAC_TIM_FREQ_DIVIDER == 1
uint32_t count = PLAT_AHB_MHZ;
#elif UDAC_TIM_FREQ_DIVIDER == 2
uint32_t count = PLAT_AHB_MHZ * 2;
#elif UDAC_TIM_FREQ_DIVIDER == 4
uint32_t count = PLAT_AHB_MHZ * 4;
#elif UDAC_TIM_FREQ_DIVIDER == 8
uint32_t count = PLAT_AHB_MHZ * 8;
#else
#error "bad freq"
#endif
// dbg("Presc %d, count %d", (int)presc, (int)count);
LL_TIM_SetPrescaler(priv->TIMx, (uint32_t) (presc - 1));
LL_TIM_SetAutoReload(priv->TIMx, count - 1);
LL_TIM_EnableARRPreload(priv->TIMx);
LL_TIM_GenerateEvent_UPDATE(priv->TIMx);
irqd_attach(priv->TIMx, UDAC_HandleIT, unit);
LL_TIM_EnableIT_UPDATE(priv->TIMx);
UDAC_Reconfigure(unit); // works with the timer - it should be inited already
// do not enbale counter initially - no need
// LL_TIM_EnableCounter(priv->TIMx);
return E_SUCCESS;
}
/** Tear down the unit */
void UDAC_deInit(Unit *unit)
{
struct priv *priv = unit->data;
// de-init peripherals
if (unit->status == E_SUCCESS ) {
LL_DAC_DeInit(DAC);
LL_TIM_DisableCounter(priv->TIMx);
hw_periph_clock_disable(DAC1);
hw_periph_clock_disable(priv->TIMx);
irqd_detach(priv->TIMx, UDAC_HandleIT);
}
// Release all resources, deinit pins
rsc_teardown(unit);
// Free memory
free_ck(unit->data);
}
-111
View File
@@ -1,111 +0,0 @@
//
// Created by MightyPork on 2018/02/03.
//
#ifndef GEX_F072_DAC_INTERNAL_H
#define GEX_F072_DAC_INTERNAL_H
#ifndef DAC_INTERNAL
#error bad include!
#endif
#include "unit_base.h"
enum UDAC_Noise {
NOISE_NONE = 0b00, // 0
NOISE_WHITE = 0b01, // 1
NOISE_TRIANGLE = 0b10, // 2
};
enum UDAC_Waveform {
UDAC_WAVE_DC,
UDAC_WAVE_SINE,
UDAC_WAVE_TRIANGLE,
UDAC_WAVE_SAWTOOTH_UP,
UDAC_WAVE_SAWTOOTH_DOWN,
UDAC_WAVE_RECTANGLE,
};
struct udac_channel_cfg {
bool enable;
bool buffered;
enum UDAC_Noise noise_type;
uint8_t noise_level; // 0-11
};
// 0 - 1 MHz, 2-500k, 4-250k, 8-125k
#define UDAC_TIM_FREQ_DIVIDER 8
#define UDAC_INDEX_WIDTH 13 // corresponds to 8192 places
#define UDAC_INDEX_SHIFT (32 - UDAC_INDEX_WIDTH)
#define UDAC_MAX_INDEX ((1 << UDAC_INDEX_WIDTH) - 1)
#define UDAC_VALUE_COUNT (1 << UDAC_INDEX_WIDTH)
extern const uint8_t LUT_sine_8192_quad_packed[];
struct udac_channel_live {
enum UDAC_Noise noise_type;
uint8_t noise_level; // 0-11
enum UDAC_Waveform waveform;
uint16_t rectangle_ontime; // for rectangle wave, 0-8191
uint16_t rectangle_high;
uint16_t rectangle_low;
uint16_t dc_level; // for DC wave
uint32_t counter;
uint32_t increment;
// last set phase if the frequencies are the same
// - can be used for live frequency changes without reset (meaningful only with matching increment values)
uint16_t phase;
uint16_t last_index;
uint16_t last_value;
};
/** Private data structure */
struct priv {
// settings
struct {
struct udac_channel_cfg ch[2];
} cfg;
// internal state
struct udac_channel_live ch[2];
TIM_TypeDef *TIMx; // timer used for the DDS function
};
/** Allocate data structure and set defaults */
error_t UDAC_preInit(Unit *unit);
/** Load from a binary buffer stored in Flash */
void UDAC_loadBinary(Unit *unit, PayloadParser *pp);
/** Write to a binary buffer for storing in Flash */
void UDAC_writeBinary(Unit *unit, PayloadBuilder *pb);
// ------------------------------------------------------------------------
/** Parse a key-value pair from the INI file */
error_t UDAC_loadIni(Unit *unit, const char *key, const char *value);
/** Generate INI file section for the unit */
void UDAC_writeIni(Unit *unit, IniWriter *iw);
// ------------------------------------------------------------------------
/** Finalize unit set-up */
error_t UDAC_init(Unit *unit);
/** Tear down the unit */
void UDAC_deInit(Unit *unit);
void UDAC_Reconfigure(Unit *unit);
void UDAC_HandleIT(void *arg);
error_t UDAC_SetFreq(Unit *unit, int channel, float freq);
void UDAC_ToggleTimerIfNeeded(Unit *unit);
#endif //GEX_F072_DAC_INTERNAL_H
-131
View File
@@ -1,131 +0,0 @@
//
// Created by MightyPork on 2018/02/03.
//
#include "platform.h"
#include "unit_base.h"
#define DAC_INTERNAL
#include "_dac_internal.h"
/** Load from a binary buffer stored in Flash */
void UDAC_loadBinary(Unit *unit, PayloadParser *pp)
{
struct priv *priv = unit->data;
uint8_t version = pp_u8(pp);
(void)version;
priv->cfg.ch[0].enable = pp_bool(pp);
priv->cfg.ch[0].buffered = pp_bool(pp);
priv->cfg.ch[0].noise_type = (enum UDAC_Noise) pp_u8(pp);
priv->cfg.ch[0].noise_level = pp_u8(pp);
priv->cfg.ch[1].enable = pp_bool(pp);
priv->cfg.ch[1].buffered = pp_bool(pp);
priv->cfg.ch[1].noise_type = (enum UDAC_Noise) pp_u8(pp);
priv->cfg.ch[1].noise_level = pp_u8(pp);
}
/** Write to a binary buffer for storing in Flash */
void UDAC_writeBinary(Unit *unit, PayloadBuilder *pb)
{
struct priv *priv = unit->data;
pb_u8(pb, 0); // version
pb_bool(pb, priv->cfg.ch[0].enable);
pb_bool(pb, priv->cfg.ch[0].buffered);
pb_u8(pb, priv->cfg.ch[0].noise_type);
pb_u8(pb, priv->cfg.ch[0].noise_level);
pb_bool(pb, priv->cfg.ch[1].enable);
pb_bool(pb, priv->cfg.ch[1].buffered);
pb_u8(pb, priv->cfg.ch[1].noise_type);
pb_u8(pb, priv->cfg.ch[1].noise_level);
}
// ------------------------------------------------------------------------
/** Parse a key-value pair from the INI file */
error_t UDAC_loadIni(Unit *unit, const char *key, const char *value)
{
bool suc = true;
struct priv *priv = unit->data;
// Ch1
if (streq(key, "ch1_enable")) {
priv->cfg.ch[0].enable = cfg_bool_parse(value, &suc);
}
else if (streq(key, "ch1_buff")) {
priv->cfg.ch[0].buffered = cfg_bool_parse(value, &suc);
}
else if (streq(key, "ch1_noise")) {
priv->cfg.ch[0].noise_type =
(enum UDAC_Noise) cfg_enum3_parse(value,
"NONE", NOISE_NONE,
"WHITE", NOISE_WHITE,
"TRIANGLE", NOISE_TRIANGLE, &suc);
}
else if (streq(key, "ch1_noise-level")) {
uint8_t x = cfg_u8_parse(value, &suc);
if (x == 0) x = 1;
if (x > 12) x = 12;
priv->cfg.ch[0].noise_level = (uint8_t) (x - 1);
}
// Ch2
else if (streq(key, "ch2_enable")) {
priv->cfg.ch[1].enable = cfg_bool_parse(value, &suc);
}
else if (streq(key, "ch2_buff")) {
priv->cfg.ch[1].buffered = cfg_bool_parse(value, &suc);
}
else if (streq(key, "ch2_noise")) {
priv->cfg.ch[1].noise_type =
(enum UDAC_Noise) cfg_enum3_parse(value,
"NONE", NOISE_NONE,
"WHITE", NOISE_WHITE,
"TRIANGLE", NOISE_TRIANGLE, &suc);
}
else if (streq(key, "ch2_noise-level")) {
uint8_t x = cfg_u8_parse(value, &suc);
if (x == 0) x = 1;
if (x > 12) x = 12;
priv->cfg.ch[1].noise_level = (uint8_t) (x - 1);
}
// end
else {
return E_BAD_KEY;
}
if (!suc) return E_BAD_VALUE;
return E_SUCCESS;
}
/** Generate INI file section for the unit */
void UDAC_writeIni(Unit *unit, IniWriter *iw)
{
struct priv *priv = unit->data;
iw_comment(iw, "Enabled channels (1:A4, 2:A5)");
iw_entry_s(iw, "ch1_enable", str_yn(priv->cfg.ch[0].enable));
iw_entry_s(iw, "ch2_enable", str_yn(priv->cfg.ch[1].enable));
iw_comment(iw, "Enable output buffer");
iw_entry_s(iw, "ch1_buff", str_yn(priv->cfg.ch[0].buffered));
iw_entry_s(iw, "ch2_buff", str_yn(priv->cfg.ch[1].buffered));
iw_comment(iw, "Superimposed noise type (NONE,WHITE,TRIANGLE) and nbr. of bits (1-12)");
iw_entry_s(iw, "ch1_noise", cfg_enum3_encode(priv->cfg.ch[0].noise_type,
NOISE_NONE, "NONE",
NOISE_WHITE, "WHITE",
NOISE_TRIANGLE, "TRIANGLE"));
iw_entry_d(iw, "ch1_noise-level", priv->cfg.ch[0].noise_level + 1);
iw_entry_s(iw, "ch2_noise", cfg_enum3_encode(priv->cfg.ch[1].noise_type,
NOISE_NONE, "NONE",
NOISE_WHITE, "WHITE",
NOISE_TRIANGLE, "TRIANGLE"));
iw_entry_d(iw, "ch2_noise-level", priv->cfg.ch[1].noise_level + 1);
}
-166
View File
@@ -1,166 +0,0 @@
//
// Created by MightyPork on 2017/11/25.
//
#include "unit_base.h"
#include "unit_dac.h"
#define DAC_INTERNAL
#include "_dac_internal.h"
// ------------------------------------------------------------------------
// Works OK up to about 20 kHz, could work faster with a faster interrupt
// (may be possible with some optimizations / adjusting priorities...)
enum DacCmd_ {
CMD_WAVE_DC = 0,
CMD_WAVE_SINE = 1,
CMD_WAVE_TRIANGLE = 2,
CMD_WAVE_SAWTOOTH_UP = 3,
CMD_WAVE_SAWTOOTH_DOWN = 4,
CMD_WAVE_RECTANGLE = 5,
CMD_SYNC = 10,
CMD_SET_FREQUENCY = 20,
CMD_SET_PHASE = 21,
CMD_SET_DITHER = 22,
};
/** Handle a request message */
static error_t UDAC_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
{
struct priv *priv = unit->data;
// Exceptions that aren't per-channel
switch (command) {
case CMD_SYNC:
dbg("Sync");
priv->ch[0].counter = priv->ch[0].phase << UDAC_INDEX_SHIFT;
priv->ch[1].counter = priv->ch[1].phase << UDAC_INDEX_SHIFT;
return E_SUCCESS;
}
uint8_t channels = pp_u8(pp);
bool want_reinit = false;
bool want_tog_timer = false;
// TODO move this stuff to the api file
for (int i = 0; i < 2; i++) {
if (channels & (1<<i)) {
switch (command) {
case CMD_SET_FREQUENCY:;
float freq = pp_float(pp);
TRY(UDAC_SetFreq(unit, i, freq));
break;
case CMD_WAVE_DC:
priv->ch[i].dc_level = pp_u16(pp);
priv->ch[i].waveform = UDAC_WAVE_DC;
want_tog_timer = true;
break;
case CMD_WAVE_SINE:
priv->ch[i].waveform = UDAC_WAVE_SINE;
want_tog_timer = true;
break;
case CMD_WAVE_TRIANGLE:
priv->ch[i].waveform = UDAC_WAVE_TRIANGLE;
want_tog_timer = true;
break;
case CMD_WAVE_SAWTOOTH_UP:
priv->ch[i].waveform = UDAC_WAVE_SAWTOOTH_UP;
want_tog_timer = true;
break;
case CMD_WAVE_SAWTOOTH_DOWN:
priv->ch[i].waveform = UDAC_WAVE_SAWTOOTH_DOWN;
want_tog_timer = true;
break;
case CMD_WAVE_RECTANGLE:;
uint16_t ontime = pp_u16(pp);
uint16_t high = pp_u16(pp);
uint16_t low = pp_u16(pp);
// use 0xFFFF to skip setting the value
if (high < 4096) priv->ch[i].rectangle_high = high;
if (low < 4096) priv->ch[i].rectangle_low = low;
if (ontime <= UDAC_VALUE_COUNT) priv->ch[i].rectangle_ontime = ontime;
// dbg("Set rect hi %d, low %d", (int)priv->ch[i].rectangle_high, (int)priv->ch[i].rectangle_low);
priv->ch[i].waveform = UDAC_WAVE_RECTANGLE;
want_tog_timer = true;
break;
case CMD_SET_PHASE:;
uint16_t ph = pp_u16(pp);
uint32_t newphase = ph << UDAC_INDEX_SHIFT;
uint32_t oldphase = priv->ch[i].phase << UDAC_INDEX_SHIFT;
int32_t diff = newphase - oldphase;
priv->ch[i].counter += diff;
priv->ch[i].phase = ph;
break;
case CMD_SET_DITHER:;
uint8_t noisetype = pp_u8(pp); // 0-none, 1-random, 2-triangle
uint8_t noisebits = pp_u8(pp);
// type 0xFF = not set
if (noisetype <= 2) {
priv->ch[i].noise_type = (enum UDAC_Noise) noisetype;
}
// bits 0xFF = not set
if (noisebits >= 1 && noisebits <= 12) {
priv->ch[i].noise_level = (uint8_t) (noisebits - 1);
}
// dbg("Ch %d: Dither type %d, level %d", i,
// (int)priv->ch[i].noise_type,
// (int)priv->ch[i].noise_level);
want_reinit = true;
break;
default:
return E_UNKNOWN_COMMAND;
}
}
}
if (want_reinit) {
UDAC_Reconfigure(unit);
}
if (want_tog_timer) {
UDAC_ToggleTimerIfNeeded(unit);
}
return E_SUCCESS;
}
// ------------------------------------------------------------------------
/** Unit template */
const UnitDriver UNIT_DAC = {
.name = "DAC",
.description = "Two-channel analog output with waveforms",
// Settings
.preInit = UDAC_preInit,
.cfgLoadBinary = UDAC_loadBinary,
.cfgWriteBinary = UDAC_writeBinary,
.cfgLoadIni = UDAC_loadIni,
.cfgWriteIni = UDAC_writeIni,
// Init
.init = UDAC_init,
.deInit = UDAC_deInit,
// Function
.handleRequest = UDAC_handleRequest,
};
-16
View File
@@ -1,16 +0,0 @@
//
// Created by MightyPork on 2017/11/25.
//
// Digital input unit; single or multiple pin read access on one port (A-F)
//
#ifndef U_DAC_H
#define U_DAC_H
#include "unit.h"
extern const UnitDriver UNIT_DAC;
// UU_ prototypes
#endif //U_DAC_H
-100
View File
@@ -7,20 +7,8 @@
#include "unit_dout.h"
#define DOUT_INTERNAL
#include "_dout_internal.h"
static void clear_pulse_by_mask(struct priv *priv, uint16_t spread)
{
assert_param(priv);
for (int i = 0; i < 16; i++) {
if (spread & (1 << i)) {
priv->msec_pulse_cnt[i] = 0;
}
}
}
error_t UU_DOut_Write(Unit *unit, uint16_t packed)
{
CHECK_TYPE(unit, &UNIT_DOUT);
@@ -28,7 +16,6 @@ error_t UU_DOut_Write(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
uint16_t set = spread;
uint16_t reset = ((~spread) & mask);
@@ -43,7 +30,6 @@ error_t UU_DOut_Set(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
priv->port->BSRR = spread;
return E_SUCCESS;
@@ -56,7 +42,6 @@ error_t UU_DOut_Clear(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
priv->port->BSRR = (spread<<16);
return E_SUCCESS;
@@ -69,7 +54,6 @@ error_t UU_DOut_Toggle(Unit *unit, uint16_t packed)
struct priv *priv = unit->data;
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
uint16_t flipped = (uint16_t) (~priv->port->ODR) & mask;
uint16_t set = flipped & spread;
@@ -87,87 +71,3 @@ error_t UU_DOut_GetPinCount(Unit *unit, uint8_t *count)
*count = (uint8_t)(32 - __CLZ(packed));
return E_SUCCESS;
}
error_t UU_DOut_Pulse(Unit *unit, uint16_t packed, bool polarity, bool is_usec, uint16_t count)
{
CHECK_TYPE(unit, &UNIT_DOUT);
struct priv *priv = unit->data;
assert_param(priv);
uint16_t mask = priv->pins;
uint16_t spread = pinmask_spread(packed, mask);
clear_pulse_by_mask(priv, spread);
vPortEnterCritical();
if (is_usec) {
// we're gonna do this right here as a delay loop.
if (count >= 1000) {
// too long, fall back to msec
count /= 1000;
is_usec = false;
}
else {
const uint32_t bsrr1 = spread << (polarity ? 0 : 16);
const uint32_t bsrr0 = spread << (polarity ? 16 : 0);
const uint32_t start = PTIM_MicroDelayAlign();
priv->port->BSRR = bsrr1;
PTIM_MicroDelayAligned(count, start);
priv->port->BSRR = bsrr0;
}
}
if (!is_usec) {
// Load the counters
for (int i = 0; i < 16; i++) {
if (spread & (1 << i)) {
priv->msec_pulse_cnt[i] = (uint16_t) (count + 1);
}
}
if (polarity) {
priv->msec_pulse_scheduled_1 |= spread;
} else {
priv->msec_pulse_scheduled_0 |= spread;
}
unit->_tick_cnt = 0;
unit->tick_interval = 1;
}
vPortExitCritical();
return E_SUCCESS;
}
void DOut_Tick(Unit *unit)
{
struct priv *priv = unit->data;
uint16_t odr = (uint16_t) priv->port->ODR;
int live_cnt = 0;
for (int i = 0; i < 16; i++) {
if (priv->msec_pulse_scheduled_1 & (1<<i)) {
odr |= (1<<i);
} else if (priv->msec_pulse_scheduled_0 & (1<<i)) {
odr &= ~(1<<i);
}
if (priv->msec_pulse_cnt[i] > 0) {
live_cnt++;
priv->msec_pulse_cnt[i]--;
if (priv->msec_pulse_cnt[i] == 0) {
odr ^= 1 << i;
}
}
}
priv->port->ODR = odr;
priv->msec_pulse_scheduled_1 = 0;
priv->msec_pulse_scheduled_0 = 0;
if (live_cnt == 0) {
unit->_tick_cnt = 0;
unit->tick_interval = 0;
}
}
-5
View File
@@ -19,9 +19,6 @@ struct priv {
uint16_t open_drain; // open drain pins
GPIO_TypeDef *port;
uint16_t msec_pulse_cnt[16];
uint16_t msec_pulse_scheduled_1;
uint16_t msec_pulse_scheduled_0;
};
/** Allocate data structure and set defaults */
@@ -49,6 +46,4 @@ error_t DOut_init(Unit *unit);
/** Tear down the unit */
void DOut_deInit(Unit *unit);
void DOut_Tick(Unit *unit);
#endif //GEX_F072_DOUT_INTERNAL_H
+2 -10
View File
@@ -9,11 +9,10 @@
#include "_dout_internal.h"
enum PinCmd_ {
CMD_QUERY = 0,
CMD_TEST = 0,
CMD_SET = 1,
CMD_CLEAR = 2,
CMD_TOGGLE = 3,
CMD_PULSE = 4,
};
/** Handle a request message */
@@ -22,7 +21,7 @@ static error_t DOut_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
uint16_t packed = pp_u16(pp);
switch (command) {
case CMD_QUERY:
case CMD_TEST:
return UU_DOut_Write(unit, packed);
case CMD_SET:
@@ -34,12 +33,6 @@ static error_t DOut_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
case CMD_TOGGLE:
return UU_DOut_Toggle(unit, packed);
case CMD_PULSE:;
bool polarity = pp_bool(pp);
bool is_usec = pp_bool(pp);
uint16_t count = pp_u16(pp);
return UU_DOut_Pulse(unit, packed, polarity, is_usec, count);
default:
return E_UNKNOWN_COMMAND;
}
@@ -62,5 +55,4 @@ const UnitDriver UNIT_DOUT = {
.deInit = DOut_deInit,
// Function
.handleRequest = DOut_handleRequest,
.updateTick = DOut_Tick,
};
-12
View File
@@ -56,16 +56,4 @@ error_t UU_DOut_Toggle(Unit *unit, uint16_t packed);
*/
error_t UU_DOut_GetPinCount(Unit *unit, uint8_t *count);
/**
* Send a pulse
*
* @param unit
* @param packed - pins to pulse
* @param polarity - pulse active level
* @param is_usec - use usec precision (for < 1 ms)
* @param count - number of units (msec or usec)
* @return success
*/
error_t UU_DOut_Pulse(Unit *unit, uint16_t packed, bool polarity, bool is_usec, uint16_t count);
#endif //U_DOUT_H
+1
View File
@@ -2,6 +2,7 @@
// Created by MightyPork on 2018/02/20.
//
#include <stm32f072xb.h>
#include "platform.h"
#define FCAP_INTERNAL
+1 -1
View File
@@ -62,7 +62,7 @@ error_t UI2C_init(Unit *unit)
uint32_t af_i2c;
uint32_t timing; // magic constant from CubeMX
#if STM32F072xB
#if GEX_PLAT_F072_DISCOVERY
// scl - 6 or 8 for I2C1, 10 for I2C2
// sda - 7 or 9 for I2C1, 11 for I2C2
if (priv->periph_num == 1) {
+1 -1
View File
@@ -77,7 +77,7 @@ void UI2C_writeIni(Unit *unit, IniWriter *iw)
iw_entry_d(iw, "device", priv->periph_num);
iw_comment(iw, "Pin mappings (SCL,SDA)");
#if STM32F072xB
#if GEX_PLAT_F072_DISCOVERY
iw_comment(iw, " I2C1: (0) B6,B7 (1) B8,B9");
iw_comment(iw, " I2C2: (0) B10,B11 (1) B13,B14");
#elif GEX_PLAT_F103_BLUEPILL
+2 -2
View File
@@ -12,7 +12,7 @@
#include "_i2c_internal.h"
enum PinCmd_ {
CMD_QUERY = 0,
CMD_TEST = 0,
CMD_READ = 1,
CMD_WRITE_REG = 2,
CMD_READ_REG = 3,
@@ -30,7 +30,7 @@ static error_t UI2C_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
switch (command) {
/** Write byte(s) - addr:u16, byte(s) */
case CMD_QUERY:
case CMD_TEST:
addr = pp_u16(pp);
const uint8_t *bb = pp_tail(pp, &len);
+2 -2
View File
@@ -12,7 +12,7 @@
// ------------------------------------------------------------------------
enum SipoCmd_ {
CMD_QUERY = 0,
CMD_WRITE = 0,
CMD_DIRECT_DATA = 1,
CMD_DIRECT_SHIFT = 2,
CMD_DIRECT_CLEAR = 3,
@@ -23,7 +23,7 @@ enum SipoCmd_ {
static error_t USIPO_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, PayloadParser *pp)
{
switch (command) {
case CMD_QUERY:
case CMD_WRITE:
{
uint32_t len;
uint16_t terminal_packed = pp_u16(pp);
+17 -17
View File
@@ -63,7 +63,7 @@ error_t USPI_init(Unit *unit)
uint32_t af_spi;
// TODO
#if STM32F072xB
#if GEX_PLAT_F072_DISCOVERY
// SPI1 - many options
// sck, miso, mosi, af
@@ -83,14 +83,14 @@ error_t USPI_init(Unit *unit)
pin_miso = 4;
pin_mosi = 5;
}
// else if (priv->remap == 2) {
// // large packages only
// spi_portname = 'E';
// af_spi = LL_GPIO_AF_1;
// pin_sck = 13;
// pin_miso = 14;
// pin_mosi = 15;
// }
else if (priv->remap == 2) {
// large packages only
spi_portname = 'E';
af_spi = LL_GPIO_AF_1;
pin_sck = 13;
pin_miso = 14;
pin_mosi = 15;
}
else {
return E_BAD_CONFIG;
}
@@ -104,14 +104,14 @@ error_t USPI_init(Unit *unit)
pin_miso = 14;
pin_mosi = 15;
}
// else if (priv->remap == 1) {
// // NOTE: there's also an incomplete remap in PB and PC
// spi_portname = 'D';
// af_spi = LL_GPIO_AF_0;
// pin_sck = 1;
// pin_miso = 3;
// pin_mosi = 4;
// }
else if (priv->remap == 1) {
// NOTE: the's also a incomplete remap in PB and PC
spi_portname = 'D';
af_spi = LL_GPIO_AF_0;
pin_sck = 1;
pin_miso = 3;
pin_mosi = 4;
}
else {
return E_BAD_CONFIG;
}
+3 -3
View File
@@ -102,9 +102,9 @@ void USPI_writeIni(Unit *unit, IniWriter *iw)
// TODO show a legend for peripherals and remaps
iw_comment(iw, "Pin mappings (SCK,MISO,MOSI)");
#if STM32F072xB
iw_comment(iw, " SPI1: (0) A5,A6,A7 (1) B3,B4,B5"); // (2) E13,E14,E15
iw_comment(iw, " SPI2: (0) B13,B14,B15"); // (1) D1,D3,D4
#if GEX_PLAT_F072_DISCOVERY
iw_comment(iw, " SPI1: (0) A5,A6,A7 (1) B3,B4,B5 (2) E13,E14,E15");
iw_comment(iw, " SPI2: (0) B13,B14,B15 (1) D1,D3,D4");
#elif GEX_PLAT_F103_BLUEPILL
#error "NO IMPL"
#elif GEX_PLAT_F303_DISCOVERY
+2 -2
View File
@@ -15,7 +15,7 @@
// SPI master
enum PinCmd_ {
CMD_QUERY = 0,
CMD_TEST = 0,
CMD_MULTICAST = 1,
};
@@ -33,7 +33,7 @@ static error_t USPI_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command, P
switch (command) {
/** Write and read byte(s) - slave_num:u8, req_len:u16, resp_skip:u16, resp_len:u16, byte(s) */
case CMD_QUERY:
case CMD_TEST:
slave = pp_u8(pp);
resp_skip = pp_u16(pp);
resp_len = pp_u16(pp);
+1 -1
View File
@@ -111,7 +111,7 @@ static inline error_t UUSART_configPins(Unit *unit)
want_rts_pin(priv)
};
#if STM32F072xB
#if GEX_PLAT_F072_DISCOVERY
const struct PinAF *mappings = NULL;
+1 -1
View File
@@ -159,7 +159,7 @@ void UUSART_writeIni(Unit *unit, IniWriter *iw)
iw_entry_d(iw, "device", priv->periph_num);
iw_comment(iw, "Pin mappings (TX,RX,CK,CTS,RTS/DE)");
#if STM32F072xB
#if GEX_PLAT_F072_DISCOVERY
iw_comment(iw, " USART1: (0) A9,A10,A8,A11,A12 (1) B6,B7,A8,A11,A12");
iw_comment(iw, " USART2: (0) A2,A3,A4,A0,A1 (1) A14,A15,A4,A0,A1");
iw_comment(iw, " USART3: (0) B10,B11,B12,B13,B14");
+2 -2
View File
@@ -92,7 +92,7 @@ void UUSART_Tick(Unit *unit)
}
enum PinCmd_ {
CMD_QUERY = 0,
CMD_WRITE = 0,
CMD_WRITE_SYNC = 1,
};
@@ -103,7 +103,7 @@ static error_t UUSART_handleRequest(Unit *unit, TF_ID frame_id, uint8_t command,
const uint8_t *pld;
switch (command) {
/** Write bytes to the USART. Payload consists of the data to send. Waits for completion. */
case CMD_QUERY:
case CMD_WRITE:
pld = pp_tail(pp, &len);
TRY(UU_USART_Write(unit, pld, len));
return E_SUCCESS;