zdrojový kód modulu

#include <stdint.h>
#include <stdio.h>
#include <avr/io.h>
#include <inttypes.h>
#include <avr/iom8.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <string.h> 

#define F_CPU 7372800 

#include <util/delay.h> 

#define UART_BAUD_RATE 115200
#define UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)((F_CPU)/((UART_BAUD_RATE)*16l)-1) 

#define PROC_WAITING_FOR_COMMAND 1
#define PROC_WAITING_FOR_CHANNEL_NUMBER 2
#define PROC_WAITING_FOR_STOP_TX 3 

#define STATE_RX 0
#define STATE_TX 1 

#define COMMAND_HELP "help"
#define COMMAND_SET_CHANNEL "setChannel"
#define COMMAND_GET_STATUS "getStatus"
#define COMMAND_RX "rx"
#define COMMAND_TX "tx"
#define COMMAND_RESET "reset" 

// define stdout function
static int UARTPutCSTDOUT(char c, FILE *stream);
// stdout
static FILE UARTStdOut = FDEV_SETUP_STREAM(UARTPutCSTDOUT, NULL, _FDEV_SETUP_WRITE); 

static uint8_t commandBufferSize = 16;
static unsigned char commandBuffer[16];
static uint8_t commandBufferPos = 0; 

static uint8_t currentState = STATE_RX; 

static uint8_t currentChannel = 9;
static uint8_t commandProcess = 1; 

void commandBufferAdd(char ch) {
    if (commandBufferPos >= commandBufferSize) {
        commandBufferReset();
    }
    commandBuffer[commandBufferPos++] = ch;
} 

void commandBufferReset(void) {
    commandBufferPos = 0;
    uint8_t i;
    for (i = 0; i < commandBufferSize; i++) {
        commandBuffer[i] = 0x00;
    }
} 

void UARTInit(void) {
    // set RS232 values
    UBRRH = (uint8_t) (UART_BAUD_CALC(UART_BAUD_RATE, F_CPU) >> 8);
    UBRRL = (uint8_t) UART_BAUD_CALC(UART_BAUD_RATE ,F_CPU);
    UCSRB = (1 << RXEN) | (1 << TXEN) | (1 << RXCIE);
    UCSRC = (1 << URSEL) | (3 << UCSZ0);
} 

void UARTPutC(unsigned char c) {
    while (!(UCSRA & (1 << UDRE)));
    UDR = c;
} 

void UARTPutString(unsigned char *data) {
    while (*data) {
        UARTPutC(*data);
        data++;
    }
} 

int UARTPutCSTDOUT(char c, FILE *stream) {
    if (c == '\n') UARTPutCSTDOUT('\r', stream);
    while(!(UCSRA & (1 << UDRE)));
    UDR = c;
    return 0;
} 

void UARTPutData(unsigned char *data, uint8_t lenght) {
    uint8_t i;
    for (i = 0; i < lenght; i++) {
        UARTPutC(data[i]);
    }
} 

int getSignalStrength(void) {
    ADCSRA |= (1 << ADIF);
    ADCSRA |= (1 << ADSC);
    while (ADCSRA & (1 << ADIF));
    return ADC;
} 

int setChannel(uint8_t channel) {
    if (currentState == STATE_RX && channel <= 40) {
        int8_t skip = currentChannel - channel;
        if (skip < 0) {
            skip = skip + 40;
        }
        DDRB &= ~(1 << PB2);
        PORTB &= ~(1 << PB2);
        uint8_t i;
        for (i = 0; i < skip; i++) {
            _delay_ms(10);
            DDRB |= (1 << PB2);
            _delay_ms(10);
            DDRB &= ~(1 << PB2);
        }
        currentChannel = channel;
        return 1;
    } else {
        return 0;
    }
} 

void setRX(void) {
    PORTB &= ~(1 << PB1);
    currentState = STATE_RX;
} 

void setTX(void) {
    PORTB |= (1 << PB1);
    currentState = STATE_TX;
} 

void resetRadio(void) {
    setRX();
    _delay_ms(100);
    currentChannel = 9;
    PORTB |= (1 << PB0);
    _delay_ms(200);
    PORTB &= ~(1 << PB0);
    _delay_ms(100);
    setChannel(1);
} 

void prompt(void) {
    if (currentState == STATE_RX) {
        printf("cmd (%d, RX): ", currentChannel);
    } else {
        printf("cmd (%d, TX): ", currentChannel);
    }
} 

SIGNAL (SIG_UART_RECV) {
    int byte = UDR; 

    switch (commandProcess) {
        case PROC_WAITING_FOR_COMMAND:
            if (byte == 0x0a || byte == 0x0d) {
                UARTPutString("\r\n");
                if (strcmp(COMMAND_HELP, commandBuffer) == 0) {
                    UARTPutString("---------------------\r\ncb2net 1.0 by Habr (http://cb2net.bivoj.eu)\r\nnavailible commands:\r\ngetStatus, setChannel, tx, rx, reset, help\r\n---------------------\r\n");
                    commandBufferReset();
                    prompt();
                } else if (strcmp(COMMAND_SET_CHANNEL, commandBuffer) == 0) {
                    UARTPutString("enter channel number (1-40): ");
                    commandProcess = PROC_WAITING_FOR_CHANNEL_NUMBER;
                    commandBufferReset();
                } else if (strcmp(COMMAND_RX, commandBuffer) == 0) {
                    setRX();
                    UARTPutString("OK, transceiver is now in RX mode\r\n");
                    commandBufferReset();
                    prompt();
                } else if (strcmp(COMMAND_TX, commandBuffer) == 0) {
                    setTX();
                    UARTPutString("OK, transceiver is now in TX mode\r\n");
                    commandBufferReset();
                    prompt();
                } else if (strcmp(COMMAND_RESET, commandBuffer) == 0) {
                    resetRadio();
                    UARTPutString("OK, transceiver was resetted.\r\n");
                    commandBufferReset();
                    prompt();
                } else if (strcmp(COMMAND_GET_STATUS, commandBuffer) == 0) {
                    UARTPutString("cb2net status\r\n");
                    printf("current channel: %d\r\n", currentChannel);
                    if (currentState == STATE_RX) {
                        UARTPutString("radio state: RX\r\n");
                        printf("signal strength: %d\r\n", getSignalStrength());
                    } else {
                        UARTPutString("radio state: TX\r\n");
                        printf("signal strength: -1\r\n");
                    }
                    commandBufferReset();
                    prompt();
                } else {
                    UARTPutString("unknown command, type \"help\" for help\r\n");
                    commandBufferReset();
                    prompt();
                }
            } else {
                if (byte >= 0x30 && byte <= 0x7E) {
                    commandBufferAdd(byte);
                    UARTPutC(byte);
                }
            }
        break;
        case PROC_WAITING_FOR_CHANNEL_NUMBER:
            if (byte == 0x0a || byte == 0x0d) {
                UARTPutString("\r\n");
                commandProcess = PROC_WAITING_FOR_COMMAND;
                uint8_t channel = 0;
                sscanf(commandBuffer, "%d", &channel);
                if (channel > 0 && channel <= 40) {
                    if (setChannel(channel)) {
                        printf("OK, channel is set to: %d\r\n", channel);
                    } else {
                        UARTPutString("ERROR, transceiver is in TX mode\r\n");
                    }
                } else {
                    printf("ERROR, bad channel number: %d\r\n", channel);
                }
                commandBufferReset();
                prompt();
            } else {
                if (byte >= 0x30 && byte <= 0x39) {
                    commandBufferAdd(byte);
                    UARTPutC(byte);
                }
            }
        break; 

    }
} 

int main(void) {
    UARTInit(); 

    sei(); 

    DDRB |= (1 << PB1) | (1 << PB0); 

    stdout = &UARTStdOut; 

    ADMUX = (0 << REFS1) | (0 << REFS0);
    ADCSRA = (1 << ADEN) | (0 << ADFR) | (1 << ADPS2) | (0 << ADPS1) | (0 << ADPS0); 

    wdt_enable(WDTO_1S); 

    UARTPutString("\r\ncb2net v1.0\r\n\r\n"); 

    commandBufferReset();
    resetRadio();
    prompt(); 

    while (1) {
        wdt_reset();
    } 

}