diff --git a/examples/LR11x0/LR11x0_LR_FHSS_Modem/LR11x0_LR_FHSS_Modem.ino b/examples/LR11x0/LR11x0_LR_FHSS_Modem/LR11x0_LR_FHSS_Modem.ino index 118103ab..b858c963 100644 --- a/examples/LR11x0/LR11x0_LR_FHSS_Modem/LR11x0_LR_FHSS_Modem.ino +++ b/examples/LR11x0/LR11x0_LR_FHSS_Modem/LR11x0_LR_FHSS_Modem.ino @@ -2,6 +2,7 @@ RadioLib LR11x0 LR-FHSS Modem Example This example shows how to use LR-FHSS modem in LR11x0 chips. + This modem can only transmit data, and is not able to receive. NOTE: The sketch below is just a guide on how to use LR-FHSS modem, so this code should not be run directly! @@ -68,9 +69,7 @@ void setup() { } void loop() { - // LR-FHSS modem can use the same transmit/receive methods - // as the LoRa modem, even their interrupt-driven versions - + // LR-FHSS modem can only transmit! // transmit LR-FHSS packet int state = radio.transmit("Hello World!"); /* @@ -89,22 +88,4 @@ void loop() { Serial.println(state); } - // receive LR-FHSS packet - String str; - state = radio.receive(str); - /* - byte byteArr[8]; - int state = radio.receive(byteArr, 8); - */ - if (state == RADIOLIB_ERR_NONE) { - Serial.println(F("[LR1110] Received packet!")); - Serial.print(F("[LR1110] Data:\t")); - Serial.println(str); - } else if (state == RADIOLIB_ERR_RX_TIMEOUT) { - Serial.println(F("[LR1110] Timed out while waiting for packet!")); - } else { - Serial.print(F("[LR1110] Failed to receive packet, code ")); - Serial.println(state); - } - } diff --git a/src/modules/LR11x0/LR11x0.cpp b/src/modules/LR11x0/LR11x0.cpp index 80a3c008..cbda7ddb 100644 --- a/src/modules/LR11x0/LR11x0.cpp +++ b/src/modules/LR11x0/LR11x0.cpp @@ -216,11 +216,8 @@ int16_t LR11x0::receive(uint8_t* data, size_t len) { timeout = (RadioLibTime_t)(((maxLen * 8.0) / brBps) * 1000.0 * 5.0); } else if(modem == RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS) { - size_t maxLen = len; - if(len == 0) { - maxLen = 0xFF; - } - timeout = (RadioLibTime_t)(((maxLen * 8.0) / (RADIOLIB_LR11X0_LR_FHSS_BIT_RATE)) * 1000.0 * 5.0); + // this modem cannot receive + return(RADIOLIB_ERR_WRONG_MODEM); } else { return(RADIOLIB_ERR_UNKNOWN); @@ -288,7 +285,7 @@ int16_t LR11x0::receiveDirect() { } int16_t LR11x0::scanChannel() { - ChannelScanConfig_t config = { + ChannelScanConfig_t cfg = { .cad = { .symNum = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, .detPeak = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, @@ -299,7 +296,7 @@ int16_t LR11x0::scanChannel() { .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK, }, }; - return(this->scanChannel(config)); + return(this->scanChannel(cfg)); } int16_t LR11x0::scanChannel(const ChannelScanConfig_t &config) { @@ -472,8 +469,7 @@ int16_t LR11x0::startReceive(uint32_t timeout, uint32_t irqFlags, uint32_t irqMa state = getPacketType(&modem); RADIOLIB_ASSERT(state); if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) && - (modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK) && - (modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS)) { + (modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) { return(RADIOLIB_ERR_WRONG_MODEM); } @@ -521,8 +517,7 @@ int16_t LR11x0::readData(uint8_t* data, size_t len) { state = getPacketType(&modem); RADIOLIB_ASSERT(state); if((modem != RADIOLIB_LR11X0_PACKET_TYPE_LORA) && - (modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK) && - (modem != RADIOLIB_LR11X0_PACKET_TYPE_LR_FHSS)) { + (modem != RADIOLIB_LR11X0_PACKET_TYPE_GFSK)) { return(RADIOLIB_ERR_WRONG_MODEM); } @@ -561,7 +556,7 @@ int16_t LR11x0::readData(uint8_t* data, size_t len) { } int16_t LR11x0::startChannelScan() { - ChannelScanConfig_t config = { + ChannelScanConfig_t cfg = { .cad = { .symNum = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, .detPeak = RADIOLIB_LR11X0_CAD_PARAM_DEFAULT, @@ -572,7 +567,7 @@ int16_t LR11x0::startChannelScan() { .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK, }, }; - return(this->startChannelScan(config)); + return(this->startChannelScan(cfg)); } int16_t LR11x0::startChannelScan(const ChannelScanConfig_t &config) { diff --git a/src/modules/SX126x/SX126x.cpp b/src/modules/SX126x/SX126x.cpp index 09e3e57e..9c46b3b1 100644 --- a/src/modules/SX126x/SX126x.cpp +++ b/src/modules/SX126x/SX126x.cpp @@ -20,35 +20,13 @@ SX126x::SX126x(Module* mod) : PhysicalLayer(RADIOLIB_SX126X_FREQUENCY_STEP_SIZE, } int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) { - // set module properties - this->mod->init(); - this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput); - this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput); - this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16; - this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8; - this->mod->spiConfig.statusPos = 1; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX126X_CMD_READ_REGISTER; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX126X_CMD_WRITE_REGISTER; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX126X_CMD_NOP; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX126X_CMD_GET_STATUS; - this->mod->spiConfig.stream = true; - this->mod->spiConfig.parseStatusCb = SPIparseStatus; - - // try to find the SX126x chip - if(!SX126x::findChip(this->chipType)) { - RADIOLIB_DEBUG_BASIC_PRINTLN("No SX126x found!"); - this->mod->term(); - return(RADIOLIB_ERR_CHIP_NOT_FOUND); - } - RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX126x"); - // BW in kHz and SF are required in order to calculate LDRO for setModulationParams // set the defaults, this will get overwritten later anyway this->bandwidthKhz = 500.0; this->spreadingFactor = 9; // initialize configuration variables (will be overwritten during public settings configuration) - this->bandwidth = RADIOLIB_SX126X_LORA_BW_500_0; // initialized to 500 kHz, since lower valeus will interfere with LLCC68 + this->bandwidth = RADIOLIB_SX126X_LORA_BW_500_0; // initialized to 500 kHz, since lower values will interfere with LLCC68 this->codingRate = RADIOLIB_SX126X_LORA_CR_4_7; this->ldrOptimize = 0x00; this->crcTypeLoRa = RADIOLIB_SX126X_LORA_CRC_ON; @@ -57,22 +35,8 @@ int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, flo this->headerType = RADIOLIB_SX126X_LORA_HEADER_EXPLICIT; this->implicitLen = 0xFF; - // reset the module and verify startup - int16_t state = reset(); - RADIOLIB_ASSERT(state); - - // set mode to standby - state = standby(); - RADIOLIB_ASSERT(state); - - // set TCXO control, if requested - if(!this->XTAL && tcxoVoltage > 0.0) { - state = setTCXO(tcxoVoltage); - RADIOLIB_ASSERT(state); - } - - // configure settings not accessible by API - state = config(RADIOLIB_SX126X_PACKET_TYPE_LORA); + // set module properties and perform initial setup + int16_t state = this->modSetup(tcxoVoltage, useRegulatorLDO, RADIOLIB_SX126X_PACKET_TYPE_LORA); RADIOLIB_ASSERT(state); // configure publicly accessible settings @@ -85,13 +49,6 @@ int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, flo state = setPreambleLength(preambleLength); RADIOLIB_ASSERT(state); - if (useRegulatorLDO) { - state = setRegulatorLDO(); - } else { - state = setRegulatorDCDC(); - } - RADIOLIB_ASSERT(state); - // set publicly accessible settings that are not a part of begin method state = setCurrentLimit(60.0); RADIOLIB_ASSERT(state); @@ -109,54 +66,18 @@ int16_t SX126x::begin(uint8_t cr, uint8_t syncWord, uint16_t preambleLength, flo } int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, uint16_t preambleLength, float tcxoVoltage, bool useRegulatorLDO) { - // set module properties - this->mod->init(); - this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput); - this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput); - this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16; - this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8; - this->mod->spiConfig.statusPos = 1; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX126X_CMD_READ_REGISTER; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX126X_CMD_WRITE_REGISTER; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX126X_CMD_NOP; - this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX126X_CMD_GET_STATUS; - this->mod->spiConfig.stream = true; - this->mod->spiConfig.parseStatusCb = SPIparseStatus; - - // try to find the SX126x chip - if(!SX126x::findChip(this->chipType)) { - RADIOLIB_DEBUG_BASIC_PRINTLN("No SX126x found!"); - this->mod->term(); - return(RADIOLIB_ERR_CHIP_NOT_FOUND); - } - RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX126x"); - // initialize configuration variables (will be overwritten during public settings configuration) this->bitRate = 21333; // 48.0 kbps this->frequencyDev = 52428; // 50.0 kHz this->rxBandwidth = RADIOLIB_SX126X_GFSK_RX_BW_156_2; this->rxBandwidthKhz = 156.2; this->pulseShape = RADIOLIB_SX126X_GFSK_FILTER_GAUSS_0_5; - this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV; // CCIT CRC configuration + this->crcTypeFSK = RADIOLIB_SX126X_GFSK_CRC_2_BYTE_INV; // CCITT CRC configuration this->preambleLengthFSK = preambleLength; this->addrComp = RADIOLIB_SX126X_GFSK_ADDRESS_FILT_OFF; - // reset the module and verify startup - int16_t state = reset(); - RADIOLIB_ASSERT(state); - - // set mode to standby - state = standby(); - RADIOLIB_ASSERT(state); - - // set TCXO control, if requested - if(!this->XTAL && tcxoVoltage > 0.0) { - state = setTCXO(tcxoVoltage); - RADIOLIB_ASSERT(state); - } - - // configure settings not accessible by API - state = config(RADIOLIB_SX126X_PACKET_TYPE_GFSK); + // set module properties and perform initial setup + int16_t state = this->modSetup(tcxoVoltage, useRegulatorLDO, RADIOLIB_SX126X_PACKET_TYPE_GFSK); RADIOLIB_ASSERT(state); // configure publicly accessible settings @@ -175,13 +96,6 @@ int16_t SX126x::beginFSK(float br, float freqDev, float rxBw, uint16_t preambleL state = setPreambleLength(preambleLength); RADIOLIB_ASSERT(state); - if(useRegulatorLDO) { - state = setRegulatorLDO(); - } else { - state = setRegulatorDCDC(); - } - RADIOLIB_ASSERT(state); - // set publicly accessible settings that are not a part of begin method uint8_t sync[] = {0x12, 0xAD}; state = setSyncWord(sync, 2); @@ -435,7 +349,7 @@ int16_t SX126x::packetMode() { } int16_t SX126x::scanChannel() { - ChannelScanConfig_t config = { + ChannelScanConfig_t cfg = { .cad = { .symNum = RADIOLIB_SX126X_CAD_PARAM_DEFAULT, .detPeak = RADIOLIB_SX126X_CAD_PARAM_DEFAULT, @@ -446,7 +360,7 @@ int16_t SX126x::scanChannel() { .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK, }, }; - return(this->scanChannel(config)); + return(this->scanChannel(cfg)); } int16_t SX126x::scanChannel(const ChannelScanConfig_t &config) { @@ -753,7 +667,7 @@ int16_t SX126x::readData(uint8_t* data, size_t len) { } int16_t SX126x::startChannelScan() { - ChannelScanConfig_t config = { + ChannelScanConfig_t cfg = { .cad = { .symNum = RADIOLIB_SX126X_CAD_PARAM_DEFAULT, .detPeak = RADIOLIB_SX126X_CAD_PARAM_DEFAULT, @@ -764,7 +678,7 @@ int16_t SX126x::startChannelScan() { .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK, }, }; - return(this->startChannelScan(config)); + return(this->startChannelScan(cfg)); } int16_t SX126x::startChannelScan(const ChannelScanConfig_t &config) { @@ -2093,6 +2007,55 @@ Module* SX126x::getMod() { return(this->mod); } +int16_t SX126x::modSetup(float tcxoVoltage, bool useRegulatorLDO, uint8_t modem) { + // set module properties + this->mod->init(); + this->mod->hal->pinMode(this->mod->getIrq(), this->mod->hal->GpioModeInput); + this->mod->hal->pinMode(this->mod->getGpio(), this->mod->hal->GpioModeInput); + this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_ADDR] = Module::BITS_16; + this->mod->spiConfig.widths[RADIOLIB_MODULE_SPI_WIDTH_CMD] = Module::BITS_8; + this->mod->spiConfig.statusPos = 1; + this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_READ] = RADIOLIB_SX126X_CMD_READ_REGISTER; + this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_WRITE] = RADIOLIB_SX126X_CMD_WRITE_REGISTER; + this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_NOP] = RADIOLIB_SX126X_CMD_NOP; + this->mod->spiConfig.cmds[RADIOLIB_MODULE_SPI_COMMAND_STATUS] = RADIOLIB_SX126X_CMD_GET_STATUS; + this->mod->spiConfig.stream = true; + this->mod->spiConfig.parseStatusCb = SPIparseStatus; + + // try to find the SX126x chip + if(!SX126x::findChip(this->chipType)) { + RADIOLIB_DEBUG_BASIC_PRINTLN("No SX126x found!"); + this->mod->term(); + return(RADIOLIB_ERR_CHIP_NOT_FOUND); + } + RADIOLIB_DEBUG_BASIC_PRINTLN("M\tSX126x"); + + // reset the module and verify startup + int16_t state = reset(); + RADIOLIB_ASSERT(state); + + // set mode to standby + state = standby(); + RADIOLIB_ASSERT(state); + + // set TCXO control, if requested + if(!this->XTAL && tcxoVoltage > 0.0) { + state = setTCXO(tcxoVoltage); + RADIOLIB_ASSERT(state); + } + + // configure settings not accessible by API + state = config(modem); + RADIOLIB_ASSERT(state); + + if (useRegulatorLDO) { + state = setRegulatorLDO(); + } else { + state = setRegulatorDCDC(); + } + return(state); +} + int16_t SX126x::config(uint8_t modem) { // reset buffer base address int16_t state = setBufferBaseAddress(); diff --git a/src/modules/SX126x/SX126x.h b/src/modules/SX126x/SX126x.h index 521921da..0c7d17b7 100644 --- a/src/modules/SX126x/SX126x.h +++ b/src/modules/SX126x/SX126x.h @@ -1218,6 +1218,7 @@ class SX126x: public PhysicalLayer { size_t implicitLen = 0; uint8_t invertIQEnabled = RADIOLIB_SX126X_LORA_IQ_STANDARD; + int16_t modSetup(float tcxoVoltage, bool useRegulatorLDO, uint8_t modem); int16_t config(uint8_t modem); bool findChip(const char* verStr); int16_t startReceiveCommon(uint32_t timeout = RADIOLIB_SX126X_RX_TIMEOUT_INF, RadioLibIrqFlags_t irqFlags = RADIOLIB_IRQ_RX_DEFAULT_FLAGS, RadioLibIrqFlags_t irqMask = RADIOLIB_IRQ_RX_DEFAULT_MASK); diff --git a/src/modules/SX128x/SX128x.cpp b/src/modules/SX128x/SX128x.cpp index d8488f1c..a51ad836 100644 --- a/src/modules/SX128x/SX128x.cpp +++ b/src/modules/SX128x/SX128x.cpp @@ -421,7 +421,7 @@ int16_t SX128x::receiveDirect() { } int16_t SX128x::scanChannel() { - ChannelScanConfig_t config = { + ChannelScanConfig_t cfg = { .cad = { .symNum = RADIOLIB_SX128X_CAD_PARAM_DEFAULT, .detPeak = 0, @@ -432,7 +432,7 @@ int16_t SX128x::scanChannel() { .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK, }, }; - return(this->scanChannel(config)); + return(this->scanChannel(cfg)); } int16_t SX128x::scanChannel(const ChannelScanConfig_t &config) { @@ -677,7 +677,7 @@ int16_t SX128x::clearIrqFlags(uint32_t irq) { } int16_t SX128x::startChannelScan() { - ChannelScanConfig_t config = { + ChannelScanConfig_t cfg = { .cad = { .symNum = RADIOLIB_SX128X_CAD_PARAM_DEFAULT, .detPeak = 0, @@ -688,7 +688,7 @@ int16_t SX128x::startChannelScan() { .irqMask = RADIOLIB_IRQ_CAD_DEFAULT_MASK, }, }; - return(this->startChannelScan(config)); + return(this->startChannelScan(cfg)); } int16_t SX128x::startChannelScan(const ChannelScanConfig_t &config) { diff --git a/src/protocols/AX25/AX25.cpp b/src/protocols/AX25/AX25.cpp index c5913e94..82a64ceb 100644 --- a/src/protocols/AX25/AX25.cpp +++ b/src/protocols/AX25/AX25.cpp @@ -402,7 +402,7 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) { uint16_t stuffedFrameBuffPos = stuffedFrameBuffLenBits + 7 - 2*(stuffedFrameBuffLenBits%8); if((frameBuff[i] >> shift) & 0x01) { // copy 1 and increment counter - SET_BIT_IN_ARRAY(stuffedFrameBuff, stuffedFrameBuffPos); + SET_BIT_IN_ARRAY_MSB(stuffedFrameBuff, stuffedFrameBuffPos); stuffedFrameBuffLenBits++; count++; @@ -412,14 +412,14 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) { stuffedFrameBuffPos = stuffedFrameBuffLenBits + 7 - 2*(stuffedFrameBuffLenBits%8); // insert 0 and reset counter - CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, stuffedFrameBuffPos); + CLEAR_BIT_IN_ARRAY_MSB(stuffedFrameBuff, stuffedFrameBuffPos); stuffedFrameBuffLenBits++; count = 0; } } else { // copy 0 and reset counter - CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, stuffedFrameBuffPos); + CLEAR_BIT_IN_ARRAY_MSB(stuffedFrameBuff, stuffedFrameBuffPos); stuffedFrameBuffLenBits++; count = 0; } @@ -454,20 +454,20 @@ int16_t AX25Client::sendFrame(AX25Frame* frame) { for(size_t i = preambleLen + 1; i < stuffedFrameBuffLen*8; i++) { size_t currBitPos = i + 7 - 2*(i%8); size_t prevBitPos = (i - 1) + 7 - 2*((i - 1)%8); - if(TEST_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos)) { + if(TEST_BIT_IN_ARRAY_MSB(stuffedFrameBuff, currBitPos)) { // bit is 1, no change, copy previous bit - if(TEST_BIT_IN_ARRAY(stuffedFrameBuff, prevBitPos)) { - SET_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos); + if(TEST_BIT_IN_ARRAY_MSB(stuffedFrameBuff, prevBitPos)) { + SET_BIT_IN_ARRAY_MSB(stuffedFrameBuff, currBitPos); } else { - CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos); + CLEAR_BIT_IN_ARRAY_MSB(stuffedFrameBuff, currBitPos); } } else { // bit is 0, transition, copy inversion of the previous bit - if(TEST_BIT_IN_ARRAY(stuffedFrameBuff, prevBitPos)) { - CLEAR_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos); + if(TEST_BIT_IN_ARRAY_MSB(stuffedFrameBuff, prevBitPos)) { + CLEAR_BIT_IN_ARRAY_MSB(stuffedFrameBuff, currBitPos); } else { - SET_BIT_IN_ARRAY(stuffedFrameBuff, currBitPos); + SET_BIT_IN_ARRAY_MSB(stuffedFrameBuff, currBitPos); } } } diff --git a/src/utils/FEC.h b/src/utils/FEC.h index a33ff61f..cf201b11 100644 --- a/src/utils/FEC.h +++ b/src/utils/FEC.h @@ -72,10 +72,10 @@ class RadioLibBCH { extern RadioLibBCH RadioLibBCHInstance; // macros to access bits in byte array, from http://www.mathcs.emory.edu/~cheung/Courses/255/Syllabus/1-C-intro/bit-array.html -#define SET_BIT_IN_ARRAY(A, k) ( A[(k/8)] |= (1 << (k%8)) ) -#define CLEAR_BIT_IN_ARRAY(A, k) ( A[(k/8)] &= ~(1 << (k%8)) ) -#define TEST_BIT_IN_ARRAY(A, k) ( A[(k/8)] & (1 << (k%8)) ) -#define GET_BIT_IN_ARRAY(A, k) ( (A[(k/8)] & (1 << (k%8))) ? 1 : 0 ) +#define SET_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] |= (1 << ((k)%8)) ) +#define CLEAR_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] &= ~(1 << ((k)%8)) ) +#define TEST_BIT_IN_ARRAY_MSB(A, k) ( A[((k)/8)] & (1 << ((k)%8)) ) +#define GET_BIT_IN_ARRAY_MSB(A, k) ( (A[((k)/8)] & (1 << ((k)%8))) ? 1 : 0 ) #endif