Reputation: 123
I'm trying to develop an RTEMS application that decodes a message that's encoded with Manchester encoder transmitted by the transmitter board. Two Raspberry Pi 2 are mounted on the board, which are connected to each other via GPIO 4 and GND. One of the Rpi is the transmitter, and sends a sequence of pulses every 10s. These pulses encode a message according to the Manchester code. The IEEE version of the code is used. There is a promise that the first bit is a 0 bit.
I'm having trouble getting the signal. For now, I'm only trying to get the signal based on edges, but I'm not getting the signal printed.
I've been trying for 2 days but I don't really now what I'm doing wrong. Any help is greatly appreciated
#define GPIO_PIN 4
#define MAX_EDGES 4096
#define SIGNAL_GAP_MS 100
volatile int edge_count = 0;
volatile rtems_interval edge_times[MAX_EDGES];
volatile rtems_interval last_edge_time = 0;
volatile uint32_t edge_values[MAX_EDGES];
volatile bool new_signal_ready = false;
void handler(void *arg) {
rtems_interval current_time = rtems_clock_get_ticks_since_boot();
uint8_t value = rtems_gpio_bsp_get_value(0, GPIO_PIN);
rtems_interval time_since_last_edge = current_time - last_edge_time;
if (time_since_last_edge >
rtems_clock_get_ticks_per_second() * SIGNAL_GAP_MS / 1000) {
if (edge_count > 0) {
new_signal_ready = true;
}
edge_count = 0;
}
if (edge_count < MAX_EDGES) {
edge_times[edge_count] = current_time - last_edge_time;
edge_values[edge_count] = value;
edge_count++;
}
last_edge_time = current_time;
}
void init_gpio(void) {
rtems_status_code sc;
sc = rtems_gpio_bsp_select_input(0, GPIO_PIN, NULL);
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to set GPIO %d as input. Error code: %s\n", GPIO_PIN,
rtems_status_text(sc));
return;
}
sc = rtems_gpio_bsp_set_resistor_mode(0, GPIO_PIN, PULL_UP);
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to set pull-up resistor for GPIO %d. Error code: %s\n",
GPIO_PIN, rtems_status_text(sc));
return;
}
printk("GPIO %d initialized as input with pull-up.\n", GPIO_PIN);
}
void interrupt_config(void) {
rtems_status_code sc;
sc = rtems_gpio_bsp_enable_interrupt(0, GPIO_PIN, BOTH_EDGES);
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to enable interrupt on GPIO %d. Error code: %s\n", GPIO_PIN,
rtems_status_text(sc));
return;
}
printk("Interrupt enabled on GPIO %d.\n", GPIO_PIN);
sc = rtems_interrupt_handler_install(rtems_gpio_bsp_get_vector(0),
"GPIO Interrupt Handler",
RTEMS_INTERRUPT_UNIQUE, handler, NULL);
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to install interrupt handler. Error code: %s\n",
rtems_status_text(sc));
return;
} else {
printk("Interrupt handler installed.\n");
}
}
void print_signal(void) {
printk("Signal received with %d edges:\n", edge_count);
for (int i = 0; i < edge_count; i++) {
printk("%d", edge_values[i]);
}
printk("\nEnd of signal sequence.\n\n");
}
void reset_signal_data(void) {
edge_count = 0;
for (int i = 0; i < MAX_EDGES; i++) {
edge_times[i] = 0;
edge_values[i] = 0;
}
}
rtems_task Init(rtems_task_argument argument) {
rtems_status_code sc;
printk("Initializing ...\n");
sc = rtems_gpio_initialize();
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to initialize GPIO. Error code: %s\n",
rtems_status_text(sc));
return;
} else {
printk("GPIO API initialized.\n");
}
init_gpio();
interrupt_config();
while (1) {
if (new_signal_ready) {
print_signal();
new_signal_ready = false;
}
reset_signal_data();
rtems_task_wake_after(1);
}
}
Upvotes: 2
Views: 98
Reputation: 123
Edit: I updated the code. I think it was a memory problem, #define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(5)
did the job.
You can find more informations here General System Configuration
#include <bsp.h>
#include <bsp/gpio.h>
#include <rtems.h>
#include <rtems/bspIo.h>
#include <stdint.h>
#define GPIO_PIN 4
#define GPIO_BANK 0
#define MAX_BITS 4000 // Increased to allow for longer signals
#define EDGE_THRESHOLD_NS 1000000 // 1ms in nanoseconds
volatile bool edge_detected = false;
volatile uint8_t decoded_bits[MAX_BITS / 8];
volatile uint32_t bit_count = 0;
volatile uint64_t last_edge_time = 0;
rtems_gpio_irq_state handler(void *arg) {
(void)arg;
edge_detected = true;
return IRQ_HANDLED;
}
void decode_manchester(void) {
uint64_t current_time = rtems_clock_get_uptime_nanoseconds();
uint64_t time_diff = current_time - last_edge_time;
decoded_bits[0] &= ~(1 << 7);
if (time_diff > EDGE_THRESHOLD_NS) {
uint8_t bit_value = rtems_gpio_get_value(GPIO_PIN);
uint32_t byte_index = bit_count / 8;
uint32_t bit_index = 7 - (bit_count % 8);
if (byte_index < MAX_BITS / 8) {
if (bit_value)
decoded_bits[byte_index] |= (1 << bit_index);
else
decoded_bits[byte_index] &= ~(1 << bit_index);
bit_count++;
}
last_edge_time = current_time;
}
}
void print_decoded_message(void) {
printk("Bit length: %u Bits / %u Bytes\n", bit_count, bit_count / 8);
// Print binary
printk("Binary:\n");
for (uint32_t i = 0; i < (bit_count + 7) / 8; i++) {
for (int j = 7; j >= 0; j--) {
if (i * 8 + (7 - j) < bit_count)
printk("%c", (decoded_bits[i] & (1 << j)) ? '1' : '0');
}
printk(" ");
}
printk("\n");
// Print ASCII
printk("ASCII:\n");
for (uint32_t i = 0; i < (bit_count + 7) / 8; i++) {
char c = decoded_bits[i];
if (c >= 32 && c <= 126) // Printable ASCII range
printk("%c", c);
else
printk(".");
}
printk("\n\n");
// Reset for next signal
bit_count = 0;
}
rtems_task Init(rtems_task_argument ignored) {
(void)ignored;
rtems_status_code sc;
printk("\n*** Manchester Decoder ***\n\n");
printk("Initializing GPIO and setting up interrupt...\n\n");
sc = rtems_gpio_initialize();
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to initialize GPIO. Error: %s\n", rtems_status_text(sc));
rtems_task_delete(RTEMS_SELF);
return;
} else {
printk("GPIO initialized\n");
}
sc = rtems_gpio_request_pin(GPIO_PIN, DIGITAL_INPUT, false, false, NULL);
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to request GPIO pin. Error: %s\n", rtems_status_text(sc));
rtems_task_delete(RTEMS_SELF);
return;
} else {
printk("GPIO pin requested\n");
}
sc = rtems_gpio_resistor_mode(GPIO_PIN, PULL_UP);
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to set resistor mode. Error: %s\n", rtems_status_text(sc));
rtems_task_delete(RTEMS_SELF);
return;
} else {
printk("Pull-Up resistor enabled\n");
}
sc = rtems_gpio_enable_interrupt(GPIO_PIN, BOTH_EDGES, UNIQUE_HANDLER, true,
handler, NULL);
if (sc != RTEMS_SUCCESSFUL) {
printk("Failed to enable interrupt. Error: %s\n", rtems_status_text(sc));
rtems_task_delete(RTEMS_SELF);
return;
} else {
printk("GPIO interrupt enabled\n\n");
}
printk("GPIO initialized. Waiting for signals...\n\n");
while (1) {
if (edge_detected) {
decode_manchester();
edge_detected = false;
}
if (rtems_clock_get_uptime_nanoseconds() - last_edge_time >
500000000) { // half a second of inactivity
if (bit_count > 0) {
printk("Signal complete. Decoding signal...\n\n");
print_decoded_message();
}
}
rtems_task_wake_after(1); // Yield to other tasks
}
}
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
#define CONFIGURE_MAXIMUM_TASKS rtems_resource_unlimited(5)
#define CONFIGURE_MAXIMUM_USER_EXTENSIONS 1
#define CONFIGURE_MAXIMUM_SEMAPHORES 4
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
#define CONFIGURE_MICROSECONDS_PER_TICK 1000 // 1ms per tick
#define CONFIGURE_INIT
#include <rtems/confdefs.h>
Upvotes: 0