diff --git a/doc/autoack b/doc/autoack new file mode 100644 index 000000000..3c5b0ea62 --- /dev/null +++ b/doc/autoack @@ -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. diff --git a/lib/include/maca.h b/lib/include/maca.h index 24c10ce3d..fa484b5c6 100644 --- a/lib/include/maca.h +++ b/lib/include/maca.h @@ -62,6 +62,11 @@ void set_demodulator_type(uint8_t demod); extern volatile uint8_t fcs_mode; #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 */ void tx_packet(volatile packet_t *p); volatile packet_t* rx_packet(void); @@ -105,6 +110,10 @@ enum { NO_FCS = 1, }; #define PRM 11 /* set for promiscuous mode */ +enum { + AUTOACK = 0, + PROMISC = 1, +}; #define REL 10 /* 1 for relative, 0 for absolute */ #define ASAP 9 /* 1 start now, 0 timer start */ #define BCN 8 /* 1 beacon only, 0 for a */ diff --git a/lib/include/packet.h b/lib/include/packet.h index 295257421..a792d8a1b 100644 --- a/lib/include/packet.h +++ b/lib/include/packet.h @@ -52,6 +52,7 @@ struct packet { /* On RX this should be 1 since the maca puts the length as the first byte*/ uint8_t offset; uint8_t lqi; + uint8_t status; #if PACKET_STATS uint8_t seen; uint8_t post_tx; diff --git a/lib/maca.c b/lib/maca.c index 0936eb3b0..025625af9 100644 --- a/lib/maca.c +++ b/lib/maca.c @@ -102,6 +102,7 @@ enum posts { static volatile uint8_t last_post = NO_POST; volatile uint8_t fcs_mode = USE_FCS; +volatile uint8_t prm_mode = PROMISC; /* call periodically to */ /* check that maca_entry is changing */ @@ -181,7 +182,9 @@ void maca_init(void) { /* initial radio command */ /* nop, promiscuous, no cca */ - *MACA_CONTROL = (1 << PRM) | (NO_CCA << MODE); + *MACA_CONTROL = + (prm_mode << PRM) | + (NO_CCA << MODE); enable_irq(MACA); *INTFRC = (1 << INT_NUM_MACA); @@ -364,8 +367,8 @@ void post_receive(void) { *MACA_CONTROL = ( (1 << maca_ctrl_asap) | ( 4 << PRECOUNT) | ( fcs_mode << NOFC ) | + ( prm_mode << PRM) | (1 << maca_ctrl_auto) | - (1 << maca_ctrl_prm) | (maca_ctrl_seq_rx)); /* status bit 10 is set immediately */ /* then 11, 10, and 9 get set */ @@ -405,7 +408,8 @@ void post_tx(void) { #if PACKET_STATS dma_tx->post_tx++; #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]); if(dma_rx == 0) { dma_rx = get_free_packet(); @@ -429,7 +433,8 @@ void post_tx(void) { *MACA_TMREN = (1 << maca_tmren_cpl); 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) | (1 << maca_ctrl_asap) | (maca_ctrl_seq_tx)); @@ -610,8 +615,17 @@ void maca_isr(void) { *MACA_CLRIRQ = (1 << maca_irq_di); dma_rx->length = *MACA_GETRXLVL - 2; /* packet length does not include FCS */ 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); } + add_to_rx(dma_rx); dma_rx = 0; } @@ -634,6 +648,7 @@ void maca_isr(void) { if(action_complete_irq()) { /* PRINTF("maca action complete %d\n\r", get_field(*MACA_CONTROL,SEQUENCE)); */ if(last_post == TX_POST) { + tx_head->status = get_field(*MACA_STATUS,CODE); if(maca_tx_callback != 0) { maca_tx_callback(tx_head); } dma_tx = 0; free_tx_head(); @@ -669,6 +684,9 @@ void init_phy(void) *MACA_TXCCADELAY = 0x00000025; *MACA_FRAMESYNC0 = 0x000000A7; *MACA_CLK = 0x00000008; + *MACA_RXACKDELAY = 30; + *MACA_RXEND = 180; + *MACA_TXACKDELAY = 68; *MACA_MASKIRQ = ((1 << maca_irq_rst) | (1 << maca_irq_acpl) | (1 << maca_irq_cm) | diff --git a/tests/Makefile b/tests/Makefile index 5e8dff878..b664694da 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -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 TARGETS_WITH_ROM_VARS := nvm-read nvm-write romimg flasher \ rftest-rx rftest-tx \ + autoack-rx autoack-tx \ per ################################################## diff --git a/tests/autoack-rx.c b/tests/autoack-rx.c new file mode 100644 index 000000000..88dad71fe --- /dev/null +++ b/tests/autoack-rx.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010, Mariano Alvira 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 +#include +#include + +#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); + } + + } +} diff --git a/tests/autoack-tx.c b/tests/autoack-tx.c new file mode 100644 index 000000000..8621ab8b0 --- /dev/null +++ b/tests/autoack-tx.c @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2010, Mariano Alvira 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 +#include +#include + +#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; + } + } + + } + +}