From f03e51a23d75275e675b0d71af58b4042c170c69 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 20 May 2019 15:03:01 +0300 Subject: [PATCH] Sync 802.15.4 RF drivers from master repos -Sync STM S2LP with v0.0.6 in master repo -Sync Atmel with v3.0.8 in master repo -Sync MCR20A with v1.0.6 in master repo --- .../source/NanostackRfPhys2lp.cpp | 124 ++++++++++-------- .../source/at24mac_s2lp.cpp | 72 ++++++++++ .../stm-s2lp-rf-driver/source/at24mac_s2lp.h | 71 ++++++++++ .../stm-s2lp-rf-driver/source/s2lpReg.h | 1 + .../stm-s2lp-rf-driver/NanostackRfPhys2lp.h | 53 +++++++- 5 files changed, 261 insertions(+), 60 deletions(-) create mode 100644 components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.cpp create mode 100644 components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.h diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp index ff17c6b775..1d88ba052c 100644 --- a/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/NanostackRfPhys2lp.cpp @@ -79,7 +79,6 @@ extern void (*fhss_bc_switch)(void); #define MAC_TYPE_ACK (2) #define MAC_TYPE_COMMAND (3) #define MAC_DATA_PENDING 0x10 -#define MAC_FRAME_VERSION_2 (2) #define FC_DST_MODE 0x0C #define FC_SRC_MODE 0xC0 #define FC_DST_ADDR_NONE 0x00 @@ -99,8 +98,6 @@ extern void (*fhss_bc_switch)(void); #define CS_SELECT() {rf->CS = 0;} #define CS_RELEASE() {rf->CS = 1;} -extern const uint8_t ADDR_UNSPECIFIED[16]; - typedef enum { RF_MODE_NORMAL = 0, RF_MODE_SNIFFER = 1 @@ -183,6 +180,7 @@ static void rf_backup_timer_stop(void); static void rf_rx_ready_handler(void); static uint32_t read_irq_status(void); static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t *pan_id); +static void rf_cca_timer_start(uint32_t slots); static RFPins *rf; static phy_device_driver_s device_driver; @@ -210,6 +208,7 @@ static uint8_t s2lp_MAC[8]; static rf_mode_e rf_mode = RF_MODE_NORMAL; static bool rf_update_config = false; static uint16_t cur_packet_len = 0xffff; +static uint32_t receiver_ready_timestamp; /* Channel configurations for sub-GHz */ static phy_rf_channel_configuration_s phy_subghz = { @@ -748,16 +747,26 @@ static void rf_start_tx(void) rf_backup_timer_start(MAX_PACKET_SENDING_TIME); } +static int rf_cca_check(void) +{ + uint32_t time_from_receiver_ready = rf_get_timestamp() - receiver_ready_timestamp; + if (time_from_receiver_ready < RSSI_SETTLING_TIME) { + wait_us(RSSI_SETTLING_TIME - time_from_receiver_ready); + } + return (rf_read_register(LINK_QUALIF1) & CARRIER_SENSE); +} + static void rf_cca_timer_interrupt(void) { - if (device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_PREPARE, 0, 0) != 0) { + int8_t status = device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_PREPARE, 0, 0); + if (status == PHY_TX_NOT_ALLOWED) { rf_flush_tx_fifo(); if (rf_state == RF_CSMA_STARTED) { rf_state = RF_IDLE; } return; } - if ((cca_enabled == true) && ((rf_state != RF_CSMA_STARTED && rf_state != RF_IDLE) || (read_irq_status() & (1 << SYNC_WORD)) || (rf_read_register(LINK_QUALIF1) & CARRIER_SENSE))) { + if ((cca_enabled == true) && ((rf_state != RF_CSMA_STARTED && rf_state != RF_IDLE) || (read_irq_status() & (1 << SYNC_WORD)) || rf_cca_check())) { if (rf_state == RF_CSMA_STARTED) { rf_state = RF_IDLE; } @@ -767,9 +776,23 @@ static void rf_cca_timer_interrupt(void) device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_FAIL, 0, 0); } } else { - rf_start_tx(); - rf_state = RF_TX_STARTED; - TEST_TX_STARTED + if (status == PHY_RESTART_CSMA) { + if (device_driver.phy_tx_done_cb) { + device_driver.phy_tx_done_cb(rf_radio_driver_id, mac_tx_handle, PHY_LINK_CCA_OK, 0, 0); + } + if (tx_time) { + uint32_t backoff_time = tx_time - rf_get_timestamp(); + // Max. time to TX can be 65ms, otherwise time has passed already -> send immediately + if (backoff_time > 65000) { + backoff_time = 1; + } + rf_cca_timer_start(backoff_time); + } + } else { + rf_start_tx(); + rf_state = RF_TX_STARTED; + TEST_TX_STARTED + } } } @@ -931,6 +954,8 @@ static void rf_sync_detected_handler(void) rf_state = RF_RX_STARTED; TEST_RX_STARTED rf_disable_interrupt(SYNC_WORD); + rf_enable_interrupt(RX_FIFO_ALMOST_FULL); + rf_enable_interrupt(RX_DATA_READY); rf_backup_timer_start(MAX_PACKET_SENDING_TIME); } @@ -953,15 +978,14 @@ static void rf_receive(uint8_t rx_channel) rf_rx_channel = rf_new_channel = rx_channel; } rf_send_command(S2LP_CMD_RX); - rf_poll_state_change(S2LP_STATE_RX); rf_enable_interrupt(SYNC_WORD); - rf_enable_interrupt(RX_FIFO_ALMOST_FULL); - rf_enable_interrupt(RX_DATA_READY); rf_enable_interrupt(RX_FIFO_UNF_OVF); rx_data_length = 0; if (rf_state != RF_CSMA_STARTED) { rf_state = RF_IDLE; } + rf_poll_state_change(S2LP_STATE_RX); + receiver_ready_timestamp = rf_get_timestamp(); rf_unlock(); } @@ -1158,14 +1182,25 @@ int8_t NanostackRfPhys2lp::rf_register() error("Multiple registrations of NanostackRfPhyAtmel not supported"); return -1; } - if (memcmp(_mac_addr, ADDR_UNSPECIFIED, 8) == 0) { + + if (!_mac_set) { +#ifdef AT24MAC + int ret = _mac.read_eui64((void *)s2lp_MAC); + if (ret < 0) { + rf = NULL; + rf_unlock(); + return -1; + } +#else randLIB_seed_random(); randLIB_get_n_bytes_random(s2lp_MAC, 8); s2lp_MAC[0] |= 2; //Set Local Bit s2lp_MAC[0] &= ~1; //Clear multicast bit - tr_info("Generated random MAC %s", trace_array(s2lp_MAC, 8)); +#endif set_mac_address(s2lp_MAC); + tr_info("MAC address: %s", trace_array(_mac_addr, 8)); } + rf = _rf; int8_t radio_id = rf_device_register(_mac_addr); @@ -1188,12 +1223,20 @@ void NanostackRfPhys2lp::rf_unregister() rf_unlock(); } -NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn, +NanostackRfPhys2lp::NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn #ifdef TEST_GPIOS_ENABLED - PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, + ,PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5 #endif //TEST_GPIOS_ENABLED - PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3) - : _mac_addr(), _rf(NULL), _mac_set(false), + ,PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3 +#ifdef AT24MAC + ,PinName i2c_sda, PinName i2c_scl +#endif //AT24MAC + ) + : +#ifdef AT24MAC + _mac(i2c_sda, i2c_scl), +#endif //AT24MAC + _mac_addr(), _rf(NULL), _mac_set(false), _spi_sdi(spi_sdi), _spi_sdo(spi_sdo), _spi_sclk(spi_sclk), _spi_cs(spi_cs), _spi_sdn(spi_sdn), #ifdef TEST_GPIOS_ENABLED _spi_test1(spi_test1), _spi_test2(spi_test2), _spi_test3(spi_test3), _spi_test4(spi_test4), _spi_test5(spi_test5), @@ -1236,20 +1279,6 @@ static bool rf_panid_filter_common(uint8_t *panid_start, uint8_t *pan_id, uint8_ return retval; } -static bool rf_panid_v2_filter(uint8_t *ptr, uint8_t *pan_id, uint8_t dst_mode, uint8_t src_mode, uint8_t seq_compressed, uint8_t panid_compressed, uint8_t frame_type) -{ - if ((dst_mode == FC_DST_ADDR_NONE) && (frame_type == MAC_TYPE_DATA || frame_type == MAC_TYPE_COMMAND)) { - return true; - } - if ((dst_mode == FC_DST_64_BITS) && (src_mode == FC_SRC_64_BITS) && panid_compressed) { - return true; - } - if (seq_compressed) { - ptr--; - } - return rf_panid_filter_common(ptr, pan_id, frame_type); -} - static bool rf_panid_v1_v0_filter(uint8_t *ptr, uint8_t *pan_id, uint8_t frame_type) { return rf_panid_filter_common(ptr, pan_id, frame_type); @@ -1298,17 +1327,6 @@ static bool rf_addr_filter_common(uint8_t *ptr, uint8_t addr_mode, uint8_t *mac_ return retval; } -static bool rf_addr_v2_filter(uint8_t *ptr, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t dst_mode, uint8_t seq_compressed, uint8_t panid_compressed) -{ - if (seq_compressed) { - ptr--; - } - if (panid_compressed) { - ptr -= 2; - } - return rf_addr_filter_common(ptr, dst_mode, mac_64bit_addr, mac_16bit_addr); -} - static bool rf_addr_v1_v0_filter(uint8_t *ptr, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t dst_mode) { return rf_addr_filter_common(ptr, dst_mode, mac_64bit_addr, mac_16bit_addr); @@ -1317,19 +1335,9 @@ static bool rf_addr_v1_v0_filter(uint8_t *ptr, uint8_t *mac_64bit_addr, uint8_t static bool rf_rx_filter(uint8_t *mac_header, uint8_t *mac_64bit_addr, uint8_t *mac_16bit_addr, uint8_t *pan_id) { uint8_t dst_mode = (mac_header[1] & FC_DST_MODE); - uint8_t src_mode = (mac_header[1] & FC_SRC_MODE); - uint8_t seq_compressed = ((mac_header[1] & FC_SEQUENCE_COMPRESSION) >> SHIFT_SEQ_COMP_FIELD); - uint8_t panid_compressed = ((mac_header[0] & FC_PAN_ID_COMPRESSION) >> SHIFT_PANID_COMP_FIELD); uint8_t frame_type = mac_header[0] & MAC_FRAME_TYPE_MASK; uint8_t version = ((mac_header[1] & VERSION_FIELD_MASK) >> SHIFT_VERSION_FIELD); - if (version == MAC_FRAME_VERSION_2) { - if (!rf_panid_v2_filter(mac_header + OFFSET_DST_PAN_ID, pan_id, dst_mode, src_mode, seq_compressed, panid_compressed, frame_type)) { - return false; - } - if (!rf_addr_v2_filter(mac_header + OFFSET_DST_ADDR, mac_64bit_addr, mac_16bit_addr, dst_mode, seq_compressed, panid_compressed)) { - return false; - } - } else { + if (version != MAC_FRAME_VERSION_2) { if (!rf_panid_v1_v0_filter(mac_header + OFFSET_DST_PAN_ID, pan_id, frame_type)) { return false; } @@ -1474,11 +1482,15 @@ static void rf_print_registers(void) #if MBED_CONF_S2LP_PROVIDE_DEFAULT NanostackRfPhy &NanostackRfPhy::get_default_instance() { - static NanostackRfPhys2lp rf_phy(S2LP_SPI_SDI, S2LP_SPI_SDO, S2LP_SPI_SCLK, S2LP_SPI_CS, S2LP_SPI_SDN, + static NanostackRfPhys2lp rf_phy(S2LP_SPI_SDI, S2LP_SPI_SDO, S2LP_SPI_SCLK, S2LP_SPI_CS, S2LP_SPI_SDN #ifdef TEST_GPIOS_ENABLED - S2LP_SPI_TEST1, S2LP_SPI_TEST2, S2LP_SPI_TEST3, S2LP_SPI_TEST4, S2LP_SPI_TEST5, + ,S2LP_SPI_TEST1, S2LP_SPI_TEST2, S2LP_SPI_TEST3, S2LP_SPI_TEST4, S2LP_SPI_TEST5 #endif //TEST_GPIOS_ENABLED - S2LP_SPI_GPIO0, S2LP_SPI_GPIO1, S2LP_SPI_GPIO2, S2LP_SPI_GPIO3); + ,S2LP_SPI_GPIO0, S2LP_SPI_GPIO1, S2LP_SPI_GPIO2, S2LP_SPI_GPIO3 +#ifdef AT24MAC + ,S2LP_I2C_SDA, S2LP_I2C_SCL +#endif //AT24MAC + ); return rf_phy; } #endif // MBED_CONF_S2LP_PROVIDE_DEFAULT diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.cpp b/components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.cpp new file mode 100644 index 0000000000..046b2b6a7b --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.cpp @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019-2019 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * 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. + */ +#include "NanostackRfPhys2lp.h" +#include "at24mac_s2lp.h" + + +#if DEVICE_I2C +#ifdef AT24MAC + +/* Device addressing */ +#define AT24MAC_EEPROM_ADDRESS (0x0A<<4) +#define AT24MAC_RW_PROTECT_ADDRESS (0x06<<4) +#define AT24MAC_SERIAL_ADDRESS (0x0B<<4) + +/* Known memory blocks */ +#define AT24MAC_SERIAL_OFFSET (0x80) +#define AT24MAC_EUI64_OFFSET (0x98) +#define AT24MAC_EUI48_OFFSET (0x9A) + +#define SERIAL_LEN 16 +#define EUI64_LEN 8 +#define EUI48_LEN 6 + +using namespace mbed; + +AT24Mac_s2lp::AT24Mac_s2lp(PinName sda, PinName scl) : _i2c(sda, scl) +{ + // Do nothing +} + +int AT24Mac_s2lp::read_serial(void *buf) +{ + char offset = AT24MAC_SERIAL_OFFSET; + if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) { + return -1; //No ACK + } + return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char *)buf, SERIAL_LEN); +} + +int AT24Mac_s2lp::read_eui64(void *buf) +{ + char offset = AT24MAC_EUI64_OFFSET; + if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) { + return -1; //No ACK + } + return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char *)buf, EUI64_LEN); +} + +int AT24Mac_s2lp::read_eui48(void *buf) +{ + char offset = AT24MAC_EUI48_OFFSET; + if (_i2c.write(AT24MAC_SERIAL_ADDRESS, &offset, 1, true)) { + return -1; //No ACK + } + return _i2c.read(AT24MAC_SERIAL_ADDRESS, (char *)buf, EUI48_LEN); +} + +#endif /* AT24MAC */ +#endif /* DEVICE_I2C */ diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.h b/components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.h new file mode 100644 index 0000000000..dc31c0f570 --- /dev/null +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/at24mac_s2lp.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2019-2019 ARM Limited. All rights reserved. + * SPDX-License-Identifier: Apache-2.0 + * 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. + */ +#ifndef AT24MAC_S2LP_H +#define AT24MAC_S2LP_H + +#include "PinNames.h" + +#if DEVICE_I2C +#ifdef AT24MAC + +#include "I2C.h" +#include "drivers/DigitalInOut.h" +#include "platform/mbed_wait_api.h" + +/* + * AT24MAC drivers. + * + * This is a EEPROM chip designed to contain factory programmed read-only EUI-64 or EUI-48, + * a 128bit serial number and some user programmable EEPROM. + * + * AT24MAC602 contains EUI-64, use read_eui64() + * AT24MAC402 contains EUI-64, use read_eui48() + * + * NOTE: You cannot use both EUI-64 and EUI-48. Chip contains only one of those. + */ + +class AT24Mac_s2lp { +public: + AT24Mac_s2lp(PinName sda, PinName scl); + + /** + * Read unique serial number from chip. + * \param buf pointer to write serial number to. Must have space for 16 bytes. + * \return zero on success, negative number on failure + */ + int read_serial(void *buf); + + /** + * Read EUI-64 from chip. + * \param buf pointer to write EUI-64 to. Must have space for 8 bytes. + * \return zero on success, negative number on failure + */ + int read_eui64(void *buf); + + /** + * Read EUI-48 from chip. + * \param buf pointer to write EUI-48 to. Must have space for 6 bytes. + * \return zero on success, negative number on failure + */ + int read_eui48(void *buf); + +private: + mbed::I2C _i2c; +}; + +#endif /* AT24MAC */ +#endif /* DEVICE_I2C */ +#endif /* AT24MAC_S2LP_H */ diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h b/components/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h index a924976c52..dfd1c79c84 100644 --- a/components/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/source/s2lpReg.h @@ -25,6 +25,7 @@ extern "C" { #define VERSION 0xC1 #define FIFO_SIZE 128 #define SPI_HEADER_LENGTH 2 +#define RSSI_SETTLING_TIME 250 #define S2LP_GPIO0 0 #define S2LP_GPIO1 1 diff --git a/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h b/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h index 8cdb99a628..66e0701174 100644 --- a/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h +++ b/components/802.15.4_RF/stm-s2lp-rf-driver/stm-s2lp-rf-driver/NanostackRfPhys2lp.h @@ -28,6 +28,42 @@ // Uncomment to use testing gpios attached to TX/RX processes //#define TEST_GPIOS_ENABLED +#if defined(TARGET_MTB_STM_S2LP) +#if !defined(S2LP_SPI_SDI) +#define S2LP_SPI_SDI PA_7 +#endif +#if !defined(S2LP_SPI_SDO) +#define S2LP_SPI_SDO PA_6 +#endif +#if !defined(S2LP_SPI_SCLK) +#define S2LP_SPI_SCLK PA_5 +#endif +#if !defined(S2LP_SPI_CS) +#define S2LP_SPI_CS PC_0 +#endif +#if !defined(S2LP_SPI_SDN) +#define S2LP_SPI_SDN PF_13 +#endif +#if !defined(S2LP_SPI_GPIO0) +#define S2LP_SPI_GPIO0 PA_3 +#endif +#if !defined(S2LP_SPI_GPIO1) +#define S2LP_SPI_GPIO1 PC_3 +#endif +#if !defined(S2LP_SPI_GPIO2) +#define S2LP_SPI_GPIO2 PF_3 +#endif +#if !defined(S2LP_SPI_GPIO3) +#define S2LP_SPI_GPIO3 PF_10 +#endif +#if !defined(S2LP_I2C_SDA) +#define S2LP_I2C_SDA PB_7 +#endif +#if !defined(S2LP_I2C_SCL) +#define S2LP_I2C_SCL PB_6 +#endif +#define AT24MAC +#else #if !defined(S2LP_SPI_SDI) #define S2LP_SPI_SDI D11 #endif @@ -70,17 +106,23 @@ #if !defined(S2LP_SPI_GPIO3) #define S2LP_SPI_GPIO3 A5 #endif +#endif + +#include "at24mac_s2lp.h" class RFPins; class NanostackRfPhys2lp : public NanostackRfPhy { public: - NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, - PinName spi_sclk, PinName spi_cs, PinName spi_sdn, + NanostackRfPhys2lp(PinName spi_sdi, PinName spi_sdo, PinName spi_sclk, PinName spi_cs, PinName spi_sdn #ifdef TEST_GPIOS_ENABLED - PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5, + ,PinName spi_test1, PinName spi_test2, PinName spi_test3, PinName spi_test4, PinName spi_test5 #endif //TEST_GPIOS_ENABLED - PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3); + ,PinName spi_gpio0, PinName spi_gpio1, PinName spi_gpio2, PinName spi_gpio3 +#ifdef AT24MAC + ,PinName i2c_sda, PinName i2c_scl +#endif //AT24MAC + ); virtual ~NanostackRfPhys2lp(); virtual int8_t rf_register(); virtual void rf_unregister(); @@ -88,6 +130,9 @@ public: virtual void set_mac_address(uint8_t *mac); private: +#ifdef AT24MAC + AT24Mac_s2lp _mac; +#endif //AT24MAC uint8_t _mac_addr[8]; RFPins *_rf; bool _mac_set;