add autoacking

This commit is contained in:
Mariano Alvira 2011-02-12 14:01:54 -05:00
parent 9f82e06861
commit 7c7864eae2
7 changed files with 366 additions and 5 deletions

34
doc/autoack Normal file
View file

@ -0,0 +1,34 @@
The known details about autoacking.
1) Auto-acking is disabled if promiscuous mode in enabled. Auto-acking
is enabled when promiscuous mode is disabled. A more proper name
for this bit would be promiscuous/#autoack.
2) If promiscuous mode is disabled and a recieved packet 1) matches
the address filters and 2) has the ack request bit set, then an
auto-ack will be sent (provided you do item 3 properly). The
sequence number is stuffed and transmitted automatically. Note: you
must have the address set properly in the maca hardware. That means
the EUI registers for long addressing and the PANID and short
addr. for short addressing.
3) You must wait 200 maca clocks or so after receiving a packet that
needs an ack. This is necessary for the maca to do it's thing. If
you don't wait enough then it either will not send the ack, or if
you wait a little more (but not enough), the ack DSN will be zero.
4) The following must be set properly, TXACKDELAY, RXACKDELAY,
RXEND. The best way to set these is to use a scope and the TX_ON
and RX_ON signals. You set TXACKDELAY so that the ack is
transmitted 12 symbols after the received packet (192 us). You set
RXACKDELAY to start before the ack is due to arrive (I'm doing
100us before). And you set RXEND to be long enough to receive the
ACK (I'm doing a 700us window or so).
4b) CCA has its own set of timings.
5) The transmitter must set TXSEQNR before MACA_DMATX.
6) The status of the next "action complete" on the TX side tells you
if the ack was received or not. Status will be 0 (success) if you
got the ack and 5 (no_ack) if you did not.

View file

@ -62,6 +62,11 @@ void set_demodulator_type(uint8_t demod);
extern volatile uint8_t fcs_mode; extern volatile uint8_t fcs_mode;
#define set_fcs_mode(x) fcs_mode = (x) #define set_fcs_mode(x) fcs_mode = (x)
/* set_prm_mode(PROMISC) to disable address filtering */
/* set_prm_mode(AUTOACK) to enable address filtering AND autoack */
extern volatile uint8_t prm_mode;
#define set_prm_mode(x) prm_mode = (x)
/* maca packet interface */ /* maca packet interface */
void tx_packet(volatile packet_t *p); void tx_packet(volatile packet_t *p);
volatile packet_t* rx_packet(void); volatile packet_t* rx_packet(void);
@ -105,6 +110,10 @@ enum {
NO_FCS = 1, NO_FCS = 1,
}; };
#define PRM 11 /* set for promiscuous mode */ #define PRM 11 /* set for promiscuous mode */
enum {
AUTOACK = 0,
PROMISC = 1,
};
#define REL 10 /* 1 for relative, 0 for absolute */ #define REL 10 /* 1 for relative, 0 for absolute */
#define ASAP 9 /* 1 start now, 0 timer start */ #define ASAP 9 /* 1 start now, 0 timer start */
#define BCN 8 /* 1 beacon only, 0 for a */ #define BCN 8 /* 1 beacon only, 0 for a */

View file

@ -52,6 +52,7 @@ struct packet {
/* On RX this should be 1 since the maca puts the length as the first byte*/ /* On RX this should be 1 since the maca puts the length as the first byte*/
uint8_t offset; uint8_t offset;
uint8_t lqi; uint8_t lqi;
uint8_t status;
#if PACKET_STATS #if PACKET_STATS
uint8_t seen; uint8_t seen;
uint8_t post_tx; uint8_t post_tx;

View file

@ -102,6 +102,7 @@ enum posts {
static volatile uint8_t last_post = NO_POST; static volatile uint8_t last_post = NO_POST;
volatile uint8_t fcs_mode = USE_FCS; volatile uint8_t fcs_mode = USE_FCS;
volatile uint8_t prm_mode = PROMISC;
/* call periodically to */ /* call periodically to */
/* check that maca_entry is changing */ /* check that maca_entry is changing */
@ -181,7 +182,9 @@ void maca_init(void) {
/* initial radio command */ /* initial radio command */
/* nop, promiscuous, no cca */ /* nop, promiscuous, no cca */
*MACA_CONTROL = (1 << PRM) | (NO_CCA << MODE); *MACA_CONTROL =
(prm_mode << PRM) |
(NO_CCA << MODE);
enable_irq(MACA); enable_irq(MACA);
*INTFRC = (1 << INT_NUM_MACA); *INTFRC = (1 << INT_NUM_MACA);
@ -364,8 +367,8 @@ void post_receive(void) {
*MACA_CONTROL = ( (1 << maca_ctrl_asap) | *MACA_CONTROL = ( (1 << maca_ctrl_asap) |
( 4 << PRECOUNT) | ( 4 << PRECOUNT) |
( fcs_mode << NOFC ) | ( fcs_mode << NOFC ) |
( prm_mode << PRM) |
(1 << maca_ctrl_auto) | (1 << maca_ctrl_auto) |
(1 << maca_ctrl_prm) |
(maca_ctrl_seq_rx)); (maca_ctrl_seq_rx));
/* status bit 10 is set immediately */ /* status bit 10 is set immediately */
/* then 11, 10, and 9 get set */ /* then 11, 10, and 9 get set */
@ -405,7 +408,8 @@ void post_tx(void) {
#if PACKET_STATS #if PACKET_STATS
dma_tx->post_tx++; dma_tx->post_tx++;
#endif #endif
*MACA_TXLEN = (uint32_t)((dma_tx->length) + 2); *MACA_TXSEQNR = dma_tx->data[2];
*MACA_TXLEN = (uint32_t)((dma_tx->length) + 2) | (3 << 16); /* set rx len to ACK length */
*MACA_DMATX = (uint32_t)&(dma_tx->data[ 0 + dma_tx->offset]); *MACA_DMATX = (uint32_t)&(dma_tx->data[ 0 + dma_tx->offset]);
if(dma_rx == 0) { if(dma_rx == 0) {
dma_rx = get_free_packet(); dma_rx = get_free_packet();
@ -429,7 +433,8 @@ void post_tx(void) {
*MACA_TMREN = (1 << maca_tmren_cpl); *MACA_TMREN = (1 << maca_tmren_cpl);
enable_irq(MACA); enable_irq(MACA);
*MACA_CONTROL = ( (1 << maca_ctrl_prm) | ( 4 << PRECOUNT) | *MACA_CONTROL = ( ( 4 << PRECOUNT) |
( prm_mode << PRM) |
(maca_ctrl_mode_no_cca << maca_ctrl_mode) | (maca_ctrl_mode_no_cca << maca_ctrl_mode) |
(1 << maca_ctrl_asap) | (1 << maca_ctrl_asap) |
(maca_ctrl_seq_tx)); (maca_ctrl_seq_tx));
@ -610,8 +615,17 @@ void maca_isr(void) {
*MACA_CLRIRQ = (1 << maca_irq_di); *MACA_CLRIRQ = (1 << maca_irq_di);
dma_rx->length = *MACA_GETRXLVL - 2; /* packet length does not include FCS */ dma_rx->length = *MACA_GETRXLVL - 2; /* packet length does not include FCS */
dma_rx->lqi = get_lqi(); dma_rx->lqi = get_lqi();
// PRINTF("maca data ind %x %d\n\r", dma_rx, dma_rx->length);
/* check if received packet needs an ack */
if(dma_rx->data[1] & 0x20) {
/* this wait is necessary to auto-ack */
volatile uint32_t wait_clk;
wait_clk = *MACA_CLK + 200;
while(*MACA_CLK < wait_clk) { continue; }
}
if(maca_rx_callback != 0) { maca_rx_callback(dma_rx); } if(maca_rx_callback != 0) { maca_rx_callback(dma_rx); }
add_to_rx(dma_rx); add_to_rx(dma_rx);
dma_rx = 0; dma_rx = 0;
} }
@ -634,6 +648,7 @@ void maca_isr(void) {
if(action_complete_irq()) { if(action_complete_irq()) {
/* PRINTF("maca action complete %d\n\r", get_field(*MACA_CONTROL,SEQUENCE)); */ /* PRINTF("maca action complete %d\n\r", get_field(*MACA_CONTROL,SEQUENCE)); */
if(last_post == TX_POST) { if(last_post == TX_POST) {
tx_head->status = get_field(*MACA_STATUS,CODE);
if(maca_tx_callback != 0) { maca_tx_callback(tx_head); } if(maca_tx_callback != 0) { maca_tx_callback(tx_head); }
dma_tx = 0; dma_tx = 0;
free_tx_head(); free_tx_head();
@ -669,6 +684,9 @@ void init_phy(void)
*MACA_TXCCADELAY = 0x00000025; *MACA_TXCCADELAY = 0x00000025;
*MACA_FRAMESYNC0 = 0x000000A7; *MACA_FRAMESYNC0 = 0x000000A7;
*MACA_CLK = 0x00000008; *MACA_CLK = 0x00000008;
*MACA_RXACKDELAY = 30;
*MACA_RXEND = 180;
*MACA_TXACKDELAY = 68;
*MACA_MASKIRQ = ((1 << maca_irq_rst) | *MACA_MASKIRQ = ((1 << maca_irq_rst) |
(1 << maca_irq_acpl) | (1 << maca_irq_acpl) |
(1 << maca_irq_cm) | (1 << maca_irq_cm) |

View file

@ -16,6 +16,7 @@ TARGETS := blink-red blink-green blink-blue blink-white blink-allio \
# this space is initialized with a rom call to rom_data_init # this space is initialized with a rom call to rom_data_init
TARGETS_WITH_ROM_VARS := nvm-read nvm-write romimg flasher \ TARGETS_WITH_ROM_VARS := nvm-read nvm-write romimg flasher \
rftest-rx rftest-tx \ rftest-rx rftest-tx \
autoack-rx autoack-tx \
per per
################################################## ##################################################

109
tests/autoack-rx.c Normal file
View file

@ -0,0 +1,109 @@
/*
* Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
* to the MC1322x project (http://mc1322x.devl.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
*
* This file is part of libmc1322x: see http://mc1322x.devl.org
* for details.
*
* $Id$
*/
#include <mc1322x.h>
#include <board.h>
#include <stdio.h>
#include "tests.h"
#include "config.h"
#define LED LED_GREEN
void maca_rx_callback(volatile packet_t *p) {
(void)p;
gpio_data_set(1ULL<< LED);
gpio_data_reset(1ULL<< LED);
}
void main(void) {
volatile packet_t *p;
volatile uint8_t t=20;
uint8_t chan;
char c;
gpio_data(0);
gpio_pad_dir_set( 1ULL << LED );
/* read from the data register instead of the pad */
/* this is needed because the led clamps the voltage low */
gpio_data_sel( 1ULL << LED);
/* trim the reference osc. to 24MHz */
trim_xtal();
uart_init(INC, MOD, SAMP);
vreg_init();
maca_init();
/* sets up tx_on, should be a board specific item */
*GPIO_FUNC_SEL2 = (0x01 << ((44-16*2)*2));
gpio_pad_dir_set( 1ULL << 44 );
set_power(0x0f); /* 0dbm */
chan = 0;
set_channel(chan); /* channel 11 */
*MACA_MACPANID = 0xaaaa;
*MACA_MAC16ADDR = 0x1111;
*MACA_TXACKDELAY = 68; /* 68 puts the tx ack at about the correct spot */
set_prm_mode(AUTOACK);
print_welcome("rftest-rx");
while(1) {
/* call check_maca() periodically --- this works around */
/* a few lockup conditions */
check_maca();
if((p = rx_packet())) {
/* print and free the packet */
printf("autoack-rx --- ");
print_packet(p);
free_packet(p);
}
if(uart1_can_get()) {
c = uart1_getc();
if(c == 'z') t++;
if(c == 'x') t--;
*MACA_TXACKDELAY = t;
printf("tx ack delay: %d\n\r", t);
}
}
}

189
tests/autoack-tx.c Normal file
View file

@ -0,0 +1,189 @@
/*
* Copyright (c) 2010, Mariano Alvira <mar@devl.org> and other contributors
* to the MC1322x project (http://mc1322x.devl.org)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. 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.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE 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 INSTITUTE 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.
*
* This file is part of libmc1322x: see http://mc1322x.devl.org
* for details.
*
* $Id$
*/
#include <mc1322x.h>
#include <board.h>
#include <stdio.h>
#include "tests.h"
#include "config.h"
#define LED LED_RED
/* 802.15.4 PSDU is 127 MAX */
/* 2 bytes are the FCS */
/* therefore 125 is the max payload length */
#define PAYLOAD_LEN 16
#define DELAY 100000
void fill_packet(volatile packet_t *p) {
static volatile uint8_t count=0;
p->length = 16;
p->offset = 0;
p->data[0] = 0x71; /* 0b 10 01 10 000 1 1 0 0 001 data, ack request, short addr */
p->data[1] = 0x98; /* 0b 10 01 10 000 1 1 0 0 001 data, ack request, short addr */
p->data[2] = count++; /* dsn */
p->data[3] = 0xaa; /* pan */
p->data[4] = 0xaa;
p->data[5] = 0x11; /* dest. short addr. */
p->data[6] = 0x11;
p->data[7] = 0x22; /* src. short addr. */
p->data[8] = 0x22;
/* payload */
p->data[9] = 'a';
p->data[10] = 'c';
p->data[11] = 'k';
p->data[12] = 't';
p->data[13] = 'e';
p->data[14] = 's';
p->data[15] = 't';
}
void maca_tx_callback(volatile packet_t *p) {
switch(p->status) {
case 0:
printf("TX OK\n\r");
break;
case 3:
printf("CRC ERR\n\r");
break;
case 5:
printf("NO ACK\n\r");
break;
default:
printf("unknown status: %d\n", (int)p->status);
}
}
void main(void) {
volatile packet_t *p;
char c;
uint16_t r=30; /* start reception 100us before ack should arrive */
uint16_t end=180; /* 750 us receive window*/
/* trim the reference osc. to 24MHz */
trim_xtal();
uart_init(INC, MOD, SAMP);
vreg_init();
maca_init();
set_channel(0); /* channel 11 */
// set_power(0x0f); /* 0xf = -1dbm, see 3-22 */
// set_power(0x11); /* 0x11 = 3dbm, see 3-22 */
set_power(0x12); /* 0x12 is the highest, not documented */
/* sets up tx_on, should be a board specific item */
GPIO->FUNC_SEL_44 = 1;
GPIO->PAD_DIR_SET_44 = 1;
GPIO->FUNC_SEL_45 = 2;
GPIO->PAD_DIR_SET_45 = 1;
*MACA_RXACKDELAY = r;
printf("rx warmup: %d\n\r", (int)(*MACA_WARMUP & 0xfff));
*MACA_RXEND = end;
printf("rx end: %d\n\r", (int)(*MACA_RXEND & 0xfff));
set_prm_mode(AUTOACK);
print_welcome("rftest-tx");
while(1) {
/* call check_maca() periodically --- this works around */
/* a few lockup conditions */
check_maca();
while((p = rx_packet())) {
if(p) {
printf("RX: ");
print_packet(p);
free_packet(p);
}
}
if(uart1_can_get()) {
c = uart1_getc();
switch(c) {
case 'z':
r++;
if(r > 4095) { r = 0; }
*MACA_RXACKDELAY = r;
printf("rx ack delay: %d\n\r", r);
break;
case 'x':
if(r == 0) { r = 4095; } else { r--; }
*MACA_RXACKDELAY = r;
printf("rx ack delay: %d\n\r", r);
break;
case 'q':
end++;
if(r > 4095) { r = 0; }
*MACA_RXEND = end;
printf("rx end: %d\n\r", end);
break;
case 'w':
end--;
if(r == 0) { r = 4095; } else { r--; }
*MACA_RXEND = end;
printf("rx end: %d\n\r", end);
break;
default:
p = get_free_packet();
if(p) {
fill_packet(p);
printf("autoack-tx --- ");
print_packet(p);
tx_packet(p);
}
break;
}
}
}
}