first upload

This commit is contained in:
Luxferre
2024-11-17 21:00:37 +02:00
commit 2aeda1c291
4 changed files with 570 additions and 0 deletions
+407
View File
@@ -0,0 +1,407 @@
#ifndef _AAIO_H
#define _AAIO_H
/*
AVR All-in-one: a single-header library in pure C (tailored to avr-gcc)
for some typical AVR ATmega series usecases
Tested on: Arduino Mega 2560 (ATmega2560), Arduino Nano (ATmega328P)
Individually selectable features:
* controlling internal LED (overridable to any other pin);
* controlling Nokia 5110 displays;
* reading the state of typical 16-key keypads;
* USB-based serial input/output.
All functions and macros are prefixed in order to avoid collision with
other C libraries.
Created by Luxferre in 2024, released into public domain
*/
/* basic includes */
#include <avr/io.h>
#include <util/delay.h>
/* Predefined profiles for Arduino Mega 2560 and Arduino Nano */
/* All parameters can be overridden before the include */
/* Definitions for Arduino Nano */
#ifdef AAIO_NANO
#ifndef AAIO_LED_PIN
#define AAIO_LED_PIN PB5
#endif
#ifndef AAIO_LED_DDR
#define AAIO_LED_DDR DDRB
#endif
#ifndef AAIO_LED_PORT
#define AAIO_LED_PORT PORTB
#endif
#ifndef AAIO_KEYPAD_DDR
#define AAIO_KEYPAD_DDR DDRD
#endif
#ifndef AAIO_KEYPAD_PORT
#define AAIO_KEYPAD_PORT PORTD
#endif
#ifndef AAIO_KEYPAD_PIN
#define AAIO_KEYPAD_PIN PIND
#endif
/* TODO: change default LCD values for Nano! */
#ifndef AAIO_LCD_PORT
#define AAIO_LCD_PORT PORTL
#endif
#ifndef AAIO_LCD_DDR
#define AAIO_LCD_DDR DDRL
#endif
#ifndef AAIO_LCD_SCE
#define AAIO_LCD_SCE PL4
#endif
#ifndef AAIO_LCD_RST
#define AAIO_LCD_RST PL3
#endif
#ifndef AAIO_LCD_DC
#define AAIO_LCD_DC PL2
#endif
#ifndef AAIO_LCD_DIN
#define AAIO_LCD_DIN PL1
#endif
#ifndef AAIO_LCD_CLK
#define AAIO_LCD_CLK PL0
#endif
#endif
/* Definitions for Arduino Mega 2560 */
#ifdef AAIO_MEGA2560
#ifndef AAIO_LED_PIN
#define AAIO_LED_PIN PB7
#endif
#ifndef AAIO_LED_DDR
#define AAIO_LED_DDR DDRB
#endif
#ifndef AAIO_LED_PORT
#define AAIO_LED_PORT PORTB
#endif
#ifndef AAIO_KEYPAD_DDR
#define AAIO_KEYPAD_DDR DDRA
#endif
#ifndef AAIO_KEYPAD_PORT
#define AAIO_KEYPAD_PORT PORTA
#endif
#ifndef AAIO_KEYPAD_PIN
#define AAIO_KEYPAD_PIN PINA
#endif
#ifndef AAIO_LCD_PORT
#define AAIO_LCD_PORT PORTL
#endif
#ifndef AAIO_LCD_DDR
#define AAIO_LCD_DDR DDRL
#endif
#ifndef AAIO_LCD_SCE
#define AAIO_LCD_SCE PL4
#endif
#ifndef AAIO_LCD_RST
#define AAIO_LCD_RST PL3
#endif
#ifndef AAIO_LCD_DC
#define AAIO_LCD_DC PL2
#endif
#ifndef AAIO_LCD_DIN
#define AAIO_LCD_DIN PL1
#endif
#ifndef AAIO_LCD_CLK
#define AAIO_LCD_CLK PL0
#endif
#endif
/* AAIO_FEATURE_LED: internal LED manipulation */
#ifdef AAIO_FEATURE_LED
/* init the internal LED I/O */
void aaio_led_init() {
AAIO_LED_DDR |= (1 << AAIO_LED_PIN);
}
/* toggle the internal LED */
void aaio_led_toggle() {
AAIO_LED_PORT ^= (1 << AAIO_LED_PIN);
}
/* set the internal LED */
void aaio_led_set(uint8_t v) {
if(v == 0) {
AAIO_LED_PORT &= ~(1 << AAIO_LED_PIN);
} else {
AAIO_LED_PORT |= (1 << AAIO_LED_PIN);
}
}
#endif
/* AAIO_FEATURE_USBUART: USB UART I/O */
/* you should define BAUD before this but it will default to 9600 */
#ifdef AAIO_FEATURE_USBUART
#ifndef BAUD
#define BAUD 9600
#endif
#include <util/setbaud.h>
#include <stdio.h>
/* init UART I/O */
void aaio_uart_init(void) {
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
UCSR0C = (1<<UCSZ01) | (1<<UCSZ00); /* 8-bit data */
UCSR0B = (1<<TXEN0) | (1<<RXEN0); /* enable TX and RX */
}
/* put a character into the bus */
int aaio_uart_putchar(char c, FILE *stream) {
if(c == '\n') aaio_uart_putchar('\r', stream);
loop_until_bit_is_set(UCSR0A, UDRE0);
UDR0 = c;
return 0;
}
/* get a character from the bus */
int aaio_uart_getchar(FILE *stream) {
while(!(UCSR0A & (1 << RXC0)));
return (UDR0);
}
/* get a string of length len from the bus, optionally echoing it back */
int aaio_uart_gets(char *buf, unsigned int len, char echo) {
unsigned int i;
char c;
do {
for(i = 0; i < len - 1; i++) {
c = (char) aaio_uart_getchar(NULL);
if(echo != 0) aaio_uart_putchar(c, NULL);
if(c == '\r' || c == '\n') break;
buf[i] = c;
}
} while (i == 0);
buf[i] = 0; /* guard the buffer */
return i;
}
/* helper utility functions to redirect stdin or stdout */
FILE _aaio_uart_input = FDEV_SETUP_STREAM(NULL, aaio_uart_getchar, _FDEV_SETUP_READ);
FILE _aaio_uart_output = FDEV_SETUP_STREAM(aaio_uart_putchar, NULL, _FDEV_SETUP_WRITE);
void aaio_uart_redirect_stdin() {
stdin = &_aaio_uart_input;
}
void aaio_uart_redirect_stdout() {
stdout = &_aaio_uart_output;
}
#endif
/* AAIO_FEATURE_KEYPAD: 16-key keypad manipulation */
#ifdef AAIO_FEATURE_KEYPAD
#include <avr/pgmspace.h>
/* scan the keyboard and return the associated value */
/* the definition must be stored in PROGMEM */
uint8_t aaio_scankey(const uint8_t keypad_def[4][4]) {
uint8_t row, col, dirmask;
for(col = 0; col < 4; col++) {
AAIO_KEYPAD_DDR = dirmask = 1 << (col + 4);
AAIO_KEYPAD_PORT = 0xf & ~dirmask;
for(row = 0; row < 4; row++) {
_delay_ms(5);
if((AAIO_KEYPAD_PIN & (1<<row)) == 0)
return pgm_read_byte(&keypad_def[col][row]);
}
_delay_ms(5);
}
return 0xff; /* return 0xff if no key press is detected */
}
#endif
/* AAIO_FEATURE_LCD_5110: Nokia 5110 display manipulation */
/* the charset must already be defined in aaio_5110_charset.h */
#ifdef AAIO_FEATURE_LCD_5110
#include "aaio_5110_charset.h"
#ifndef AAIO_LCD_CONTRAST
#define AAIO_LCD_CONTRAST 0x40
#endif
/* Nokia 5110 display data structure */
static struct {
uint8_t screen[504];
uint8_t cursor_x;
uint8_t cursor_y;
} _aaio_lcd = {
.cursor_x = 0,
.cursor_y = 0
};
/* send data to the LCD (in data or command mode) */
static void _aaio_lcd_write(uint8_t byte, uint8_t is_data) {
register uint8_t i;
AAIO_LCD_PORT &= ~(1 << AAIO_LCD_SCE); /* enable the controller */
if(is_data)
AAIO_LCD_PORT |= (1 << AAIO_LCD_DC);
else
AAIO_LCD_PORT &= ~(1 << AAIO_LCD_DC);
for(i = 0; i < 8; i++) {
/* set data pin to byte state */
if((byte >> (7-i)) & 1)
AAIO_LCD_PORT |= (1 << AAIO_LCD_DIN);
else
AAIO_LCD_PORT &= ~(1 << AAIO_LCD_DIN);
/* blink the clock */
AAIO_LCD_PORT |= (1 << AAIO_LCD_CLK);
AAIO_LCD_PORT &= ~(1 << AAIO_LCD_CLK);
}
AAIO_LCD_PORT |= (1 << AAIO_LCD_SCE); /* disable the controller */
}
static void _aaio_lcd_write_cmd(uint8_t cmd) {
_aaio_lcd_write(cmd, 0);
}
static void _aaio_lcd_write_data(uint8_t data) {
_aaio_lcd_write(data, 1);
}
/* init the LCD (must be called before any other function) */
void aaio_lcd_init(void) {
register unsigned i;
/* set pins as output */
AAIO_LCD_DDR |= (1 << AAIO_LCD_SCE);
AAIO_LCD_DDR |= (1 << AAIO_LCD_RST);
AAIO_LCD_DDR |= (1 << AAIO_LCD_DC);
AAIO_LCD_DDR |= (1 << AAIO_LCD_DIN);
AAIO_LCD_DDR |= (1 << AAIO_LCD_CLK);
/* reset the display */
AAIO_LCD_PORT |= (1 << AAIO_LCD_RST);
AAIO_LCD_PORT |= (1 << AAIO_LCD_SCE);
_delay_ms(10);
AAIO_LCD_PORT &= ~(1 << AAIO_LCD_RST);
_delay_ms(70);
AAIO_LCD_PORT |= (1 << AAIO_LCD_RST);
AAIO_LCD_PORT &= ~(1 << AAIO_LCD_SCE); /* enable the controller */
_aaio_lcd_write_cmd(0x21); /* LCD extended commands mode */
_aaio_lcd_write_cmd(0xB0); /* default VOP */
_aaio_lcd_write_cmd(0x04); /* set temperature coefficient */
_aaio_lcd_write_cmd(0x14); /* LCD bias mode 1:48 */
_aaio_lcd_write_cmd(0x20); /* standard commands mode, powered down */
_aaio_lcd_write_cmd(0x09); /* LCD in normal mode */
/* clear LCD RAM */
_aaio_lcd_write_cmd(0x80);
_aaio_lcd_write_cmd(AAIO_LCD_CONTRAST);
for(i = 0; i < 504; i++) _aaio_lcd_write_data(0);
/* activate the LCD */
_aaio_lcd_write_cmd(0x08);
_aaio_lcd_write_cmd(0x0C);
}
/* clear the LCD */
void aaio_lcd_clear(void) {
register unsigned i;
/* set column and row to 0 */
_aaio_lcd_write_cmd(0x80);
_aaio_lcd_write_cmd(0x40);
/* reset the cursor */
_aaio_lcd.cursor_x = 0;
_aaio_lcd.cursor_y = 0;
/* clear everything */
for(i = 0; i < 504; i++) _aaio_lcd.screen[i] = 0;
}
/* power the LCD on/off */
void aaio_lcd_power(uint8_t on) {
_aaio_lcd_write_cmd(on ? 0x20 : 0x24);
}
/* set a pixel */
void aaio_lcd_set_pixel(uint8_t x, uint8_t y, uint8_t value) {
uint8_t *byte = &_aaio_lcd.screen[(y >> 3) * 84 + x];
if(value) *byte |= (1 << (y & 7));
else *byte &= ~(1 << (y & 7));
}
/* write an ASCII character */
void aaio_lcd_write_char(char code, uint8_t scale) {
register uint8_t x, y;
for(x = 0; x < 5*scale; x++)
for(y = 0; y < 7*scale; y++)
if(pgm_read_byte(&CHARSET[code-32][x/scale]) & (1 << y/scale))
aaio_lcd_set_pixel(_aaio_lcd.cursor_x + x, _aaio_lcd.cursor_y + y, 1);
else
aaio_lcd_set_pixel(_aaio_lcd.cursor_x + x, _aaio_lcd.cursor_y + y, 0);
_aaio_lcd.cursor_x += 5*scale + 1;
if(_aaio_lcd.cursor_x >= 84) {
_aaio_lcd.cursor_x = 0;
_aaio_lcd.cursor_y += 7*scale + 1;
}
if(_aaio_lcd.cursor_y >= 48) {
_aaio_lcd.cursor_x = 0;
_aaio_lcd.cursor_y = 0;
}
}
void aaio_lcd_write_string(const char *str, uint8_t scale) {
while(*str) aaio_lcd_write_char(*str++, scale);
}
void aaio_lcd_set_cursor(uint8_t x, uint8_t y) {
_aaio_lcd.cursor_x = x;
_aaio_lcd.cursor_y = y;
}
void aaio_lcd_render(void) {
register unsigned i;
/* set column and row to 0 */
_aaio_lcd_write_cmd(0x80);
_aaio_lcd_write_cmd(0x40);
/* write screen data to the display */
for(i = 0; i < 504; i++) _aaio_lcd_write_data(_aaio_lcd.screen[i]);
}
#endif
#endif
+103
View File
@@ -0,0 +1,103 @@
#ifndef _AAIO_5110_CHARSET_H
#define _AAIO_5110_CHARSET_H
#include <avr/pgmspace.h>
const uint8_t CHARSET[][5] PROGMEM = {
{ 0x00, 0x00, 0x00, 0x00, 0x00 }, // 20 space
{ 0x00, 0x00, 0x5f, 0x00, 0x00 }, // 21 !
{ 0x00, 0x07, 0x00, 0x07, 0x00 }, // 22 "
{ 0x14, 0x7f, 0x14, 0x7f, 0x14 }, // 23 #
{ 0x24, 0x2a, 0x7f, 0x2a, 0x12 }, // 24 $
{ 0x23, 0x13, 0x08, 0x64, 0x62 }, // 25 %
{ 0x36, 0x49, 0x55, 0x22, 0x50 }, // 26 &
{ 0x00, 0x05, 0x03, 0x00, 0x00 }, // 27 '
{ 0x00, 0x1c, 0x22, 0x41, 0x00 }, // 28 (
{ 0x00, 0x41, 0x22, 0x1c, 0x00 }, // 29 )
{ 0x14, 0x08, 0x3e, 0x08, 0x14 }, // 2a *
{ 0x08, 0x08, 0x3e, 0x08, 0x08 }, // 2b +
{ 0x00, 0x50, 0x30, 0x00, 0x00 }, // 2c ,
{ 0x08, 0x08, 0x08, 0x08, 0x08 }, // 2d -
{ 0x00, 0x60, 0x60, 0x00, 0x00 }, // 2e .
{ 0x20, 0x10, 0x08, 0x04, 0x02 }, // 2f /
{ 0x3e, 0x51, 0x49, 0x45, 0x3e }, // 30 0
{ 0x00, 0x42, 0x7f, 0x40, 0x00 }, // 31 1
{ 0x42, 0x61, 0x51, 0x49, 0x46 }, // 32 2
{ 0x21, 0x41, 0x45, 0x4b, 0x31 }, // 33 3
{ 0x18, 0x14, 0x12, 0x7f, 0x10 }, // 34 4
{ 0x27, 0x45, 0x45, 0x45, 0x39 }, // 35 5
{ 0x3c, 0x4a, 0x49, 0x49, 0x30 }, // 36 6
{ 0x01, 0x71, 0x09, 0x05, 0x03 }, // 37 7
{ 0x36, 0x49, 0x49, 0x49, 0x36 }, // 38 8
{ 0x06, 0x49, 0x49, 0x29, 0x1e }, // 39 9
{ 0x00, 0x36, 0x36, 0x00, 0x00 }, // 3a :
{ 0x00, 0x56, 0x36, 0x00, 0x00 }, // 3b ;
{ 0x08, 0x14, 0x22, 0x41, 0x00 }, // 3c <
{ 0x14, 0x14, 0x14, 0x14, 0x14 }, // 3d =
{ 0x00, 0x41, 0x22, 0x14, 0x08 }, // 3e >
{ 0x02, 0x01, 0x51, 0x09, 0x06 }, // 3f ?
{ 0x32, 0x49, 0x79, 0x41, 0x3e }, // 40 @
{ 0x7e, 0x11, 0x11, 0x11, 0x7e }, // 41 A
{ 0x7f, 0x49, 0x49, 0x49, 0x36 }, // 42 B
{ 0x3e, 0x41, 0x41, 0x41, 0x22 }, // 43 C
{ 0x7f, 0x41, 0x41, 0x22, 0x1c }, // 44 D
{ 0x7f, 0x49, 0x49, 0x49, 0x41 }, // 45 E
{ 0x7f, 0x09, 0x09, 0x09, 0x01 }, // 46 F
{ 0x3e, 0x41, 0x49, 0x49, 0x7a }, // 47 G
{ 0x7f, 0x08, 0x08, 0x08, 0x7f }, // 48 H
{ 0x00, 0x41, 0x7f, 0x41, 0x00 }, // 49 I
{ 0x20, 0x40, 0x41, 0x3f, 0x01 }, // 4a J
{ 0x7f, 0x08, 0x14, 0x22, 0x41 }, // 4b K
{ 0x7f, 0x40, 0x40, 0x40, 0x40 }, // 4c L
{ 0x7f, 0x02, 0x0c, 0x02, 0x7f }, // 4d M
{ 0x7f, 0x04, 0x08, 0x10, 0x7f }, // 4e N
{ 0x3e, 0x41, 0x41, 0x41, 0x3e }, // 4f O
{ 0x7f, 0x09, 0x09, 0x09, 0x06 }, // 50 P
{ 0x3e, 0x41, 0x51, 0x21, 0x5e }, // 51 Q
{ 0x7f, 0x09, 0x19, 0x29, 0x46 }, // 52 R
{ 0x46, 0x49, 0x49, 0x49, 0x31 }, // 53 S
{ 0x01, 0x01, 0x7f, 0x01, 0x01 }, // 54 T
{ 0x3f, 0x40, 0x40, 0x40, 0x3f }, // 55 U
{ 0x1f, 0x20, 0x40, 0x20, 0x1f }, // 56 V
{ 0x3f, 0x40, 0x38, 0x40, 0x3f }, // 57 W
{ 0x63, 0x14, 0x08, 0x14, 0x63 }, // 58 X
{ 0x07, 0x08, 0x70, 0x08, 0x07 }, // 59 Y
{ 0x61, 0x51, 0x49, 0x45, 0x43 }, // 5a Z
{ 0x00, 0x7f, 0x41, 0x41, 0x00 }, // 5b [
{ 0x02, 0x04, 0x08, 0x10, 0x20 }, // 5c backslash
{ 0x00, 0x41, 0x41, 0x7f, 0x00 }, // 5d ]
{ 0x04, 0x02, 0x01, 0x02, 0x04 }, // 5e ^
{ 0x40, 0x40, 0x40, 0x40, 0x40 }, // 5f _
{ 0x00, 0x01, 0x02, 0x04, 0x00 }, // 60 `
{ 0x20, 0x54, 0x54, 0x54, 0x78 }, // 61 a
{ 0x7f, 0x48, 0x44, 0x44, 0x38 }, // 62 b
{ 0x38, 0x44, 0x44, 0x44, 0x20 }, // 63 c
{ 0x38, 0x44, 0x44, 0x48, 0x7f }, // 64 d
{ 0x38, 0x54, 0x54, 0x54, 0x18 }, // 65 e
{ 0x08, 0x7e, 0x09, 0x01, 0x02 }, // 66 f
{ 0x0c, 0x52, 0x52, 0x52, 0x3e }, // 67 g
{ 0x7f, 0x08, 0x04, 0x04, 0x78 }, // 68 h
{ 0x00, 0x44, 0x7d, 0x40, 0x00 }, // 69 i
{ 0x20, 0x40, 0x44, 0x3d, 0x00 }, // 6a j
{ 0x7f, 0x10, 0x28, 0x44, 0x00 }, // 6b k
{ 0x00, 0x41, 0x7f, 0x40, 0x00 }, // 6c l
{ 0x7c, 0x04, 0x18, 0x04, 0x78 }, // 6d m
{ 0x7c, 0x08, 0x04, 0x04, 0x78 }, // 6e n
{ 0x38, 0x44, 0x44, 0x44, 0x38 }, // 6f o
{ 0x7c, 0x14, 0x14, 0x14, 0x08 }, // 70 p
{ 0x08, 0x14, 0x14, 0x18, 0x7c }, // 71 q
{ 0x7c, 0x08, 0x04, 0x04, 0x08 }, // 72 r
{ 0x48, 0x54, 0x54, 0x54, 0x20 }, // 73 s
{ 0x04, 0x3f, 0x44, 0x40, 0x20 }, // 74 t
{ 0x3c, 0x40, 0x40, 0x20, 0x7c }, // 75 u
{ 0x1c, 0x20, 0x40, 0x20, 0x1c }, // 76 v
{ 0x3c, 0x40, 0x30, 0x40, 0x3c }, // 77 w
{ 0x44, 0x28, 0x10, 0x28, 0x44 }, // 78 x
{ 0x0c, 0x50, 0x50, 0x50, 0x3c }, // 79 y
{ 0x44, 0x64, 0x54, 0x4c, 0x44 }, // 7a z
{ 0x00, 0x08, 0x36, 0x41, 0x00 }, // 7b {
{ 0x00, 0x00, 0x7f, 0x00, 0x00 }, // 7c |
{ 0x00, 0x41, 0x36, 0x08, 0x00 }, // 7d }
{ 0x10, 0x08, 0x08, 0x10, 0x08 }, // 7e ~
{ 0x00, 0x00, 0x00, 0x00, 0x00 } // 7f
};
#endif
+33
View File
@@ -0,0 +1,33 @@
/* AAIO features to use */
#define AAIO_FEATURE_KEYPAD
#define AAIO_FEATURE_LCD_5110
/* include the AAIO header */
#include "aaio.h"
/* keypad definition */
const static uint8_t keypad_def[4][4] PROGMEM = {
{'1' , '2' , '3' , 'A' },
{'4' , '5' , '6' , 'B' },
{'7' , '8' , '9' , 'C' },
{'*' , '0' , '#' , 'D' }
};
int main(void) {
aaio_lcd_init();
aaio_lcd_clear();
aaio_lcd_write_string("AAIO lib rulez!",1);
aaio_lcd_set_cursor(0, 10);
aaio_lcd_write_string("Nice!", 3);
aaio_lcd_render();
unsigned char c;
for(;;) {
c = aaio_scankey(keypad_def);
if(c != 0xff) {
aaio_lcd_set_cursor(0, 32);
aaio_lcd_write_char(c, 2);
aaio_lcd_render();
}
}
}
+27
View File
@@ -0,0 +1,27 @@
#define BAUD 9600
/* AAIO features to use */
#define AAIO_FEATURE_LED
#define AAIO_FEATURE_USBUART
/* include the AAIO header */
#include "aaio.h"
int main (void) {
aaio_led_init();
aaio_uart_init();
aaio_uart_redirect_stdout();
aaio_uart_redirect_stdin();
char buf[100];
while(1) {
printf("command> ");
aaio_uart_gets(buf, sizeof(buf), 1);
printf("You entered: %s\r\n", buf);
if(buf[0] == '0') aaio_led_set(0);
else if(buf[0] == '1') aaio_led_set(1);
else aaio_led_toggle();
}
return 0;
}