Here is the code for the microcontroller (ATMEGA256RFR2, running at 3.3 V)
#include <avr/io.h>
// LOW.CLKDIV8 is unchecked, and LOW.CKSEL_SUT is Transceiver Oscillator; Start-up time: 16K CK + 65 ms
#define F_CPU 16000000UL
#include <util/delay.h>
#include <avr/interrupt.h>
#include "main.h"
// Place to store a string for USART communication
static char temp_string[64];
// Simple routine to output a serial string to the UART
void print_serial(const char * const print_string) {
uint8_t temp = 0;
while (temp < strlen(print_string)) {
if ((UCSR1A & 0x20) == 0) {
// Do nothing
_delay_us(10);
}
else {
// Send a byte
UDR1 = (uint8_t) print_string[temp];
temp = temp + 1;
}
}
// Send ASCII 13 and 10
temp = 0;
while (temp < 2) {
if ((UCSR1A & 0x20) == 0) {
// Do nothing
_delay_us(10);
}
else {
if (temp == 0) {
UDR1 = 13;
}
if (temp == 1) {
UDR1 = 10;
}
temp = temp + 1;
}
}
}
// Place to store the user input
static uint8_t rx_in_buffer[64];
// The count of user input
static uint8_t rx_in_buffer_count = 0;
ISR(USART1_RX_vect) {
// Read the character from the buffer
uint8_t temp = UDR1;
// Put the character in the buffer
rx_in_buffer[rx_in_buffer_count] = temp;
// Increment the count
rx_in_buffer_count = rx_in_buffer_count + 1;
// Count has to be less than 63
if (rx_in_buffer_count > 63) {
rx_in_buffer_count = 63;
}
// If the character is carriage return, process the command
if (temp == 13) {
go_process_command();
}
}
void go_process_command() {
// Print some characters in the buffer
//snprintf(temp_string, 64, "Rx: %d, %d, %d, %d, %d, %d", rx_in_buffer[0], rx_in_buffer[1], rx_in_buffer[2], rx_in_buffer[3], rx_in_buffer[4], rx_in_buffer[5]);
//print_serial(temp_string);
// The read command
if ((rx_in_buffer[0] == 114) || (rx_in_buffer[0] == 82)) { // The read command, r or R, expect decimal, for example, expect r72 to read 0x48, OCR0B
//print_serial("r/R");
// The location of the carriage return
uint8_t ind_13 = 0;
// Find character 13
for (uint8_t ii = 1; ii < 64; ii++) {
if (rx_in_buffer[ii] == 13) {
ind_13 = ii;
break;
}
}
// Where character 13 was found
//snprintf(temp_string, 64, "Char13: %d", ind_13);
//print_serial(temp_string);
// For processing the register address (convert ASCII characters to addr)
uint8_t found_it = 0;
uint16_t addr = 0;
uint16_t pow_10 = 1;
// If ind_13 was found, build up addr
if (ind_13 > 1) {
for (uint8_t ii = (ind_13 - 1); ii > 0; ii--) {
if ((rx_in_buffer[ii] >= 48) || (rx_in_buffer[ii] <= 57)) {
addr = addr + (rx_in_buffer[ii] - 48) * pow_10;
pow_10 = pow_10 * 10;
found_it = 1;
}
else { // Unexpected character
found_it = 0;
break;
}
}
}
// Print the address and whether the parsing was as expected
//snprintf(temp_string, 64, "addr: %u, found_it: %d", addr, found_it);
//print_serial(temp_string);
// Print the register value
if (found_it == 1) {
volatile uint8_t * reg_addr = (uint8_t *) addr;
uint8_t temp_value = *reg_addr;
snprintf(temp_string, 64, "Reg: %u = %d, %x", addr, temp_value, temp_value);
print_serial(temp_string);
}
}
else if ((rx_in_buffer[0] == 119) || (rx_in_buffer[0] == 87)) { // The write command, w or W, for example, expect w72=4
//print_serial("w/W");
// The location of the carriage return
uint8_t ind_13 = 0;
// Find character 13, carriage return
for (uint8_t ii = 1; ii < 64; ii++) {
if (rx_in_buffer[ii] == 13) {
ind_13 = ii;
break;
}
}
// The location of the =
uint8_t ind_eq = 0;
for (uint8_t ii = 1; ii < 64; ii++) {
if (rx_in_buffer[ii] == 61) {
ind_eq = ii;
break;
}
}
// Where character = and 13 were found
//snprintf(temp_string, 64, "Char=: %d, 13: %d", ind_eq, ind_13);
//print_serial(temp_string);
if ((ind_eq > 1) && ((ind_eq + 1) < ind_13)) {
// For processing the register address (convert ASCII characters to addr)
uint8_t found_it = 0;
uint16_t addr = 0;
uint16_t pow_10 = 1;
// Get the register address
for (uint8_t ii = (ind_eq - 1); ii > 0; ii--) {
if ((rx_in_buffer[ii] >= 48) || (rx_in_buffer[ii] <= 57)) {
addr = addr + (rx_in_buffer[ii] - 48) * pow_10;
pow_10 = pow_10 * 10;
found_it = 1;
}
else { // Unexpected character
found_it = 0;
break;
}
}
// Print the address and whether the parsing was as expected
//snprintf(temp_string, 64, "addr: %u, found_it: %d", addr, found_it);
//print_serial(temp_string);
// Attempt to set the register value
if (found_it == 1) {
// Print the current value of the register
volatile uint8_t * reg_addr = (uint8_t *) addr;
//snprintf(temp_string, 64, "Reg: %u = %d, old value", addr, *reg_addr);
//print_serial(temp_string);
// Now, parse the value
found_it = 0;
pow_10 = 1;
uint16_t in_val = 0;
// Get the value
for (uint8_t ii = (ind_13 - 1); ii > ind_eq; ii--) {
if ((rx_in_buffer[ii] >= 48) || (rx_in_buffer[ii] <= 57)) {
in_val = in_val + (rx_in_buffer[ii] - 48) * pow_10;
pow_10 = pow_10 * 10;
found_it = 1;
}
else { // Unexpected character
found_it = 0;
break;
}
}
// Print the value and whether the parsing was as expected
//snprintf(temp_string, 64, "New value: %d, found_it: %d", in_val, found_it);
//print_serial(temp_string);
if ((found_it == 1) && (in_val <= 255)) {
// Write the value
*reg_addr = (uint8_t) in_val;
snprintf(temp_string, 64, "Reg: %u = %d, new value", addr, in_val);
print_serial(temp_string);
}
}
}
}
else {
print_serial("Command error");
}
// Last things to do
// Set the buffer count to 0
rx_in_buffer_count = 0;
// Clear the buffer
for (uint8_t ii = 0; ii < 64; ii++) {
rx_in_buffer[ii] = 0;
}
}
int main(void)
{
// Get the UART ready
UBRR1H = 0; // Oscillator is 16 MHz, 9600 is decimal 103
UBRR1L = 103;
// Enable Rx interrupt, enable Rx, enable Tx
UCSR1B = (1 << 7) | (1 << 4) | (1 << 3); // Enable RXCIE1, Enable Tx and Rx
UCSR1C = (0 << 6) | (0 << 4) | (0 << 3) | (3 << 1); // Asynchronous, No parity, 8 bits
_delay_ms(1);
// Enable interrupts
SREG |= (1 << 7);
// PB4 is the USER_LED, labeled LED0 on the ATMEGA256RFR2 xplained board
DDRB = (1 << 4);
// PG0 is for chip select
DDRG = 1;
PORTG = 1;
// Use USART0 as SPI
UBRR0L = 0; // Set to 0 first
UBRR0H = 0;
DDRE = (1 << 2); // Set XCK0 to output
// UDORD0 - MSB first, UCPHA0 , UCPOL0
UCSR0C = (3 << 6) | (0 << 2) | (0 << 1) | (0);
// Enable Rx and Tx
UCSR0B = (1 << 4) | (1 << 3);
// Now set the baud rate
UBRR0L = 3; // Target 2 Mbps (assuming 16 MHz CPU clock)
UBRR0H = 0;
_delay_ms(1);
// Echo to the user to start
print_serial("Go time!");
while (1)
{
// Blink the LED while waiting for the interrupt
PORTB |= (1 << 4);
_delay_ms(500);
PORTB &= 255 - (1 << 4);
_delay_ms(500);
}
}
Here is the header file
#ifndef MAIN_H_
#define MAIN_H_
// Serial port stuff
#include <string.h>
#include <stdio.h>
// Printing a string to the serial port
void print_serial(const char * const print_string);
// Given an input array, process the command
void go_process_command();
#endif // MAIN_H_
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.