Reception OK

This commit is contained in:
tzim 2019-09-10 00:46:03 +02:00
parent a7d9fd37b3
commit 2c1b324d4f
7 changed files with 451 additions and 24 deletions

174
Hamming.c Normal file
View file

@ -0,0 +1,174 @@
/*
Hamming Error-Correcting Code (ECC)
Optimized for avr-gcc 4.8.1 in Atmel AVR Studio 6.2
August 12, 2014
You should include Hamming.c, Hamming.h, and only one of the other Hamming files in your project.
The other Hamming files implement the same methods in different ways, that may be better or worse for your needs.
This was created for LoFi in the TheHackadayPrize contest.
http://hackaday.io/project/1552-LoFi
Copyright 2014 David Cook
RobotRoom.com
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 <avr/pgmspace.h>
#include "Hamming.h"
/****************************/
/* */
/* Constants and structures */
/* */
/****************************/
#ifndef null
#define null ((void*) 0)
#endif
// If transmitting/writing only, you don't need to include this file.
// If receiving/reading, then this provides the methods to correct bit errors.
#define UNCORRECTABLE 0xFF
#define ERROR_IN_PARITY 0xFE
#define NO_ERROR 0x00
/****************************/
/* */
/* Global variables */
/* */
/****************************/
// Private table. Faster and more compact than multiple if statements.
static const byte _hammingCorrect128Syndrome[16] PROGMEM =
{
NO_ERROR, // 0
ERROR_IN_PARITY, // 1
ERROR_IN_PARITY, // 2
0x01, // 3
ERROR_IN_PARITY, // 4
0x02, // 5
0x04, // 6
0x08, // 7
ERROR_IN_PARITY, // 8
0x10, // 9
0x20, // 10
0x40, // 11
0x80, // 12
UNCORRECTABLE, // 13
UNCORRECTABLE, // 14
UNCORRECTABLE, // 15
};
/****************************/
/* */
/* Private methods */
/* */
/****************************/
// Give a pointer to a received byte,
// and given a nibble difference in parity (parity ^ calculated parity)
// this will correct the received byte value if possible.
// It returns the number of bits corrected:
// 0 means no errors
// 1 means one corrected error
// 3 means corrections not possible
static byte HammingCorrect128Syndrome(byte* value, byte syndrome)
{
// Using only the lower nibble (& 0x0F), look up the bit
// to correct in a table
byte correction = pgm_read_byte(&(_hammingCorrect128Syndrome[syndrome & 0x0F]));
if (correction != NO_ERROR)
{
if (correction == UNCORRECTABLE || value == null)
{
return 3; // Non-recoverable error
}
else
{
if ( correction != ERROR_IN_PARITY)
{
*value ^= correction;
}
return 1; // 1-bit recoverable error;
}
}
return 0; // No errors
}
/****************************/
/* */
/* Public methods */
/* */
/****************************/
// Given a pointer to a received byte and the received parity (as a lower nibble),
// this calculates what the parity should be and fixes the received value if needed.
// It returns the number of bits corrected:
// 0 means no errors
// 1 means one corrected error
// 3 means corrections not possible
byte HammingCorrect128(byte* value, nibble parity)
{
byte syndrome;
if (value == null)
{
return 3; // Non-recoverable error
}
syndrome = HammingCalculateParity128(*value) ^ parity;
if (syndrome != 0)
{
return HammingCorrect128Syndrome(value, syndrome);
}
return 0; // No errors
}
// Given a pointer to a first value and a pointer to a second value and
// their combined given parity (lower nibble first parity, upper nibble second parity),
// this calculates what the parity should be and fixes the values if needed.
// It returns the number of bits corrected:
// 0 means no errors
// 1 means one corrected error
// 2 means two corrected errors
// 3 means corrections not possible
byte HammingCorrect2416(byte* first, byte* second, byte parity)
{
byte syndrome;
if (first == null || second == null)
{
return 3; // Non-recoverable error
}
syndrome = HammingCalculateParity2416(*first, *second) ^ parity;
if (syndrome != 0)
{
return HammingCorrect128Syndrome(first, syndrome) + HammingCorrect128Syndrome(second, syndrome >> 4);
}
return 0; // No errors
}

68
Hamming.h Normal file
View file

@ -0,0 +1,68 @@
/*
Hamming Error-Correcting Code (ECC)
Optimized for avr-gcc 4.8.1 in Atmel AVR Studio 6.2
August 12, 2014
You should include Hamming.c, Hamming.h, and only one of the other Hamming files in your project.
The other Hamming files implement the same methods in different ways, that may be better or worse for your needs.
This was created for LoFi in the TheHackadayPrize contest.
http://hackaday.io/project/1552-LoFi
Copyright 2014 David Cook
RobotRoom.com
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 _HAMMING_H
#define _HAMMING_H
#ifndef _AVR_H
typedef unsigned char byte;
typedef unsigned char nibble;
#endif
/**** These are needed to transmit and receive ****/
// Given a byte to transmit, this returns the parity as a nibble
nibble HammingCalculateParity128(byte value);
// Given two bytes to transmit, this returns the parity
// as a byte with the lower nibble being for the first byte,
// and the upper nibble being for the second byte.
byte HammingCalculateParity2416(byte first, byte second);
/**** These are needed only to receive ****/
// Given a pointer to a received byte and the received parity (as a lower nibble),
// this calculates what the parity should be and fixes the received value if needed.
// It returns the number of bits corrected:
// 0 means no errors
// 1 means one corrected error
// 3 means corrections not possible
byte HammingCorrect128(byte* value, nibble parity);
// Given a pointer to a first value and a pointer to a second value and
// their combined given parity (lower nibble first parity, upper nibble second parity),
// this calculates what the parity should be and fixes the values if needed.
// It returns the number of bits corrected:
// 0 means no errors
// 1 means one corrected error
// 2 means two corrected errors
// 3 means corrections not possible
byte HammingCorrect2416(byte* first, byte* second, byte parity);
#endif // _HAMMING_H

View file

@ -0,0 +1,64 @@
/*
Hamming Error-Correcting Code (ECC)
Optimized for avr-gcc 4.8.1 in Atmel AVR Studio 6.2
August 12, 2014
You should include Hamming.c, Hamming.h, and only one of the other Hamming files in your project.
The other Hamming files implement the same methods in different ways, that may be better or worse for your needs.
This was created for LoFi in the TheHackadayPrize contest.
http://hackaday.io/project/1552-LoFi
Copyright 2014 David Cook
RobotRoom.com
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 <avr/pgmspace.h>
#include "Hamming.h"
/****************************/
/* */
/* Global variables */
/* */
/****************************/
// This contains all of the precalculated parity values for a nibble (4 bits).
static const byte _hammingCalculateParityLowNibble[] PROGMEM =
{ 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7 };
static const byte _hammingCalculateParityHighNibble[] PROGMEM =
{ 0, 9, 10, 3, 11, 2, 1, 8, 12, 5, 6, 15, 7, 14, 13, 4 };
/****************************/
/* */
/* Public methods */
/* */
/****************************/
// Given a byte to transmit, this returns the parity as a nibble
nibble HammingCalculateParity128(byte value)
{
return pgm_read_byte(&(_hammingCalculateParityLowNibble[value&0x0F])) ^ pgm_read_byte(&(_hammingCalculateParityHighNibble[value >> 4]));
}
// Given two bytes to transmit, this returns the parity
// as a byte with the lower nibble being for the first byte,
// and the upper nibble being for the second byte.
byte HammingCalculateParity2416(byte first, byte second)
{
return HammingCalculateParity128(second) << 4 | HammingCalculateParity128(first);
}

View file

@ -55,7 +55,7 @@ RESETPORT = /dev/ttyU0
TARGET = pyrorf TARGET = pyrorf
SRC = main.c lcd.c spi.c rf24.c SRC = main.c lcd.c spi.c rf24.c Hamming.c HammingCalculateParitySmallAndFast.c
CXXSRC = CXXSRC =
ASRC = i2cmaster.S ASRC = i2cmaster.S
MCU = atmega32u4 MCU = atmega32u4
@ -102,7 +102,7 @@ LDFLAGS = -lm -Wl,--gc-sections
AVRDUDE_PROGRAMMER = avr109 AVRDUDE_PROGRAMMER = avr109
AVRDUDE_PORT = $(PORT) AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex:i AVRDUDE_WRITE_FLASH = -U flash:w:$(TARGET).hex:i
AVRDUDE_FLAGS = -D -F -p m32u4 -P$(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) -b $(UPLOAD_RATE) AVRDUDE_FLAGS = -D -p m32u4 -P$(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER)
# Program settings # Program settings
CC = avr-gcc CC = avr-gcc

110
main.c
View file

@ -14,6 +14,7 @@
#include "lcd.h" #include "lcd.h"
#include "spi.h" #include "spi.h"
#include "rf24.h" #include "rf24.h"
#include "Hamming.h"
int main (void); int main (void);
void setup (void); void setup (void);
@ -21,6 +22,61 @@ void loop (void);
void lcdprint( char* ptr); void lcdprint( char* ptr);
void debughex (uint8_t* ptr,uint8_t len); void debughex (uint8_t* ptr,uint8_t len);
int decode_radioin (uint8_t * buffer){
uint8_t err=0, errcpt=0, plen, cpt, incrc,crc;
uint8_t* in = buffer;
uint8_t* out, *end;
// Decode first 2 bytes
err = HammingCorrect2416(in,in+1,*(in+2));
if(err >2) { lcdprint("RXH1"); return 0; }
errcpt+=err;
in+=3;
// len
plen = buffer[0] & 0x0F;
if(plen>32) return 0;
// Hamming
cpt = plen + (plen&1); // even
cpt = (cpt/2)*3;
end = buffer + cpt;
// Correct
while(in<end){
err= HammingCorrect2416(in,in+1,*(in+2));
if(err>2){
lcdprint("RXH"); return 0;
}
errcpt+=err; in+=3;
}
// Shift (strip parity)
in = buffer+3;
out = buffer+2;
while(in<end){
*(out++)=*(in++); // Copy Byte
*(out++)=*(in++); // Copy Byte
in++; // skip parity
}
/*
// Calc CRC
in=buffer;
incrc=buffer[3];
buffer[3]=0;
cpt=plen;
crc=0;
while(cpt--) crc= _crc8_ccitt_update(crc,*(in++));
if(crc!=incrc) {printf("CRC\n"); return 0; }
*/
return plen;
}
int main(void) int main(void)
{ {
setup(); setup();
@ -35,7 +91,7 @@ void setup(void)
#endif #endif
lcd_init(20,4); lcd_init(20,4);
lcd_backlight(0); lcd_backlight(1);
lcd_clear(); lcd_clear();
lcd_home(); lcd_home();
lcd_display(); lcd_display();
@ -48,14 +104,22 @@ void setup(void)
rf24_setup(); rf24_setup();
// rf24_init(); rf24_init();
//char st = rf24_read_reg(STATUS); //char st = rf24_read_reg(STATUS);
rf24_update_fifo_status(); rf24_update_fifo_status();
debughex(&rf24_status,1); debughex(&rf24_status,1);
#if defined(__AVR_ATmega32A__)
GICR|=_BV(INT2);
#elif defined(__AVR_ATmega32U4__)
EICRA=_BV(ISC21);
EIMSK=_BV(INT2);
#endif
while(1); rf24_RXMode();
#if defined(TIMSK1) #if defined(TIMSK1)
// setup Timer1 // setup Timer1
TCCR1A = 0; TCCR1A = 0;
@ -63,7 +127,7 @@ void setup(void)
OCR1A = 10000; OCR1A = 10000;
TIMSK1 = _BV(OCIE1A); TIMSK1 = _BV(OCIE1A);
TCCR1B = _BV(WGM12)|_BV(CS11); TCCR1B = _BV(WGM12)|_BV(CS11);
#elif defined(__AVR_ATmega2560__) #else
// setup Timer1 // setup Timer1
TCCR1A = 0; TCCR1A = 0;
TCNT1=0; TCNT1=0;
@ -77,18 +141,32 @@ void setup(void)
} }
volatile int i=0,j=0; volatile int i=0,j=0;
volatile int u=0; volatile int u=0,insomnia=0;
uint8_t buff[40];
void loop(void) void loop(void)
{ if(!u){ {
u=20; insomnia=0;
char buf[15]; if(!u){
lcd_setCursor(0,1); u=0;
snprintf(buf,15,"%d %d ",i,j++); //char buf[15];
lcdprint(buf); lcd_setCursor(12,0);
rf24_update_status();
debughex(&rf24_status,1);
if((rf24_status&0x0E)!=0x0E){
int s = rf24_receive(buff);
s= decode_radioin(buff);
lcd_setCursor(0,1);
debughex(buff,s);
insomnia=1;
}
}
if(!insomnia){
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_mode();
} }
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_mode();
} }
@ -97,6 +175,12 @@ ISR(TIMER1_COMPA_vect){
if(u)u--; if(u)u--;
} }
ISR(INT2_vect){
insomnia=1;
lcd_setCursor(12,3);
lcdprint("INT");
}
void lcdprint( char* ptr) void lcdprint( char* ptr)
{ {
while (*ptr) lcd_write(*ptr++); while (*ptr) lcd_write(*ptr++);

47
rf24.c
View file

@ -24,7 +24,6 @@ void inline rf24_ceHi(){
void inline rf24_ceLow(){ void inline rf24_ceLow(){
CE_PIN_PORT &= ~_BV(CE_PIN_BIT); CE_PIN_PORT &= ~_BV(CE_PIN_BIT);
_delay_us(10);
} }
void inline rf24_csnHi(){ void inline rf24_csnHi(){
@ -68,6 +67,12 @@ uint8_t rf24_read_reg(const uint8_t reg)
} }
void rf24_update_status()
{
rf24_csnLow();
rf24_status = spi_transfer(NOP);
rf24_csnHi();
}
void rf24_update_fifo_status() void rf24_update_fifo_status()
{ {
@ -101,23 +106,53 @@ void rf24_init()
rf24_write_reg(DYNPD,0); rf24_write_reg(DYNPD,0);
rf24_write_reg(FEATURE,0); rf24_write_reg(FEATURE,0);
rf24_Off();
} }
/*
void rf24_Off() void rf24_Off()
{ {
rf24_write_reg(CONFIG,rf24_CONFIG&0xF8); rf24_write_reg(CONFIG,rf24_CONFIG&0xF8);
rf24_csnLow();
spi_transfer(FLUSH_RX);
rf24_csnHi();
rf24_csnLow();
spi_transfer(FLUSH_TX);
rf24_csnHi();
rf24_write_reg(STATUS,0xFF);
} }
void rf24_RXMode() void rf24_RXMode()
{ {
rf24_Off(); rf24_ceLow();
_delay_us(1000); rf24_csnLow();
rf24_buffer[0]=FLUSH_RX; spi_transfer(FLUSH_RX);
spi_transfer_rf24(rf24_buffer,rf24_buffer,1); rf24_csnHi();
rf24_write_reg(CONFIG,rf24_CONFIG|0x03); rf24_write_reg(CONFIG,rf24_CONFIG|0x03);
rf24_ceHi();
} }
int rf24_receive(uint8_t * buffer)
{
rf24_update_status();
int pipe = (rf24_status & 0x0E) >> 1;
if(pipe==7) return 0;
int len = plens[pipe];
int i=len;
rf24_csnLow();
spi_transfer(R_RX_PAYLOAD);
while (i--)
*(buffer++) = spi_transfer(NOP);
rf24_csnHi();
rf24_write_reg(STATUS,_BV(RX_DR));
return len;
}
/*
void rf24_TXMode() void rf24_TXMode()
{ {
rf24_Off(); rf24_Off();

6
rf24.h
View file

@ -10,17 +10,19 @@ void rf24_write_lreg(const uint8_t reg, const uint8_t * val, size_t len);
void rf24_write_reg(const uint8_t reg, const uint8_t val); void rf24_write_reg(const uint8_t reg, const uint8_t val);
uint8_t rf24_read_reg(const uint8_t reg); uint8_t rf24_read_reg(const uint8_t reg);
void rf24_update_fifo_status(); void rf24_update_fifo_status();
void rf24_update_status();
extern uint8_t rf24_status; extern uint8_t rf24_status;
extern uint8_t rf24_fifo; extern uint8_t rf24_fifo;
void rf24_setup(); void rf24_setup();
void rf24_init(); void rf24_init();
void rf24_RXMode();
void rf24_Off();
int rf24_receive(uint8_t * buffer);
/* /*
void rf24_Off();
void rf24_RXMode(); void rf24_RXMode();
void rf24_TXMode(); void rf24_TXMode();
int rf24_receive(uint8_t * buffer);
int rf24_send(uint8_t * buffer, int len); int rf24_send(uint8_t * buffer, int len);
int rf24_waitforTX(); int rf24_waitforTX();
*/ */