<commit_before>// -*- Mode: C; c-basic-offset: 8; -*-
//
// Copyright (c) 2011 <NAME>, All Rights Reserved
// Copyright (c) 2011 <NAME>, All Rights Reserved
// Copyright (c) 2013 <NAME>-Stephen, All Rights Reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  o Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  o Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//

// #define DEBUG 1

#include "board.h"
#include "radio.h"
#include "timer.h"
#include "golay.h"
#include "crc.h"

__xdata uint8_t radio_buffer[MAX_PACKET_LENGTH];
__xdata uint8_t radio_buffer_count;

// We need this now because the interleaving golay handling can no longer
// be done in place.
__xdata uint8_t radio_interleave_buffer[MAX_PACKET_LENGTH];
__pdata uint8_t receive_packet_length;
__pdata uint8_t partial_packet_length;

// Collect timing stats for golay decoding
// Interleaved decoding takes about 400x16usec ticks per 3 bytes(!)
// using the naive code.
// By optimising interleave_getbyte() this is now down to 190 ticks per byte.
__xdata uint16_t golay_decode_start_time;
__xdata uint16_t golay_decode_end_time;
__xdata uint8_t golay_decode_time_bytes;

__pdata uint8_t last_rssi;
__pdata uint8_t netid[2];

static volatile __bit packet_received;
static volatile __bit preamble_detected;

__pdata struct radio_settings settings;


// internal helper functions
//
static void	register_write(uint8_t reg, uint8_t value) __reentrant;
static uint8_t	register_read(uint8_t reg);
static bool	software_reset(void);
static void	set_frequency_registers(uint32_t frequency);
static uint32_t scale_uint32(uint32_t value, uint32_t scale);
static void	clear_status_registers(void);

// save and restore radio interrupt. We use this rather than
// __critical to ensure we don't disturb the timer interrupt at all.
// minimal tick drift is critical for TDM
#define EX0_SAVE_DISABLE __bit EX0_saved = EX0; EX0 = 0
#define EX0_RESTORE EX0 = EX0_saved

#define RADIO_RX_INTERRUPTS (EZRADIOPRO_ENRXFFAFULL|EZRADIOPRO_ENPKVALID|EZRADIOPRO_ENCRCERROR)

// FIFO thresholds to allow for packets larger than 64 bytes
#define TX_FIFO_THRESHOLD_LOW 32
#define TX_FIFO_THRESHOLD_HIGH 60
#define RX_FIFO_THRESHOLD_HIGH 50

// return a received packet
//
// returns true on success, false on no packet available
//
bool
radio_receive_packet(uint8_t *length, __xdata uint8_t * __xdata buf)
{
	__xdata uint8_t elen;

	if (!packet_received) {
		return false;
	}

	if (receive_packet_length > MAX_PACKET_LENGTH) {
		radio_receiver_on();
		goto failed;
	}

#if 0
	// useful for testing high packet loss
	if ((timer_entropy() & 0x7) != 0) {
		radio_receiver_on();
		goto failed;		
	}
#endif

	if (!feature_golay) {
		// simple unencoded packets
		// PGS20130409: This seems to indicate that if golay is disabled, so is
		// the netid code.
		*length = receive_packet_length;
		memcpy(buf, radio_buffer, receive_packet_length);
		radio_receiver_on();
		return true;
	}

	golay_decode_start_time=timer2_tick();

	// Previously we decoded in the caller's buffer, so that the next
	// packet could be received while we process this one.
	// However, interleaving the FEC means that we can't decode the buffer in
	// place, because the bits are scrambled all through the packet (which is
	// the point, since burst errors will now be spread over many golay blocks).
	// So we have a special receive buffer for the decoding now.  
	// This also allows us to golay protect the entire packet in one piece,
	// instead of with the headers separate -- which means we can properly
	// protect the headers instead of having all the header bits in the first
	// part of the packet, and thus no better protected than if we had no
	// interleaving.<commit_msg>updated comment about handling of netid when golay encoding is disabled to indicate that hardware headers are used when error correction is disabled.<commit_after>// -*- Mode: C; c-basic-offset: 8; -*-
//
// Copyright (c) 2011 <NAME>, All Rights Reserved
// Copyright (c) 2011 <NAME>, All Rights Reserved
// Copyright (c) 2013 <NAME>-Stephen, All Rights Reserved
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
//  o Redistributions of source code must retain the above copyright
//    notice, this list of conditions and the following disclaimer.
//  o Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in
//    the documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
//

// #define DEBUG 1

#include "board.h"
#include "radio.h"
#include "timer.h"
#include "golay.h"
#include "crc.h"

__xdata uint8_t radio_buffer[MAX_PACKET_LENGTH];
__xdata uint8_t radio_buffer_count;

// We need this now because the interleaving golay handling can no longer
// be done in place.
__xdata uint8_t radio_interleave_buffer[MAX_PACKET_LENGTH];
__pdata uint8_t receive_packet_length;
__pdata uint8_t partial_packet_length;

// Collect timing stats for golay decoding
// Interleaved decoding takes about 400x16usec ticks per 3 bytes(!)
// using the naive code.
// By optimising interleave_getbyte() this is now down to 190 ticks per byte.
__xdata uint16_t golay_decode_start_time;
__xdata uint16_t golay_decode_end_time;
__xdata uint8_t golay_decode_time_bytes;

__pdata uint8_t last_rssi;
__pdata uint8_t netid[2];

static volatile __bit packet_received;
static volatile __bit preamble_detected;

__pdata struct radio_settings settings;


// internal helper functions
//
static void	register_write(uint8_t reg, uint8_t value) __reentrant;
static uint8_t	register_read(uint8_t reg);
static bool	software_reset(void);
static void	set_frequency_registers(uint32_t frequency);
static uint32_t scale_uint32(uint32_t value, uint32_t scale);
static void	clear_status_registers(void);

// save and restore radio interrupt. We use this rather than
// __critical to ensure we don't disturb the timer interrupt at all.
// minimal tick drift is critical for TDM
#define EX0_SAVE_DISABLE __bit EX0_saved = EX0; EX0 = 0
#define EX0_RESTORE EX0 = EX0_saved

#define RADIO_RX_INTERRUPTS (EZRADIOPRO_ENRXFFAFULL|EZRADIOPRO_ENPKVALID|EZRADIOPRO_ENCRCERROR)

// FIFO thresholds to allow for packets larger than 64 bytes
#define TX_FIFO_THRESHOLD_LOW 32
#define TX_FIFO_THRESHOLD_HIGH 60
#define RX_FIFO_THRESHOLD_HIGH 50

// return a received packet
//
// returns true on success, false on no packet available
//
bool
radio_receive_packet(uint8_t *length, __xdata uint8_t * __xdata buf)
{
	__xdata uint8_t elen;

	if (!packet_received) {
		return false;
	}

	if (receive_packet_length > MAX_PACKET_LENGTH) {
		radio_receiver_on();
		goto failed;
	}

#if 0
	// useful for testing high packet loss
	if ((timer_entropy() & 0x7) != 0) {
		radio_receiver_on();
		goto failed;		
	}
#endif

	if (!feature_golay) {
		// simple unencoded packets
		// When golay encoding is disabled, the netid is in the packet headers.
		*length = receive_packet_length;
		memcpy(buf, radio_buffer, receive_packet_length);
		radio_receiver_on();
		return true;
	}

	golay_decode_start_time=timer2_tick();

	// Previously we decoded in the caller's buffer, so that the next
	// packet could be received while we process this one.
	// However, interleaving the FEC means that we can't decode the buffer in
	// place, because the bits are scrambled all through the packet (which is
	// the point, since burst errors will now be spread over many golay blocks).
	// So we have a special receive buffer for the decoding now.  
	// This also allows us to golay protect the entire packet in one piece,
	// instead of with the headers separate -- which means we can properly
	// protect the headers instead of having all the header bits in the first
	// part of the packet, and thus no better protected than if we had no
	// interleaving.
{'fraction_non_alphanumeric': 0.07140677448886176, 'fraction_numerical': 0.015868172108635947, 'mean_word_length': 4.337676438653637, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3587204', 'n_tokens_mistral': 3159, 'n_tokens_neox': 2876, 'n_words': 1222}