Skip to content

Commit

Permalink
Add sys/avr/lib
Browse files Browse the repository at this point in the history
  • Loading branch information
fornellas committed May 26, 2018
1 parent 981f542 commit 746daf1
Show file tree
Hide file tree
Showing 5 changed files with 149 additions and 161 deletions.
159 changes: 0 additions & 159 deletions sys/avr/at90usb1286/main.c

This file was deleted.

61 changes: 61 additions & 0 deletions sys/avr/hello/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#include <u8g2.h>
#include <util/delay.h>
#include <u8x8_avr.h>

#define P_CPU_NS (1000000000UL / F_CPU)

u8g2_t u8g2;

uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
// Re-use library for delays
if(u8x8_avr_delay(u8x8, msg, arg_int, arg_ptr))
return 1;

switch(msg){
case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8
DDRB |= (1<<0); // CS
DDRB |= (1<<4); // DC
DDRA |= (1<<7); // RESET
break; // can be used to setup pins
case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int
if(arg_int)
PORTB |= (1<<0);
else
PORTB &= ~(1<<0);
break;
case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int
if(arg_int)
PORTB |= (1<<4);
else
PORTB &= ~(1<<4);
break;
case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int
if(arg_int)
PORTA |= (1<<7);
else
PORTA &= ~(1<<7);
break;
default:
u8x8_SetGPIOResult(u8x8, 1); // default return value
break;
}
return 1;
}

int main(void)
{
u8g2_Setup_sh1106_128x64_vcomh0_f(
&u8g2, U8G2_R0,
u8x8_byte_avr_hw_spi,
u8x8_gpio_and_delay
);
u8g2_InitDisplay(&u8g2);
u8g2_SetPowerSave(&u8g2, 0);
while(1){
u8g2_ClearBuffer(&u8g2);
u8g2_SetFont(&u8g2, u8g2_font_ncenB14_tr);
u8g2_DrawStr(&u8g2, 0, 15, "Hello!");
u8g2_SendBuffer(&u8g2);
}
}
6 changes: 4 additions & 2 deletions sys/avr/at90usb1286/makefile → sys/avr/hello/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ SIZE = avr-size
MCU = at90usb1286
F_CPU = 16000000
U8G2_SRC = ../../../csrc
AVR_LIB_SRC = ../lib
CFLAGS = \
-mmcu=$(MCU) \
-DF_CPU=$(F_CPU)UL \
Expand All @@ -12,12 +13,13 @@ CFLAGS = \
-Werror \
-ffunction-sections \
-fdata-sections \
-I$(U8G2_SRC)/
-I$(U8G2_SRC)/ \
-I$(AVR_LIB_SRC)
LDFLAGS = \
-Wl,--gc-sections \
-mmcu=$(MCU)

SRC = $(shell ls $(U8G2_SRC)/*.c) main.c
SRC = $(shell ls $(U8G2_SRC)/*.c) $(shell ls $(AVR_LIB_SRC)/*.c) main.c

OBJ = $(SRC:.c=.o)

Expand Down
79 changes: 79 additions & 0 deletions sys/avr/lib/u8x8_avr.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#include "u8x8_avr.h"
#include <util/delay.h>

#define P_CPU_NS (1000000000UL / F_CPU)

uint8_t u8x8_byte_avr_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) {
uint8_t *data;

switch(msg) {
case U8X8_MSG_BYTE_INIT:
DDRB |= (1 << 1); // CLOCK (SCLK)
DDRB |= (1 << 2); // DATA (MOSI)
SPSR |= (1 << SPI2X); // SPI2X: Double SPI Speed bit
SPCR = ((1 << SPE) | (1 << MSTR)); // Enable / Master
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
case U8X8_MSG_BYTE_SET_DC:
u8x8_gpio_SetDC(u8x8, arg_int);
break;
case U8X8_MSG_BYTE_START_TRANSFER:
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
break;
case U8X8_MSG_BYTE_SEND:
data = (uint8_t *)arg_ptr;
while( arg_int > 0 ) {
SPDR = (uint8_t)*data;
while (!(SPSR & _BV(SPIF)));
data++;
arg_int--;
}
break;
case U8X8_MSG_BYTE_END_TRANSFER:
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
break;
default:
return 0;
}
return 1;
}

uint8_t u8x8_avr_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
{
uint8_t cycles;

switch(msg){
case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second
// At 20Mhz, each cycle is 50ns, the call itself is slower.
break;
case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds
// Approximate best case values...
#define CALL_CYCLES 26UL
#define CALC_CYCLES 4UL
#define RETURN_CYCLES 4UL
#define CYCLES_PER_LOOP 4UL

cycles = (100UL * arg_int) / (P_CPU_NS * CYCLES_PER_LOOP);

if(cycles > CALL_CYCLES + RETURN_CYCLES + CALC_CYCLES) break;

__asm__ __volatile__ (
"1: sbiw %0,1" "\n\t" // 2 cycles
"brne 1b" : "=w" (cycles) : "0" (cycles) // 2 cycles
);
break;
case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds
for(int i=0 ; i < arg_int ; i++)
_delay_us(10);
break;
case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second
for(int i=0 ; i < arg_int ; i++)
_delay_ms(1);
break;
default:
return 0;
}
return 1;
}
5 changes: 5 additions & 0 deletions sys/avr/lib/u8x8_avr.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#include <u8g2.h>
#include <stdint.h>

uint8_t u8x8_byte_avr_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
uint8_t u8x8_avr_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);

0 comments on commit 746daf1

Please sign in to comment.