fix spdif for s3 and remove one override

SPDIF on esp32 was partly incorrect due to word ordering and required i2s_hal override. This is not needed anymore as the "mistery" of SPDIF hack has been properly sorted out
This commit is contained in:
philippe44
2023-08-30 22:00:05 -07:00
parent e9ccd8eef7
commit 55053d5941
4 changed files with 35 additions and 296 deletions

View File

@@ -1,6 +1,6 @@
if(IDF_TARGET STREQUAL esp32 AND IDF_VERSION_MAJOR EQUAL 4 AND IDF_VERSION_MINOR LESS 4) if(IDF_TARGET STREQUAL esp32 AND IDF_VERSION_MAJOR EQUAL 4 AND IDF_VERSION_MINOR LESS 4)
set(lib_dir ${build_dir}/esp-idf) set(lib_dir ${build_dir}/esp-idf)
set(driver esp32/i2s.c esp32/i2s_hal.c) set(driver esp32/i2s.c)
string(REPLACE ".c" ".c.obj" driver_obj "${driver}") string(REPLACE ".c" ".c.obj" driver_obj "${driver}")
idf_component_register( SRCS ${driver} idf_component_register( SRCS ${driver}
@@ -20,5 +20,5 @@ if(IDF_TARGET STREQUAL esp32 AND IDF_VERSION_MAJOR EQUAL 4 AND IDF_VERSION_MINOR
VERBATIM VERBATIM
) )
else() else()
message(STATUS "==> NO I2S LIBRARY OVERRIDE, SPDIF MIGHT NOT WORK <==") message(STATUS "==> NO OVERRIDE <==")
endif() endif()

View File

@@ -1,275 +0,0 @@
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// The HAL layer for I2S (common part)
#include "soc/soc.h"
#include "soc/soc_caps.h"
#include "hal/i2s_hal.h"
#define I2S_TX_PDM_FP_DEF 960 // Set to the recommended value(960) in TRM
#define I2S_RX_PDM_DSR_DEF 0
void i2s_hal_set_tx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits)
{
if (bits <= I2S_BITS_PER_SAMPLE_16BIT) {
i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
} else {
i2s_ll_set_tx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3);
}
i2s_ll_set_tx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
#if SOC_I2S_SUPPORTS_DMA_EQUAL
i2s_ll_set_tx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
#endif
}
void i2s_hal_set_rx_mode(i2s_hal_context_t *hal, i2s_channel_t ch, i2s_bits_per_sample_t bits)
{
if (bits <= I2S_BITS_PER_SAMPLE_16BIT) {
i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
} else {
i2s_ll_set_rx_fifo_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 2 : 3);
}
i2s_ll_set_rx_chan_mod(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
#if SOC_I2S_SUPPORTS_DMA_EQUAL
i2s_ll_set_rx_dma_equal(hal->dev, (ch == I2S_CHANNEL_STEREO) ? 0 : 1);
#endif
}
void i2s_hal_set_in_link(i2s_hal_context_t *hal, uint32_t bytes_num, uint32_t addr)
{
i2s_ll_set_in_link_addr(hal->dev, addr);
i2s_ll_set_rx_eof_num(hal->dev, bytes_num);
}
#if SOC_I2S_SUPPORTS_PDM
void i2s_hal_tx_pdm_cfg(i2s_hal_context_t *hal, uint32_t fp, uint32_t fs)
{
i2s_ll_tx_pdm_cfg(hal->dev, fp, fs);
}
void i2s_hal_get_tx_pdm(i2s_hal_context_t *hal, uint32_t *fp, uint32_t *fs)
{
i2s_ll_get_tx_pdm(hal->dev, fp, fs);
}
void i2s_hal_rx_pdm_cfg(i2s_hal_context_t *hal, uint32_t dsr)
{
i2s_ll_rx_pdm_cfg(hal->dev, dsr);
}
void i2s_hal_get_rx_pdm(i2s_hal_context_t *hal, uint32_t *dsr)
{
i2s_ll_get_rx_pdm(hal->dev, dsr);
}
#endif
void i2s_hal_set_clk_div(i2s_hal_context_t *hal, int div_num, int div_a, int div_b, int tx_bck_div, int rx_bck_div)
{
i2s_ll_set_clkm_div_num(hal->dev, div_num);
i2s_ll_set_clkm_div_a(hal->dev, div_a);
i2s_ll_set_clkm_div_b(hal->dev, div_b);
i2s_ll_set_tx_bck_div_num(hal->dev, tx_bck_div);
i2s_ll_set_rx_bck_div_num(hal->dev, rx_bck_div);
}
void i2s_hal_set_tx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits)
{
i2s_ll_set_tx_bits_mod(hal->dev, bits);
}
void i2s_hal_set_rx_bits_mod(i2s_hal_context_t *hal, i2s_bits_per_sample_t bits)
{
i2s_ll_set_rx_bits_mod(hal->dev, bits);
}
void i2s_hal_reset(i2s_hal_context_t *hal)
{
// Reset I2S TX/RX module first, and then, reset DMA and FIFO.
i2s_ll_reset_tx(hal->dev);
i2s_ll_reset_rx(hal->dev);
i2s_ll_reset_dma_in(hal->dev);
i2s_ll_reset_dma_out(hal->dev);
i2s_ll_reset_rx_fifo(hal->dev);
i2s_ll_reset_tx_fifo(hal->dev);
}
void i2s_hal_start_tx(i2s_hal_context_t *hal)
{
i2s_ll_start_out_link(hal->dev);
i2s_ll_start_tx(hal->dev);
}
void i2s_hal_start_rx(i2s_hal_context_t *hal)
{
i2s_ll_start_in_link(hal->dev);
i2s_ll_start_rx(hal->dev);
}
void i2s_hal_stop_tx(i2s_hal_context_t *hal)
{
i2s_ll_stop_out_link(hal->dev);
i2s_ll_stop_tx(hal->dev);
}
void i2s_hal_stop_rx(i2s_hal_context_t *hal)
{
i2s_ll_stop_in_link(hal->dev);
i2s_ll_stop_rx(hal->dev);
}
void i2s_hal_format_config(i2s_hal_context_t *hal, const i2s_config_t *i2s_config)
{
switch (i2s_config->communication_format) {
case I2S_COMM_FORMAT_STAND_MSB:
if (i2s_config->mode & I2S_MODE_TX) {
i2s_ll_set_tx_format_msb_align(hal->dev);
}
if (i2s_config->mode & I2S_MODE_RX) {
i2s_ll_set_rx_format_msb_align(hal->dev);
}
break;
case I2S_COMM_FORMAT_STAND_PCM_SHORT:
if (i2s_config->mode & I2S_MODE_TX) {
i2s_ll_set_tx_pcm_long(hal->dev);
}
if (i2s_config->mode & I2S_MODE_RX) {
i2s_ll_set_rx_pcm_long(hal->dev);
}
break;
case I2S_COMM_FORMAT_STAND_PCM_LONG:
if (i2s_config->mode & I2S_MODE_TX) {
i2s_ll_set_tx_pcm_short(hal->dev);
}
if (i2s_config->mode & I2S_MODE_RX) {
i2s_ll_set_rx_pcm_short(hal->dev);
}
break;
default: //I2S_COMM_FORMAT_STAND_I2S
if (i2s_config->mode & I2S_MODE_TX) {
i2s_ll_set_tx_format_philip(hal->dev);
}
if (i2s_config->mode & I2S_MODE_RX) {
i2s_ll_set_rx_format_philip(hal->dev);
}
break;
}
}
void i2s_hal_config_param(i2s_hal_context_t *hal, const i2s_config_t *i2s_config)
{
//reset i2s
i2s_ll_reset_tx(hal->dev);
i2s_ll_reset_rx(hal->dev);
//reset dma
i2s_ll_reset_dma_in(hal->dev);
i2s_ll_reset_dma_out(hal->dev);
i2s_ll_enable_dma(hal->dev);
i2s_ll_set_lcd_en(hal->dev, 0);
i2s_ll_set_camera_en(hal->dev, 0);
i2s_ll_set_dscr_en(hal->dev, 0);
i2s_ll_set_tx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left
i2s_ll_set_tx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel
i2s_ll_set_tx_mono(hal->dev, 0);
i2s_ll_set_rx_chan_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? i2s_config->channel_format : (i2s_config->channel_format >> 1)); // 0-two channel;1-right;2-left;3-righ;4-left
i2s_ll_set_rx_fifo_mod(hal->dev, i2s_config->channel_format < I2S_CHANNEL_FMT_ONLY_RIGHT ? 0 : 1); // 0-right&left channel;1-one channel
i2s_ll_set_rx_mono(hal->dev, 0);
i2s_ll_set_dscr_en(hal->dev, 1); //connect dma to fifo
i2s_ll_stop_tx(hal->dev);
i2s_ll_stop_rx(hal->dev);
if (i2s_config->mode & I2S_MODE_TX) {
int order = i2s_config->bits_per_sample == 32 ? 0 : 1;
i2s_ll_set_tx_msb_right(hal->dev, order);
i2s_ll_set_tx_right_first(hal->dev, ~order);
i2s_ll_set_tx_slave_mod(hal->dev, 0); // Master
i2s_ll_set_tx_fifo_mod_force_en(hal->dev, 1);
if (i2s_config->mode & I2S_MODE_SLAVE) {
i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave
}
}
if (i2s_config->mode & I2S_MODE_RX) {
i2s_ll_set_rx_msb_right(hal->dev, 0);
i2s_ll_set_rx_right_first(hal->dev, 0);
i2s_ll_set_rx_slave_mod(hal->dev, 0); // Master
i2s_ll_set_rx_fifo_mod_force_en(hal->dev, 1);
if (i2s_config->mode & I2S_MODE_SLAVE) {
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
}
}
#if SOC_I2S_SUPPORTS_PDM
if (!(i2s_config->mode & I2S_MODE_PDM)) {
i2s_ll_set_rx_pdm_en(hal->dev, 0);
i2s_ll_set_tx_pdm_en(hal->dev, 0);
} else {
if (i2s_config->mode & I2S_MODE_TX) {
i2s_ll_tx_pdm_cfg(hal->dev, I2S_TX_PDM_FP_DEF, i2s_config->sample_rate/100);
}
if(i2s_config->mode & I2S_MODE_RX) {
i2s_ll_rx_pdm_cfg(hal->dev, I2S_RX_PDM_DSR_DEF);
}
// PDM mode have nothing to do with communication format configuration.
return;
}
#endif
#if SOC_I2S_SUPPORTS_ADC_DAC
if (i2s_config->mode & (I2S_MODE_DAC_BUILT_IN | I2S_MODE_ADC_BUILT_IN)) {
if (i2s_config->mode & I2S_MODE_DAC_BUILT_IN) {
i2s_ll_build_in_dac_ena(hal->dev);
}
if (i2s_config->mode & I2S_MODE_ADC_BUILT_IN) {
i2s_ll_build_in_adc_ena(hal->dev);
i2s_ll_set_rx_chan_mod(hal->dev, 1);
i2s_ll_set_rx_fifo_mod(hal->dev, 1);
i2s_ll_set_rx_mono(hal->dev, 0);
}
// Buildin ADC and DAC have nothing to do with communication format configuration.
return;
}
#endif
i2s_hal_format_config(hal, i2s_config);
}
void i2s_hal_enable_master_mode(i2s_hal_context_t *hal)
{
i2s_ll_set_tx_slave_mod(hal->dev, 0); //MASTER Slave
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
}
void i2s_hal_enable_slave_mode(i2s_hal_context_t *hal)
{
i2s_ll_set_tx_slave_mod(hal->dev, 1); //TX Slave
i2s_ll_set_rx_slave_mod(hal->dev, 1); //RX Slave
}
void i2s_hal_init(i2s_hal_context_t *hal, int i2s_num)
{
//Get hardware instance.
hal->dev = I2S_LL_GET_HW(i2s_num);
}

View File

@@ -109,29 +109,36 @@ void equalizer_close(void) {
* change sample rate * change sample rate
*/ */
void equalizer_set_samplerate(uint32_t samplerate) { void equalizer_set_samplerate(uint32_t samplerate) {
#if BYTES_PER_FRAME == 4
if (equalizer.samplerate != samplerate) equalizer_close(); if (equalizer.samplerate != samplerate) equalizer_close();
equalizer.samplerate = samplerate; equalizer.samplerate = samplerate;
equalizer.update = true; equalizer.update = true;
LOG_INFO("equalizer sample rate %u", samplerate); LOG_INFO("equalizer sample rate %u", samplerate);
#else
LOG_INFO("no equalizer with 32 bits samples");
#endif
} }
/**************************************************************************************** /****************************************************************************************
* get volume update and recalculate loudness according to * get volume update and recalculate loudness according to
*/ */
void equalizer_set_volume(unsigned left, unsigned right) { void equalizer_set_volume(unsigned left, unsigned right) {
#if BYTES_PER_FRAME == 4
equalizer.volume = (left + right) / 2; equalizer.volume = (left + right) / 2;
// do classic dB conversion and scale it 0..100 // do classic dB conversion and scale it 0..100
if (equalizer.volume) equalizer.volume = log2(equalizer.volume); if (equalizer.volume) equalizer.volume = log2(equalizer.volume);
equalizer.volume = equalizer.volume / 16.0 * 100.0; equalizer.volume = equalizer.volume / 16.0 * 100.0;
calculate_loudness(); calculate_loudness();
equalizer.update = true; equalizer.update = true;
#endif
} }
/**************************************************************************************** /****************************************************************************************
* change gains from LMS * change gains from LMS
*/ */
void equalizer_set_gain(int8_t *gain) { void equalizer_set_gain(int8_t *gain) {
#if BYTES_PER_FRAME == 4
char config[EQ_BANDS * 4 + 1] = { }; char config[EQ_BANDS * 4 + 1] = { };
int n = 0; int n = 0;
@@ -145,12 +152,16 @@ void equalizer_set_gain(int8_t *gain) {
equalizer.update = true; equalizer.update = true;
LOG_INFO("equalizer gain %s", config); LOG_INFO("equalizer gain %s", config);
#else
LOG_INFO("no equalizer with 32 bits samples");
#endif
} }
/**************************************************************************************** /****************************************************************************************
* change loudness from LMS * change loudness from LMS
*/ */
void equalizer_set_loudness(uint8_t loudness) { void equalizer_set_loudness(uint8_t loudness) {
#if BYTES_PER_FRAME == 4
// update loudness gains as a factor of loudness and volume // update loudness gains as a factor of loudness and volume
equalizer.loudness = loudness / 100.0; equalizer.loudness = loudness / 100.0;
calculate_loudness(); calculate_loudness();
@@ -161,12 +172,16 @@ void equalizer_set_loudness(uint8_t loudness) {
equalizer.update = true; equalizer.update = true;
LOG_INFO("loudness %u", (unsigned) loudness); LOG_INFO("loudness %u", (unsigned) loudness);
#else
LOG_INFO("no equalizer with 32 bits samples");
#endif
} }
/**************************************************************************************** /****************************************************************************************
* process equalizer * process equalizer
*/ */
void equalizer_process(uint8_t *buf, uint32_t bytes) { void equalizer_process(uint8_t *buf, uint32_t bytes) {
#if BYTES_PER_FRAME == 4
// don't want to process with output locked, so take the small risk to miss one parametric update // don't want to process with output locked, so take the small risk to miss one parametric update
if (equalizer.update) { if (equalizer.update) {
equalizer.update = false; equalizer.update = false;
@@ -198,4 +213,5 @@ void equalizer_process(uint8_t *buf, uint32_t bytes) {
if (equalizer.handle) { if (equalizer.handle) {
esp_equalizer_process(equalizer.handle, buf, bytes, equalizer.samplerate, 2); esp_equalizer_process(equalizer.handle, buf, bytes, equalizer.samplerate, 2);
} }
#endif
} }

View File

@@ -583,15 +583,11 @@ static void output_thread_i2s(void *arg) {
i2s_set_sample_rates(CONFIG_I2S_NUM, spdif.enabled ? i2s_config.sample_rate * 2 : i2s_config.sample_rate); i2s_set_sample_rates(CONFIG_I2S_NUM, spdif.enabled ? i2s_config.sample_rate * 2 : i2s_config.sample_rate);
i2s_zero_dma_buffer(CONFIG_I2S_NUM); i2s_zero_dma_buffer(CONFIG_I2S_NUM);
#if BYTES_PER_FRAME == 4
equalizer_set_samplerate(output.current_sample_rate); equalizer_set_samplerate(output.current_sample_rate);
#endif
} }
#if BYTES_PER_FRAME == 4
// run equalizer // run equalizer
equalizer_process(obuf, oframes * BYTES_PER_FRAME); equalizer_process(obuf, oframes * BYTES_PER_FRAME);
#endif
// we assume that here we have been able to entirely fill the DMA buffers // we assume that here we have been able to entirely fill the DMA buffers
if (spdif.enabled) { if (spdif.enabled) {
@@ -709,12 +705,16 @@ static const u16_t spdif_bmclookup[256] = { //biphase mark encoded values (least
/* /*
SPDIF is supposed to be (before BMC encoding, from LSB to MSB) SPDIF is supposed to be (before BMC encoding, from LSB to MSB)
PPPP AAAA SSSS SSSS SSSS SSSS SSSS VUCP 0.... 1... 191.. 0
after BMC encoding, each bits becomes 2 hence this becomes a 64 bits word. The BLFMRF MLFWRF MLFWRF BLFMRF (B,M,W=preamble-4, L/R=left/Right-24, F=Flags-4)
the trick is to start not with a PPPP sequence but with an VUCP sequence to that each xLF pattern is 32 bits
the 16 bits samples are aligned with a BMC word boundary. Note that the LSB of the PPPP AAAA SSSS SSSS SSSS SSSS SSSS VUCP (P=preamble, A=auxiliary, S=sample-20bits, V=valid, U=user data, C=channel status, P=parity)
audio is transmitted first (not the MSB) and that ESP32 libray sends R then L, After BMC encoding, each bit becomes 2 hence this becomes a 64 bits word. The parity
contrary to what seems to be usually done, so (dst) order had to be changed is fixed by changing AAAA bits so that VUPC does not change. Then then trick is to
start not with a PPPP sequence but with an VUCP sequence to that the 16 bits samples
are aligned with a BMC word boundary. Input buffer is left first => LRLR...
The I2S interface must output first the B/M/W preamble which means that second
32 bits words must be first and so must be marked right channel.
*/ */
static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count) { static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, size_t *count) {
register u16_t hi, lo, aux; register u16_t hi, lo, aux;
@@ -729,7 +729,6 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, s
// invert if last preceeding bit is 1 // invert if last preceeding bit is 1
lo ^= ~((s16_t)hi) >> 16; lo ^= ~((s16_t)hi) >> 16;
// first 16 bits // first 16 bits
*dst++ = ((u32_t)lo << 16) | hi;
aux = 0xb333 ^ (((u32_t)((s16_t)lo)) >> 17); aux = 0xb333 ^ (((u32_t)((s16_t)lo)) >> 17);
#else #else
hi = spdif_bmclookup[(u8_t)(*src >> 24)]; hi = spdif_bmclookup[(u8_t)(*src >> 24)];
@@ -738,39 +737,38 @@ static void IRAM_ATTR spdif_convert(ISAMPLE_T *src, size_t frames, u32_t *dst, s
// invert if last preceeding bit is 1 // invert if last preceeding bit is 1
lo ^= ~((s16_t)hi) >> 16; lo ^= ~((s16_t)hi) >> 16;
// first 16 bits // first 16 bits
*dst++ = ((u32_t)lo << 16) | hi;
// we use 20 bits samples as we need to force parity // we use 20 bits samples as we need to force parity
aux = spdif_bmclookup[(u8_t)(*src++ >> 12)]; aux = spdif_bmclookup[(u8_t)(*src++ >> 12)];
aux = (u8_t) (aux ^ (~((s16_t)lo) >> 16)); aux = (u8_t) (aux ^ (~((s16_t)lo) >> 16));
aux |= (0xb3 ^ (((u16_t)((s8_t)aux)) >> 9)) << 8; aux |= (0xb3 ^ (((u16_t)((s8_t)aux)) >> 9)) << 8;
#endif #endif
// VUCP-Bits: Valid, Subcode, Channelstatus, Parity = 0 // set special preamble every 192 iteration
// As parity is always 0, we can use fixed preambles
if (++cnt > 191) { if (++cnt > 191) {
*dst++ = VUCP | (PREAMBLE_B << 16 ) | aux; //special preamble for one of 192 frames *dst++ = VUCP | (PREAMBLE_B << 16 ) | aux; //special preamble for one of 192 frames
cnt = 0; cnt = 0;
} else { } else {
*dst++ = VUCP | (PREAMBLE_M << 16) | aux; *dst++ = VUCP | (PREAMBLE_M << 16) | aux;
} }
// now write sample's 16 low bits
*dst++ = ((u32_t)lo << 16) | hi;
// then do right channel, no need to check PREAMBLE_B // then do right channel, no need to check PREAMBLE_B
#if BYTES_PER_FRAME == 4 #if BYTES_PER_FRAME == 4
hi = spdif_bmclookup[(u8_t)(*src >> 8)]; hi = spdif_bmclookup[(u8_t)(*src >> 8)];
lo = spdif_bmclookup[(u8_t) *src++]; lo = spdif_bmclookup[(u8_t) *src++];
lo ^= ~((s16_t)hi) >> 16; lo ^= ~((s16_t)hi) >> 16;
*dst++ = ((u32_t)lo << 16) | hi;
aux = 0xb333 ^ (((u32_t)((s16_t)lo)) >> 17); aux = 0xb333 ^ (((u32_t)((s16_t)lo)) >> 17);
#else #else
hi = spdif_bmclookup[(u8_t)(*src >> 24)]; hi = spdif_bmclookup[(u8_t)(*src >> 24)];
lo = spdif_bmclookup[(u8_t)(*src >> 16)]; lo = spdif_bmclookup[(u8_t)(*src >> 16)];
lo ^= ~((s16_t)hi) >> 16; lo ^= ~((s16_t)hi) >> 16;
*dst++ = ((u32_t)lo << 16) | hi;
aux = spdif_bmclookup[(u8_t)(*src++ >> 12)]; aux = spdif_bmclookup[(u8_t)(*src++ >> 12)];
aux = (u8_t) (aux ^ (~((s16_t)lo) >> 16)); aux = (u8_t) (aux ^ (~((s16_t)lo) >> 16));
aux |= (0xb3 ^ (((u16_t)((s8_t)aux)) >> 9)) << 8; aux |= (0xb3 ^ (((u16_t)((s8_t)aux)) >> 9)) << 8;
#endif #endif
*dst++ = VUCP | (PREAMBLE_W << 16) | aux; *dst++ = VUCP | (PREAMBLE_W << 16) | aux;
*dst++ = ((u32_t)lo << 16) | hi;
} }
*count = cnt; *count = cnt;