mirror of
https://github.com/Valeh2012/PersonalVotingMachine
synced 2025-12-08 18:15:11 +02:00
first commit
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=adc_dma_tim
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
U8G2INC:=../../../../csrc/
|
||||
U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
|
||||
Example for the STM32L031 Eval Board with 128x64 OLED at PA13/PA14
|
||||
|
||||
LED: PA1 / AF2: TIM2_CH2
|
||||
VarRes: PA5 / ADC CH5
|
||||
|
||||
ch0 PA0 pin 6
|
||||
ch1 PA1 pin 7
|
||||
ch2 PA2 pin 8
|
||||
ch3 PA3 pin 9
|
||||
ch4 PA4 pin 10
|
||||
ch5 PA5 pin 11
|
||||
ch6 PA6 pin 12
|
||||
ch7 PA7 pin 13
|
||||
ch8 PB0 -
|
||||
ch9 PB1 pin 14
|
||||
|
||||
|
||||
ch 0..15: GPIO
|
||||
ch 16: ???
|
||||
ch 17: vref (bandgap)
|
||||
ch18: temperature sensor
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
/*=======================================================================*/
|
||||
/* external functions */
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
/*=======================================================================*/
|
||||
/* global variables */
|
||||
|
||||
u8x8_t u8x8; // u8x8 object
|
||||
uint8_t u8x8_x, u8x8_y; // current position on the screen
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
}
|
||||
|
||||
/* return current system time in milliseconds */
|
||||
unsigned long getUpTime(void)
|
||||
{
|
||||
unsigned long sys_tick_cycle = SysTick->LOAD+1;
|
||||
unsigned long millis_per_sys_tick_irq;
|
||||
|
||||
/*
|
||||
the simple approach
|
||||
millis_per_sys_tick_irq = (sys_tick_cycle*1000UL)/SystemCoreClock;
|
||||
may overflow for large values of SysTick->LOAD. Instead this is better because SystemCoreClock is always
|
||||
very large:
|
||||
millis_per_sys_tick_irq = sys_tick_cycle/(SystemCoreClock/1000);
|
||||
|
||||
*/
|
||||
|
||||
millis_per_sys_tick_irq = sys_tick_cycle/(SystemCoreClock/1000);
|
||||
return millis_per_sys_tick_irq * SysTickCount;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void setHSIClock()
|
||||
{
|
||||
|
||||
/* test if the current clock source is something else than HSI */
|
||||
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
{
|
||||
/* enable HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
/* wait until HSI becomes ready */
|
||||
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
|
||||
;
|
||||
|
||||
/* enable the HSI "divide by 4" bit */
|
||||
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
|
||||
/* wait until the "divide by 4" flag is enabled */
|
||||
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
|
||||
;
|
||||
|
||||
|
||||
/* then use the HSI clock */
|
||||
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
|
||||
|
||||
/* wait until HSI clock is used */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PLL */
|
||||
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
|
||||
/* wait until PLL is inactive */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) != 0)
|
||||
;
|
||||
|
||||
/* set latency to 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* At this point the HSI runs with 4 MHz */
|
||||
/* Multiply by 16 device by 2 --> 32 MHz */
|
||||
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
|
||||
|
||||
/* enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* wait until the PLL is ready */
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
;
|
||||
|
||||
/* use the PLL has clock source */
|
||||
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
|
||||
/* wait until the PLL source is active */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
|
||||
SystemCoreClockUpdate(); /* Update SystemCoreClock global variable */
|
||||
}
|
||||
|
||||
/*
|
||||
Enable several power regions: PWR, GPIOA
|
||||
|
||||
This must be executed after each reset.
|
||||
*/
|
||||
void startUp(void)
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface (PWR) */
|
||||
PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR and RTC */
|
||||
|
||||
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/* u8x8 display procedures */
|
||||
|
||||
void initDisplay(void)
|
||||
{
|
||||
u8x8_Setup(&u8x8, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0);
|
||||
u8x8_InitDisplay(&u8x8);
|
||||
u8x8_ClearDisplay(&u8x8);
|
||||
u8x8_SetPowerSave(&u8x8, 0);
|
||||
u8x8_SetFont(&u8x8, u8x8_font_amstrad_cpc_extended_r);
|
||||
u8x8_x = 0;
|
||||
u8x8_y = 0;
|
||||
}
|
||||
|
||||
|
||||
void outChar(uint8_t c)
|
||||
{
|
||||
if ( u8x8_x >= u8x8_GetCols(&u8x8) )
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y++;
|
||||
}
|
||||
u8x8_DrawGlyph(&u8x8, u8x8_x, u8x8_y, c);
|
||||
u8x8_x++;
|
||||
}
|
||||
|
||||
void outStr(const char *s)
|
||||
{
|
||||
while( *s )
|
||||
outChar(*s++);
|
||||
}
|
||||
|
||||
void outHexHalfByte(uint8_t b)
|
||||
{
|
||||
b &= 0x0f;
|
||||
if ( b < 10 )
|
||||
outChar(b+'0');
|
||||
else
|
||||
outChar(b+'a'-10);
|
||||
}
|
||||
|
||||
void outHex8(uint8_t b)
|
||||
{
|
||||
outHexHalfByte(b >> 4);
|
||||
outHexHalfByte(b);
|
||||
}
|
||||
|
||||
void outHex16(uint16_t v)
|
||||
{
|
||||
outHex8(v>>8);
|
||||
outHex8(v);
|
||||
}
|
||||
|
||||
void outDec16(uint16_t v)
|
||||
{
|
||||
outStr(u8x8_u16toa(v, 5));
|
||||
}
|
||||
|
||||
void outHex32(uint32_t v)
|
||||
{
|
||||
outHex16(v>>16);
|
||||
outHex16(v);
|
||||
}
|
||||
|
||||
void setRow(uint8_t r)
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y = r;
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/*
|
||||
ADC defaults:
|
||||
- Clock source: ADCCLK (HSI16) (ADC_CFGR2)
|
||||
- ADC clock prescaler: divide by 1 (ADC_CCR)
|
||||
- software enabled start
|
||||
- right alignment
|
||||
- 12 Bit resolution
|
||||
- No interrupts enabled
|
||||
- 1.5 clock cycles sampling time (fastest)
|
||||
|
||||
Calibration:
|
||||
better ignore ADC_ISR_EOCAL and use the ADC_CR_ADCAL flag only.
|
||||
otherwise some extra NOPs are required after calibration
|
||||
|
||||
Time
|
||||
(1.5 + 12.5) / 4 MHz = 3.5us --> 286KHz
|
||||
x16 oversampling: 56us --> 17.9KHz
|
||||
*/
|
||||
|
||||
|
||||
void initADC(uint8_t ch)
|
||||
{
|
||||
|
||||
/* ADC Clock Enable */
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADCEN; /* enable ADC clock */
|
||||
__NOP(); __NOP(); /* extra delay for clock stabilization required? */
|
||||
|
||||
/* ADC Reset */
|
||||
|
||||
RCC->APB2RSTR |= RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); __NOP(); /* let us wait for some time */
|
||||
RCC->APB2RSTR &= ~RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); __NOP(); /* let us wait for some time */
|
||||
|
||||
/* CALIBRATION */
|
||||
|
||||
ADC1->CR |= ADC_CR_ADCAL; /* start calibration */
|
||||
while ((ADC1->CR & ADC_CR_ADCAL) != 0) /* wait for clibration finished */
|
||||
{
|
||||
}
|
||||
|
||||
/* ENABLE ADC */
|
||||
|
||||
ADC1->ISR |= ADC_ISR_ADRDY; /* clear ready flag */
|
||||
ADC1->CR |= ADC_CR_ADEN; /* enable ADC */
|
||||
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* wait for ADC */
|
||||
{
|
||||
}
|
||||
|
||||
/* CONFIGURE ADC */
|
||||
|
||||
ADC1->CFGR1 |= ADC_CFGR1_CONT; /* continues mode */
|
||||
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSR_0; /* 011 oversampling ration x16 */
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSR_1;
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSS_2; /* shift 4 bits (because of x16 oversampling) */
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSE; /* enable oversampling */
|
||||
|
||||
ADC1->CHSELR = 1<<ch; /* Select channel */
|
||||
//ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* Select a sampling mode of 111 (very slow)*/
|
||||
|
||||
/* START CONVERSION */
|
||||
|
||||
ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversion */
|
||||
while ((ADC1->ISR & ADC_ISR_EOC) == 0) /* wait end of first conversion */
|
||||
{
|
||||
}
|
||||
|
||||
//data is available in ADC1->DR;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void initTIM(void)
|
||||
{
|
||||
|
||||
/* enable clock for TIM2 */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||
//RCC->CFGR |= RCC_CFGR_PPRE1_2;
|
||||
//RCC->CFGR |= RCC_CFGR_PPRE1_1;
|
||||
//RCC->CFGR |= RCC_CFGR_PPRE1_0;
|
||||
/*cenable clock for GPIOA */
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP(); __NOP(); /* extra delay for clock stabilization required? */
|
||||
|
||||
/* configure GPIOA PA1 for TIM2 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE1; /* clear mode for PA1 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE1_1; /* alt fn */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1; /* push-pull */
|
||||
GPIOA->AFR[0] &= ~(15<<4); /* Clear Alternate Function PA1 */
|
||||
GPIOA->AFR[0] |= 2<<4; /* AF2 Alternate Function PA1 */
|
||||
|
||||
/* TIM2 configure */
|
||||
/* disable all interrupts */
|
||||
//TIM2->DIER = 0; /* 0 is reset default value */
|
||||
|
||||
/* clear everything, including the "Update disable" flag, so that updates */
|
||||
/* are generated */
|
||||
// TIM2->CR1 = 0; /* 0 is reset default value */
|
||||
//TIM2->CR1 |= TIM_CR1_ARPE; // ARR is not modified so constant update is ok
|
||||
/* Update request by manual UG bit setting or slave controller */
|
||||
/* both is not required here */
|
||||
/* so, update request by couter over/underflow remains */
|
||||
//TIM2->CR1 |= TIM_CR1_URS; /* only udf/ovf generae events */
|
||||
|
||||
|
||||
TIM2->ARR = 4096; /* total cycle count */
|
||||
TIM2->CCR2 = 1024; /* duty cycle */
|
||||
//TIM2->CCMR1 &= ~TIM_CCMR1_OC2CE; /* disable clear output compare 2 **/
|
||||
TIM2->CCMR1 |= TIM_CCMR1_OC2M; /* all 3 bits set: PWM Mode 2 */
|
||||
//TIM2->CCMR1 &= ~TIM_CCMR1_OC1M_0; /* 110: PWM Mode 1 */
|
||||
TIM2->CCMR1 |= TIM_CCMR1_OC2PE; /* preload enable CCR2 is preloaded*/
|
||||
// TIM2->CCMR1 &= ~TIM_CCMR1_OC2FE; /* fast disable (reset default) */
|
||||
// TIM2->CCMR1 &= ~TIM_CCMR1_CC2S; /* configure cc2 as output (this is reset default) */
|
||||
|
||||
|
||||
//TIM2->EGR |= TIM_EGR_CC2G; /* capture event cc2 */
|
||||
TIM2->CCER |= TIM_CCER_CC2E; /* set output enable */
|
||||
//TIM2->CCER |= TIM_CCER_CC2P; /* polarity 0: normal (reset default) / 1: inverted*/
|
||||
|
||||
TIM2->CR1 |= TIM_CR1_CEN; /* counter enable */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
copy from ADC1->DR to TIM2->CCR2
|
||||
ADC DMA requests can be used with DMA Channel 1
|
||||
*/
|
||||
void initDMA()
|
||||
{
|
||||
|
||||
RCC->AHBENR |= RCC_AHBENR_DMAEN; /* enable DMA clock */
|
||||
__NOP(); __NOP(); /* extra delay for clock stabilization required? */
|
||||
|
||||
/* defaults:
|
||||
- 8 Bit access
|
||||
- read from peripheral
|
||||
- none-circular mode
|
||||
- no increment mode
|
||||
*/
|
||||
|
||||
DMA1_Channel1->CCR |= DMA_CCR_MSIZE_0; /* 16 bit access */
|
||||
DMA1_Channel1->CCR |= DMA_CCR_PSIZE_0; /* 16 bit access */
|
||||
DMA1_Channel1->CCR |= DMA_CCR_CIRC; /* circular mode */
|
||||
|
||||
DMA1_Channel1->CNDTR = 1; /* one data, then repeat (circular mode) */
|
||||
DMA1_Channel1->CPAR = (uint32_t)&(ADC1->DR); /* source value */
|
||||
DMA1_Channel1->CMAR = (uint32_t)&(TIM2->CCR2); /* destination register */
|
||||
|
||||
DMA1_CSELR->CSELR &= ~DMA_CSELR_C1S; /* 0000: select ADC for DMA CH 1 (this is reset default) */
|
||||
|
||||
DMA1_Channel1->CCR |= DMA_CCR_EN; /* enable */
|
||||
|
||||
ADC1->CFGR1 |= ADC_CFGR1_DMACFG; /* never stop DMA requests */
|
||||
ADC1->CFGR1 |= ADC_CFGR1_DMAEN; /* enable DMA requests for ADC */
|
||||
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void main()
|
||||
{
|
||||
uint32_t start, diff;
|
||||
|
||||
setHSIClock(); /* enable 32 MHz Clock */
|
||||
startUp(); /* enable systick irq and several power regions */
|
||||
initDisplay(); /* aktivate display */
|
||||
|
||||
/* setup ADC controlled PWM */
|
||||
|
||||
initADC(5); /* read from channel 5 (pin 11) */
|
||||
initTIM();
|
||||
initDMA();
|
||||
|
||||
/* rest of the code just shows the current ADC value on the OLED */
|
||||
|
||||
setRow(0); outStr("ADC DMA TIM Test");
|
||||
setRow(2); outStr("ch5 pin11: ");
|
||||
setRow(5); outStr("cycle: ");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
setRow(3); outHex16(ADC1->DR);
|
||||
|
||||
TIM2->SR &= ~TIM_SR_CC2IF; /* clear irq flag */
|
||||
while ( (TIM2->SR & TIM_SR_CC2IF) == 0 )
|
||||
;
|
||||
start = SysTick->VAL;
|
||||
|
||||
TIM2->SR &= ~TIM_SR_CC2IF; /* clear irq flag */
|
||||
while ( (TIM2->SR & TIM_SR_CC2IF) == 0 )
|
||||
;
|
||||
diff = start-SysTick->VAL;
|
||||
setRow(6); outHex32(diff);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
u8x8cb.c
|
||||
|
||||
STM32L031
|
||||
|
||||
PA13: Clock
|
||||
PA14: Data
|
||||
Both lines have a pullup resistor
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* only support for software I2C*/
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no open drain for PA10 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed for PA10 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown for PA10 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA9 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no open drain for PA9 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA9 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA9 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
/* not required for SW I2C */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
delay_micro_seconds(arg_int*1000UL);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_I2C:
|
||||
/* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
|
||||
delay_micro_seconds(arg_int<=2?5:1);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_3; /* atomic clr PA9 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9: input mode */
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr PA10 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
// input mode
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10: input mode */
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case U8X8_MSG_GPIO_MENU_SELECT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_NEXT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_PREV:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN));
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_MENU_HOME:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN));
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=adc_test
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
U8G2INC:=../../../../csrc/
|
||||
U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
129
basic-setup/components/u8g2/sys/arm/stm32l031x6/adc_test/delay.c
Normal file
129
basic-setup/components/u8g2/sys/arm/stm32l031x6/adc_test/delay.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
328
basic-setup/components/u8g2/sys/arm/stm32l031x6/adc_test/main.c
Normal file
328
basic-setup/components/u8g2/sys/arm/stm32l031x6/adc_test/main.c
Normal file
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
|
||||
Example for the STM32L031 Eval Board with 128x64 OLED at PA13/PA14
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
/*=======================================================================*/
|
||||
/* external functions */
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
/*=======================================================================*/
|
||||
/* global variables */
|
||||
|
||||
u8x8_t u8x8; // u8x8 object
|
||||
uint8_t u8x8_x, u8x8_y; // current position on the screen
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setHSIClock()
|
||||
{
|
||||
|
||||
/* test if the current clock source is something else than HSI */
|
||||
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
{
|
||||
/* enable HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
/* wait until HSI becomes ready */
|
||||
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
|
||||
;
|
||||
|
||||
/* enable the HSI "divide by 4" bit */
|
||||
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
|
||||
/* wait until the "divide by 4" flag is enabled */
|
||||
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
|
||||
;
|
||||
|
||||
|
||||
/* then use the HSI clock */
|
||||
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
|
||||
|
||||
/* wait until HSI clock is used */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PLL */
|
||||
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
|
||||
/* wait until PLL is inactive */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) != 0)
|
||||
;
|
||||
|
||||
/* set latency to 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* At this point the HSI runs with 4 MHz */
|
||||
/* Multiply by 16 device by 2 --> 32 MHz */
|
||||
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
|
||||
|
||||
/* enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* wait until the PLL is ready */
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
;
|
||||
|
||||
/* use the PLL has clock source */
|
||||
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
|
||||
/* wait until the PLL source is active */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
|
||||
SystemCoreClockUpdate(); /* Update SystemCoreClock global variable */
|
||||
}
|
||||
|
||||
/*
|
||||
Enable several power regions: PWR, GPIOA
|
||||
|
||||
This must be executed after each reset.
|
||||
*/
|
||||
void startUp(void)
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface (PWR) */
|
||||
PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR and RTC */
|
||||
|
||||
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/* u8x8 display procedures */
|
||||
|
||||
void initDisplay(void)
|
||||
{
|
||||
u8x8_Setup(&u8x8, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0);
|
||||
u8x8_InitDisplay(&u8x8);
|
||||
u8x8_ClearDisplay(&u8x8);
|
||||
u8x8_SetPowerSave(&u8x8, 0);
|
||||
u8x8_SetFont(&u8x8, u8x8_font_amstrad_cpc_extended_r);
|
||||
u8x8_x = 0;
|
||||
u8x8_y = 0;
|
||||
}
|
||||
|
||||
|
||||
void outChar(uint8_t c)
|
||||
{
|
||||
if ( u8x8_x >= u8x8_GetCols(&u8x8) )
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y++;
|
||||
}
|
||||
u8x8_DrawGlyph(&u8x8, u8x8_x, u8x8_y, c);
|
||||
u8x8_x++;
|
||||
}
|
||||
|
||||
void outStr(const char *s)
|
||||
{
|
||||
while( *s )
|
||||
outChar(*s++);
|
||||
}
|
||||
|
||||
void outHexHalfByte(uint8_t b)
|
||||
{
|
||||
b &= 0x0f;
|
||||
if ( b < 10 )
|
||||
outChar(b+'0');
|
||||
else
|
||||
outChar(b+'a'-10);
|
||||
}
|
||||
|
||||
void outHex8(uint8_t b)
|
||||
{
|
||||
outHexHalfByte(b >> 4);
|
||||
outHexHalfByte(b);
|
||||
}
|
||||
|
||||
void outHex16(uint16_t v)
|
||||
{
|
||||
outHex8(v>>8);
|
||||
outHex8(v);
|
||||
}
|
||||
|
||||
void outHex32(uint32_t v)
|
||||
{
|
||||
outHex16(v>>16);
|
||||
outHex16(v);
|
||||
}
|
||||
|
||||
void setRow(uint8_t r)
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y = r;
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void initADC(void)
|
||||
{
|
||||
//__disable_irq();
|
||||
|
||||
/* ADC Clock Enable */
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADCEN; /* enable ADC clock */
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* ADC Reset */
|
||||
|
||||
RCC->APB2RSTR |= RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
RCC->APB2RSTR &= ~RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* ADC Basic Setup */
|
||||
|
||||
ADC1->IER = 0; /* do not allow any interrupts */
|
||||
ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* select HSI16 clock */
|
||||
|
||||
ADC1->CR |= ADC_CR_ADVREGEN; /* enable ADC voltage regulator, probably not required, because this is automatically activated */
|
||||
ADC->CCR |= ADC_CCR_VREFEN; /* Wake-up the VREFINT */
|
||||
ADC->CCR |= ADC_CCR_TSEN; /* Wake-up the temperature sensor */
|
||||
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* CALIBRATION */
|
||||
|
||||
if ((ADC1->CR & ADC_CR_ADEN) != 0) /* clear ADEN flag if required */
|
||||
{
|
||||
/* is this correct, i think we must use the disable flag here */
|
||||
ADC1->CR &= (uint32_t)(~ADC_CR_ADEN);
|
||||
}
|
||||
ADC1->CR |= ADC_CR_ADCAL; /* start calibration */
|
||||
while ((ADC1->ISR & ADC_ISR_EOCAL) == 0) /* wait for clibration finished */
|
||||
{
|
||||
}
|
||||
ADC1->ISR |= ADC_ISR_EOCAL; /* clear the status flag, by writing 1 to it */
|
||||
__NOP(); /* not sure why, but some nop's are required here, at least 4 of them */
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
/* ENABLE ADC */
|
||||
|
||||
ADC1->ISR |= ADC_ISR_ADRDY; /* clear ready flag */
|
||||
ADC1->CR |= ADC_CR_ADEN; /* enable ADC */
|
||||
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* wait for ADC */
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ch0 PA0 pin 6
|
||||
ch1 PA1 pin 7
|
||||
ch2 PA2 pin 8
|
||||
ch3 PA3 pin 9
|
||||
ch4 PA4 pin 10
|
||||
ch5 PA5 pin 11
|
||||
ch6 PA6 pin 12
|
||||
ch7 PA7 pin 13
|
||||
ch8 PB0 -
|
||||
ch9 PB1 pin 14
|
||||
|
||||
|
||||
ch 0..15: GPIO
|
||||
ch 16: ???
|
||||
ch 17: vref (bandgap)
|
||||
ch18: temperature sensor
|
||||
|
||||
returns 12 bit result, right aligned
|
||||
*/
|
||||
uint16_t getADC(uint8_t ch)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t i;
|
||||
|
||||
/* CONFIGURE ADC */
|
||||
|
||||
ADC1->CFGR1 &= ~ADC_CFGR1_EXTEN; /* software enabled conversion start */
|
||||
ADC1->CFGR1 &= ~ADC_CFGR1_ALIGN; /* right alignment */
|
||||
ADC1->CFGR1 &= ~ADC_CFGR1_RES; /* 12 bit resolution */
|
||||
ADC1->CHSELR = 1<<ch; /* Select channel */
|
||||
ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* Select a sampling mode of 111 (very slow)*/
|
||||
|
||||
/* DO CONVERSION */
|
||||
|
||||
data = 0;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
|
||||
ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversion */
|
||||
while ((ADC1->ISR & ADC_ISR_EOC) == 0) /* wait end of conversion */
|
||||
{
|
||||
}
|
||||
data += ADC1->DR; /* get ADC result and clear the ISR_EOC flag */
|
||||
}
|
||||
data >>= 3;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void main()
|
||||
{
|
||||
uint16_t adc_value;
|
||||
uint16_t i;
|
||||
|
||||
setHSIClock(); /* enable 32 MHz Clock */
|
||||
startUp(); /* enable systick irq and several power regions */
|
||||
initDisplay(); /* aktivate display */
|
||||
initADC();
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE1; /* clear mode for PA1 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE1_0; /* Output mode for PA1 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1; /* no Push/Pull for PA1 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED1; /* low speed for PA1 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD1; /* no pullup/pulldown for PA1 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_1; /* atomic set PA1 */
|
||||
|
||||
setRow(0); outStr("ADC Test");
|
||||
|
||||
setRow(2); outStr("ch5 pin11: ");
|
||||
setRow(3); outHex16(getADC(5));
|
||||
setRow(4); outStr("bandgap: ");
|
||||
setRow(5); outHex16(getADC(17));
|
||||
setRow(6); outStr("temp: ");
|
||||
setRow(7); outHex16(getADC(18));
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
for( i = 0; i < 2000; i++ )
|
||||
{
|
||||
adc_value = getADC(5);
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_1; /* atomic clr PA1 */
|
||||
delay_system_ticks(0x1000 - adc_value);
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_1; /* atomic set PA1 */
|
||||
delay_system_ticks(adc_value);
|
||||
}
|
||||
|
||||
setRow(3); outHex16(adc_value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
u8x8cb.c
|
||||
|
||||
STM32L031
|
||||
|
||||
PA13: Clock
|
||||
PA14: Data
|
||||
Both lines have a pullup resistor
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* only support for software I2C*/
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no open drain for PA10 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed for PA10 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown for PA10 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA9 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no open drain for PA9 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA9 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA9 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
/* not required for SW I2C */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
delay_micro_seconds(arg_int*1000UL);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_I2C:
|
||||
/* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
|
||||
delay_micro_seconds(arg_int<=2?5:1);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_3; /* atomic clr PA9 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9: input mode */
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr PA10 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
// input mode
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10: input mode */
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case U8X8_MSG_GPIO_MENU_SELECT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_NEXT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_PREV:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN));
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_MENU_HOME:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN));
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=adc_tim_continues_test
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
U8G2INC:=../../../../csrc/
|
||||
U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
|
||||
Example for the STM32L031 Eval Board with 128x64 OLED at PA13/PA14
|
||||
|
||||
LED: PA1 / AF2: TIM2_CH2
|
||||
VarRes: PA5 / ADC CH5
|
||||
|
||||
ch0 PA0 pin 6
|
||||
ch1 PA1 pin 7
|
||||
ch2 PA2 pin 8
|
||||
ch3 PA3 pin 9
|
||||
ch4 PA4 pin 10
|
||||
ch5 PA5 pin 11
|
||||
ch6 PA6 pin 12
|
||||
ch7 PA7 pin 13
|
||||
ch8 PB0 -
|
||||
ch9 PB1 pin 14
|
||||
|
||||
|
||||
ch 0..15: GPIO
|
||||
ch 16: ???
|
||||
ch 17: vref (bandgap)
|
||||
ch18: temperature sensor
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
/*=======================================================================*/
|
||||
/* external functions */
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
/*=======================================================================*/
|
||||
/* global variables */
|
||||
|
||||
u8x8_t u8x8; // u8x8 object
|
||||
uint8_t u8x8_x, u8x8_y; // current position on the screen
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setHSIClock()
|
||||
{
|
||||
|
||||
/* test if the current clock source is something else than HSI */
|
||||
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
{
|
||||
/* enable HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
/* wait until HSI becomes ready */
|
||||
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
|
||||
;
|
||||
|
||||
/* enable the HSI "divide by 4" bit */
|
||||
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
|
||||
/* wait until the "divide by 4" flag is enabled */
|
||||
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
|
||||
;
|
||||
|
||||
|
||||
/* then use the HSI clock */
|
||||
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
|
||||
|
||||
/* wait until HSI clock is used */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PLL */
|
||||
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
|
||||
/* wait until PLL is inactive */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) != 0)
|
||||
;
|
||||
|
||||
/* set latency to 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* At this point the HSI runs with 4 MHz */
|
||||
/* Multiply by 16 device by 2 --> 32 MHz */
|
||||
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
|
||||
|
||||
/* enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* wait until the PLL is ready */
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
;
|
||||
|
||||
/* use the PLL has clock source */
|
||||
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
|
||||
/* wait until the PLL source is active */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
|
||||
SystemCoreClockUpdate(); /* Update SystemCoreClock global variable */
|
||||
}
|
||||
|
||||
/*
|
||||
Enable several power regions: PWR, GPIOA
|
||||
|
||||
This must be executed after each reset.
|
||||
*/
|
||||
void startUp(void)
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface (PWR) */
|
||||
PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR and RTC */
|
||||
|
||||
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/* u8x8 display procedures */
|
||||
|
||||
void initDisplay(void)
|
||||
{
|
||||
u8x8_Setup(&u8x8, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0);
|
||||
u8x8_InitDisplay(&u8x8);
|
||||
u8x8_ClearDisplay(&u8x8);
|
||||
u8x8_SetPowerSave(&u8x8, 0);
|
||||
u8x8_SetFont(&u8x8, u8x8_font_amstrad_cpc_extended_r);
|
||||
u8x8_x = 0;
|
||||
u8x8_y = 0;
|
||||
}
|
||||
|
||||
|
||||
void outChar(uint8_t c)
|
||||
{
|
||||
if ( u8x8_x >= u8x8_GetCols(&u8x8) )
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y++;
|
||||
}
|
||||
u8x8_DrawGlyph(&u8x8, u8x8_x, u8x8_y, c);
|
||||
u8x8_x++;
|
||||
}
|
||||
|
||||
void outStr(const char *s)
|
||||
{
|
||||
while( *s )
|
||||
outChar(*s++);
|
||||
}
|
||||
|
||||
void outHexHalfByte(uint8_t b)
|
||||
{
|
||||
b &= 0x0f;
|
||||
if ( b < 10 )
|
||||
outChar(b+'0');
|
||||
else
|
||||
outChar(b+'a'-10);
|
||||
}
|
||||
|
||||
void outHex8(uint8_t b)
|
||||
{
|
||||
outHexHalfByte(b >> 4);
|
||||
outHexHalfByte(b);
|
||||
}
|
||||
|
||||
void outHex16(uint16_t v)
|
||||
{
|
||||
outHex8(v>>8);
|
||||
outHex8(v);
|
||||
}
|
||||
|
||||
void outHex32(uint32_t v)
|
||||
{
|
||||
outHex16(v>>16);
|
||||
outHex16(v);
|
||||
}
|
||||
|
||||
void setRow(uint8_t r)
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y = r;
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/*
|
||||
ADC defaults:
|
||||
- Clock source: ADCCLK (HSI16) (ADC_CFGR2)
|
||||
- ADC clock prescaler: divide by 1 (ADC_CCR)
|
||||
- software enabled start
|
||||
- right alignment
|
||||
- 12 Bit resolution
|
||||
- No interrupts enabled
|
||||
|
||||
Calibration:
|
||||
better ignore ADC_ISR_EOCAL and use the ADC_CR_ADCAL flag only.
|
||||
otherwise some extra NOPs are required after calibration
|
||||
*/
|
||||
|
||||
|
||||
void initADC(uint8_t ch)
|
||||
{
|
||||
|
||||
/* ADC Clock Enable */
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADCEN; /* enable ADC clock */
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* ADC Reset */
|
||||
|
||||
RCC->APB2RSTR |= RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
RCC->APB2RSTR &= ~RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* CALIBRATION */
|
||||
|
||||
ADC1->CR |= ADC_CR_ADCAL; /* start calibration */
|
||||
while ((ADC1->CR & ADC_CR_ADCAL) != 0) /* wait for clibration finished */
|
||||
{
|
||||
}
|
||||
|
||||
/* ENABLE ADC */
|
||||
|
||||
ADC1->ISR |= ADC_ISR_ADRDY; /* clear ready flag */
|
||||
ADC1->CR |= ADC_CR_ADEN; /* enable ADC */
|
||||
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* wait for ADC */
|
||||
{
|
||||
}
|
||||
|
||||
/* CONFIGURE ADC */
|
||||
|
||||
//ADC1->CFGR1 &= ~ADC_CFGR1_EXTEN; /* software enabled conversion start */
|
||||
//ADC1->CFGR1 &= ~ADC_CFGR1_ALIGN; /* right alignment */
|
||||
//ADC1->CFGR1 &= ~ADC_CFGR1_RES; /* 12 bit resolution */
|
||||
|
||||
ADC1->CFGR1 |= ADC_CFGR1_CONT; /* continues mode */
|
||||
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSR_0; /* 011 oversampling ration x16 */
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSR_1;
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSS_2; /* shift 4 bits (because of x16 oversampling) */
|
||||
|
||||
//ADC1->CFGR2 |= ADC_CFGR2_OVSR_1; /* 110 oversampling ration x128 */
|
||||
//ADC1->CFGR2 |= ADC_CFGR2_OVSR_2;
|
||||
//ADC1->CFGR2 |= ADC_CFGR2_OVSS_0; /* shift 7 bits (because of x128 oversampling) */
|
||||
//ADC1->CFGR2 |= ADC_CFGR2_OVSS_1; /* shift 7 bits (because of x128 oversampling) */
|
||||
//ADC1->CFGR2 |= ADC_CFGR2_OVSS_2; /* shift 7 bits (because of x128 oversampling) */
|
||||
|
||||
ADC1->CFGR2 |= ADC_CFGR2_OVSE; /* enable oversampling */
|
||||
|
||||
ADC1->CHSELR = 1<<ch; /* Select channel */
|
||||
//ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* Select a sampling mode of 111 (very slow)*/
|
||||
|
||||
/* START CONVERSION */
|
||||
|
||||
ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversion */
|
||||
|
||||
while ((ADC1->ISR & ADC_ISR_EOC) == 0) /* wait end of first conversion */
|
||||
{
|
||||
}
|
||||
|
||||
//data is available in ADC1->DR;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void initTIM(void)
|
||||
{
|
||||
/* enable clock for TIM2 */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||
|
||||
/*enable clock for GPIOA */
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
|
||||
__NOP(); /* extra delay for clock stabilization required? */
|
||||
__NOP();
|
||||
|
||||
/* prescalar for AHB and APB1 */
|
||||
|
||||
/* reselt defaults for HPRE and PPRE1: no clock division */
|
||||
// RCC->CFGR &= ~RCC_CFGR_HPRE;
|
||||
// RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
||||
// RCC->CFGR &= ~RCC_CFGR_PPRE1;
|
||||
// RCC->CFGR |= RCC_CFGR_PPRE1_DIV1;
|
||||
|
||||
/* configure GPIOA PA1 for TIM2 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE1; /* clear mode for PA9 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE1_1; /* alt fn */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1; /* push-pull */
|
||||
GPIOA->AFR[0] &= ~(15<<4); /* Clear Alternate Function PA1 */
|
||||
GPIOA->AFR[0] |= 2<<4; /* AF2 Alternate Function PA1 */
|
||||
|
||||
/* TIM2 configure */
|
||||
/* disable all interrupts */
|
||||
//TIM2->DIER = 0; /* 0 is reset default value */
|
||||
|
||||
/* clear everything, including the "Update disable" flag, so that updates */
|
||||
/* are generated */
|
||||
// TIM2->CR1 = 0; /* 0 is reset default value */
|
||||
//TIM2->CR1 |= TIM_CR1_ARPE; // ARR is not modified so constant update is ok
|
||||
/* Update request by manual UG bit setting or slave controller */
|
||||
/* both is not required here */
|
||||
/* so, update request by couter over/underflow remains */
|
||||
//TIM2->CR1 |= TIM_CR1_URS; /* only udf/ovf generae events */
|
||||
|
||||
|
||||
TIM2->ARR = 4096; /* total cycle count */
|
||||
TIM2->CCR2 = 1024; /* duty cycle */
|
||||
//TIM2->CCMR1 &= ~TIM_CCMR1_OC2CE; /* disable clear output compare 2 **/
|
||||
TIM2->CCMR1 |= TIM_CCMR1_OC2M; /* all 3 bits set: PWM Mode 2 */
|
||||
//TIM2->CCMR1 &= ~TIM_CCMR1_OC1M_0; /* 110: PWM Mode 1 */
|
||||
TIM2->CCMR1 |= TIM_CCMR1_OC2PE; /* preload enable CCR2 is preloaded*/
|
||||
// TIM2->CCMR1 &= ~TIM_CCMR1_OC2FE; /* fast disable (reset default) */
|
||||
// TIM2->CCMR1 &= ~TIM_CCMR1_CC2S; /* configure cc2 as output (this is reset default) */
|
||||
|
||||
|
||||
//TIM2->EGR |= TIM_EGR_CC2G; /* capture event cc2 */
|
||||
TIM2->CCER |= TIM_CCER_CC2E; /* set output enable */
|
||||
//TIM2->CCER |= TIM_CCER_CC2P; /* polarity 0: normal (reset default) / 1: inverted*/
|
||||
|
||||
TIM2->CR1 |= TIM_CR1_CEN; /* counter enable */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void main()
|
||||
{
|
||||
uint16_t adc_value;
|
||||
|
||||
setHSIClock(); /* enable 32 MHz Clock */
|
||||
startUp(); /* enable systick irq and several power regions */
|
||||
initDisplay(); /* aktivate display */
|
||||
initADC(5); /* channel 5 */
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE1; /* clear mode for PA1 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE1_0; /* Output mode for PA1 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1; /* no Push/Pull for PA1 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED1; /* low speed for PA1 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD1; /* no pullup/pulldown for PA1 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_1; /* atomic set PA1 */
|
||||
|
||||
initTIM();
|
||||
|
||||
|
||||
setRow(0); outStr("ADC Test");
|
||||
|
||||
setRow(2); outStr("ch5 pin11: ");
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
adc_value = ADC1->DR;
|
||||
TIM2->CCR2 = adc_value;
|
||||
setRow(3); outHex16(adc_value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
u8x8cb.c
|
||||
|
||||
STM32L031
|
||||
|
||||
PA13: Clock
|
||||
PA14: Data
|
||||
Both lines have a pullup resistor
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* only support for software I2C*/
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no open drain for PA10 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed for PA10 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown for PA10 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA9 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no open drain for PA9 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA9 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA9 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
/* not required for SW I2C */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
delay_micro_seconds(arg_int*1000UL);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_I2C:
|
||||
/* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
|
||||
delay_micro_seconds(arg_int<=2?5:1);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_3; /* atomic clr PA9 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9: input mode */
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr PA10 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
// input mode
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10: input mode */
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case U8X8_MSG_GPIO_MENU_SELECT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_NEXT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_PREV:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN));
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_MENU_HOME:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN));
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=adc_test
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
U8G2INC:=../../../../csrc/
|
||||
U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
|
||||
adc_tim_test
|
||||
|
||||
Example for the STM32L031 Eval Board with 128x64 OLED at PA13/PA14
|
||||
|
||||
LED: PA1 / AF2: TIM2_CH2
|
||||
VarRes: PA5 / ADC CH5
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
/*=======================================================================*/
|
||||
/* external functions */
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
/*=======================================================================*/
|
||||
/* global variables */
|
||||
|
||||
u8x8_t u8x8; // u8x8 object
|
||||
uint8_t u8x8_x, u8x8_y; // current position on the screen
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setHSIClock()
|
||||
{
|
||||
|
||||
/* test if the current clock source is something else than HSI */
|
||||
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
{
|
||||
/* enable HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
/* wait until HSI becomes ready */
|
||||
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
|
||||
;
|
||||
|
||||
/* enable the HSI "divide by 4" bit */
|
||||
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
|
||||
/* wait until the "divide by 4" flag is enabled */
|
||||
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
|
||||
;
|
||||
|
||||
|
||||
/* then use the HSI clock */
|
||||
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
|
||||
|
||||
/* wait until HSI clock is used */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PLL */
|
||||
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
|
||||
/* wait until PLL is inactive */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) != 0)
|
||||
;
|
||||
|
||||
/* set latency to 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* At this point the HSI runs with 4 MHz */
|
||||
/* Multiply by 16 device by 2 --> 32 MHz */
|
||||
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
|
||||
|
||||
/* enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* wait until the PLL is ready */
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
;
|
||||
|
||||
/* use the PLL has clock source */
|
||||
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
|
||||
/* wait until the PLL source is active */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
|
||||
SystemCoreClockUpdate(); /* Update SystemCoreClock global variable */
|
||||
}
|
||||
|
||||
/*
|
||||
Enable several power regions: PWR, GPIOA
|
||||
|
||||
This must be executed after each reset.
|
||||
*/
|
||||
void startUp(void)
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface (PWR) */
|
||||
PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR and RTC */
|
||||
|
||||
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/* u8x8 display procedures */
|
||||
|
||||
void initDisplay(void)
|
||||
{
|
||||
u8x8_Setup(&u8x8, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0);
|
||||
u8x8_InitDisplay(&u8x8);
|
||||
u8x8_ClearDisplay(&u8x8);
|
||||
u8x8_SetPowerSave(&u8x8, 0);
|
||||
u8x8_SetFont(&u8x8, u8x8_font_amstrad_cpc_extended_r);
|
||||
u8x8_x = 0;
|
||||
u8x8_y = 0;
|
||||
}
|
||||
|
||||
|
||||
void outChar(uint8_t c)
|
||||
{
|
||||
if ( u8x8_x >= u8x8_GetCols(&u8x8) )
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y++;
|
||||
}
|
||||
u8x8_DrawGlyph(&u8x8, u8x8_x, u8x8_y, c);
|
||||
u8x8_x++;
|
||||
}
|
||||
|
||||
void outStr(const char *s)
|
||||
{
|
||||
while( *s )
|
||||
outChar(*s++);
|
||||
}
|
||||
|
||||
void outHexHalfByte(uint8_t b)
|
||||
{
|
||||
b &= 0x0f;
|
||||
if ( b < 10 )
|
||||
outChar(b+'0');
|
||||
else
|
||||
outChar(b+'a'-10);
|
||||
}
|
||||
|
||||
void outHex8(uint8_t b)
|
||||
{
|
||||
outHexHalfByte(b >> 4);
|
||||
outHexHalfByte(b);
|
||||
}
|
||||
|
||||
void outHex16(uint16_t v)
|
||||
{
|
||||
outHex8(v>>8);
|
||||
outHex8(v);
|
||||
}
|
||||
|
||||
void outHex32(uint32_t v)
|
||||
{
|
||||
outHex16(v>>16);
|
||||
outHex16(v);
|
||||
}
|
||||
|
||||
void setRow(uint8_t r)
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y = r;
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void initADC(void)
|
||||
{
|
||||
//__disable_irq();
|
||||
|
||||
/* ADC Clock Enable */
|
||||
|
||||
RCC->APB2ENR |= RCC_APB2ENR_ADCEN; /* enable ADC clock */
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* ADC Reset */
|
||||
|
||||
RCC->APB2RSTR |= RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
RCC->APB2RSTR &= ~RCC_APB2RSTR_ADCRST;
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* ADC Basic Setup */
|
||||
|
||||
ADC1->IER = 0; /* do not allow any interrupts */
|
||||
ADC1->CFGR2 &= ~ADC_CFGR2_CKMODE; /* select HSI16 clock */
|
||||
|
||||
ADC1->CR |= ADC_CR_ADVREGEN; /* enable ADC voltage regulator, probably not required, because this is automatically activated */
|
||||
ADC->CCR |= ADC_CCR_VREFEN; /* Wake-up the VREFINT */
|
||||
ADC->CCR |= ADC_CCR_TSEN; /* Wake-up the temperature sensor */
|
||||
|
||||
__NOP(); /* let us wait for some time */
|
||||
__NOP(); /* let us wait for some time */
|
||||
|
||||
/* CALIBRATION */
|
||||
|
||||
if ((ADC1->CR & ADC_CR_ADEN) != 0) /* clear ADEN flag if required */
|
||||
{
|
||||
/* is this correct, i think we must use the disable flag here */
|
||||
ADC1->CR &= (uint32_t)(~ADC_CR_ADEN);
|
||||
}
|
||||
ADC1->CR |= ADC_CR_ADCAL; /* start calibration */
|
||||
while ((ADC1->ISR & ADC_ISR_EOCAL) == 0) /* wait for clibration finished */
|
||||
{
|
||||
}
|
||||
ADC1->ISR |= ADC_ISR_EOCAL; /* clear the status flag, by writing 1 to it */
|
||||
__NOP(); /* not sure why, but some nop's are required here, at least 4 of them */
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
/* ENABLE ADC */
|
||||
|
||||
ADC1->ISR |= ADC_ISR_ADRDY; /* clear ready flag */
|
||||
ADC1->CR |= ADC_CR_ADEN; /* enable ADC */
|
||||
while ((ADC1->ISR & ADC_ISR_ADRDY) == 0) /* wait for ADC */
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ch0 PA0 pin 6
|
||||
ch1 PA1 pin 7
|
||||
ch2 PA2 pin 8
|
||||
ch3 PA3 pin 9
|
||||
ch4 PA4 pin 10
|
||||
ch5 PA5 pin 11
|
||||
ch6 PA6 pin 12
|
||||
ch7 PA7 pin 13
|
||||
ch8 PB0 -
|
||||
ch9 PB1 pin 14
|
||||
|
||||
|
||||
ch 0..15: GPIO
|
||||
ch 16: ???
|
||||
ch 17: vref (bandgap)
|
||||
ch18: temperature sensor
|
||||
|
||||
returns 12 bit result, right aligned
|
||||
*/
|
||||
uint16_t getADC(uint8_t ch)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t i;
|
||||
|
||||
/* CONFIGURE ADC */
|
||||
|
||||
ADC1->CFGR1 &= ~ADC_CFGR1_EXTEN; /* software enabled conversion start */
|
||||
ADC1->CFGR1 &= ~ADC_CFGR1_ALIGN; /* right alignment */
|
||||
ADC1->CFGR1 &= ~ADC_CFGR1_RES; /* 12 bit resolution */
|
||||
ADC1->CHSELR = 1<<ch; /* Select channel */
|
||||
ADC1->SMPR |= ADC_SMPR_SMP_0 | ADC_SMPR_SMP_1 | ADC_SMPR_SMP_2; /* Select a sampling mode of 111 (very slow)*/
|
||||
|
||||
/* DO CONVERSION */
|
||||
|
||||
data = 0;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
|
||||
ADC1->CR |= ADC_CR_ADSTART; /* start the ADC conversion */
|
||||
while ((ADC1->ISR & ADC_ISR_EOC) == 0) /* wait end of conversion */
|
||||
{
|
||||
}
|
||||
data += ADC1->DR; /* get ADC result and clear the ISR_EOC flag */
|
||||
}
|
||||
data >>= 3;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void initTIM(void)
|
||||
{
|
||||
/* enable clock for TIM2 */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
|
||||
|
||||
/*enable clock for GPIOA */
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
|
||||
__NOP(); /* extra delay for clock stabilization required? */
|
||||
__NOP();
|
||||
|
||||
/* prescalar for AHB and APB1 */
|
||||
|
||||
/* reselt defaults for HPRE and PPRE1: no clock division */
|
||||
// RCC->CFGR &= ~RCC_CFGR_HPRE;
|
||||
// RCC->CFGR |= RCC_CFGR_HPRE_DIV1;
|
||||
// RCC->CFGR &= ~RCC_CFGR_PPRE1;
|
||||
// RCC->CFGR |= RCC_CFGR_PPRE1_DIV1;
|
||||
|
||||
/* configure GPIOA PA1 for TIM2 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE1; /* clear mode for PA9 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE1_1; /* alt fn */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1; /* push-pull */
|
||||
GPIOA->AFR[0] &= ~(15<<4); /* Clear Alternate Function PA1 */
|
||||
GPIOA->AFR[0] |= 2<<4; /* AF2 Alternate Function PA1 */
|
||||
|
||||
/* TIM2 configure */
|
||||
/* disable all interrupts */
|
||||
//TIM2->DIER = 0; /* 0 is reset default value */
|
||||
|
||||
/* clear everything, including the "Update disable" flag, so that updates */
|
||||
/* are generated */
|
||||
// TIM2->CR1 = 0; /* 0 is reset default value */
|
||||
//TIM2->CR1 |= TIM_CR1_ARPE; // ARR is not modified so constant update is ok
|
||||
/* Update request by manual UG bit setting or slave controller */
|
||||
/* both is not required here */
|
||||
/* so, update request by couter over/underflow remains */
|
||||
//TIM2->CR1 |= TIM_CR1_URS; /* only udf/ovf generae events */
|
||||
|
||||
|
||||
TIM2->ARR = 4096; /* total cycle count */
|
||||
TIM2->CCR2 = 1024; /* duty cycle */
|
||||
//TIM2->CCMR1 &= ~TIM_CCMR1_OC2CE; /* disable clear output compare 2 **/
|
||||
TIM2->CCMR1 |= TIM_CCMR1_OC2M; /* all 3 bits set: PWM Mode 2 */
|
||||
//TIM2->CCMR1 &= ~TIM_CCMR1_OC1M_0; /* 110: PWM Mode 1 */
|
||||
TIM2->CCMR1 |= TIM_CCMR1_OC2PE; /* preload enable CCR2 is preloaded*/
|
||||
// TIM2->CCMR1 &= ~TIM_CCMR1_OC2FE; /* fast disable (reset default) */
|
||||
// TIM2->CCMR1 &= ~TIM_CCMR1_CC2S; /* configure cc2 as output (this is reset default) */
|
||||
|
||||
|
||||
//TIM2->EGR |= TIM_EGR_CC2G; /* capture event cc2 */
|
||||
TIM2->CCER |= TIM_CCER_CC2E; /* set output enable */
|
||||
//TIM2->CCER |= TIM_CCER_CC2P; /* polarity 0: normal (reset default) / 1: inverted*/
|
||||
|
||||
TIM2->PSC = 7;
|
||||
|
||||
TIM2->CR1 |= TIM_CR1_CEN; /* counter enable */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void main()
|
||||
{
|
||||
uint16_t adc_value;
|
||||
uint16_t i;
|
||||
|
||||
setHSIClock(); /* enable 32 MHz Clock */
|
||||
startUp(); /* enable systick irq and several power regions */
|
||||
initDisplay(); /* aktivate display */
|
||||
initADC();
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE1; /* clear mode for PA1 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE1_0; /* Output mode for PA1 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1; /* no Push/Pull for PA1 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED1; /* low speed for PA1 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD1; /* no pullup/pulldown for PA1 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_1; /* atomic set PA1 */
|
||||
|
||||
initTIM();
|
||||
|
||||
|
||||
setRow(0); outStr("ADC Test");
|
||||
|
||||
setRow(2); outStr("ch5 pin11: ");
|
||||
setRow(3); outHex16(getADC(5));
|
||||
setRow(4); outStr("bandgap: ");
|
||||
setRow(5); outHex16(getADC(17));
|
||||
setRow(6); outStr("temp: ");
|
||||
setRow(7); outHex16(getADC(18));
|
||||
|
||||
for(;;)
|
||||
{
|
||||
|
||||
adc_value = getADC(5);
|
||||
TIM2->CCR2 = adc_value;
|
||||
setRow(3); outHex16(adc_value);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
u8x8cb.c
|
||||
|
||||
STM32L031
|
||||
|
||||
PA13: Clock
|
||||
PA14: Data
|
||||
Both lines have a pullup resistor
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* only support for software I2C*/
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no open drain for PA10 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed for PA10 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown for PA10 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA9 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no open drain for PA9 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA9 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA9 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
/* not required for SW I2C */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
delay_micro_seconds(arg_int*1000UL);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_I2C:
|
||||
/* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
|
||||
delay_micro_seconds(arg_int<=2?5:1);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_3; /* atomic clr PA9 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9: input mode */
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr PA10 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
// input mode
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10: input mode */
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case U8X8_MSG_GPIO_MENU_SELECT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_NEXT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_PREV:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN));
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_MENU_HOME:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN));
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
148
basic-setup/components/u8g2/sys/arm/stm32l031x6/blink/Makefile
Normal file
148
basic-setup/components/u8g2/sys/arm/stm32l031x6/blink/Makefile
Normal file
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=blink
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
#U8G2INC:=../../../../csrc/
|
||||
#U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
34
basic-setup/components/u8g2/sys/arm/stm32l031x6/blink/main.c
Normal file
34
basic-setup/components/u8g2/sys/arm/stm32l031x6/blink/main.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/* LED blink project for the STM32L031 */
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
if ( SysTickCount & 1 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA13 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA13 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no Push/Pull for PA13 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA13 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA13 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
|
||||
SysTick->LOAD = 2000*500 - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
|
||||
for(;;)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=blink_a13_a14
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
#U8G2INC:=../../../../csrc/
|
||||
#U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/* LED blink project for the STM32L031 */
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
switch ( SysTickCount & 3 )
|
||||
{
|
||||
case 0:
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */
|
||||
break;
|
||||
case 1:
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
break;
|
||||
case 2:
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA13 */
|
||||
break;
|
||||
case 3:
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr PA13 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA13 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA13 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no Push/Pull for PA13 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA13 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA13 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA14 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA14 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no Push/Pull for PA14 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed for PA14 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown for PA14 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr PA14 */
|
||||
|
||||
SysTick->LOAD = 2000*500 - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
|
||||
for(;;)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=blink
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
#U8G2INC:=../../../../csrc/
|
||||
#U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
@@ -0,0 +1,97 @@
|
||||
/* LED blink project for the STM32L031 */
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setHSIClock()
|
||||
{
|
||||
|
||||
|
||||
/* test if the current clock source is something else than HSI */
|
||||
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
{
|
||||
/* enable HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
/* wait until HSI becomes ready */
|
||||
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
|
||||
;
|
||||
|
||||
/* enable the HSI "divide by 4" bit */
|
||||
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
|
||||
/* wait until the "divide by 4" flag is enabled */
|
||||
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
|
||||
;
|
||||
|
||||
|
||||
/* then use the HSI clock */
|
||||
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
|
||||
|
||||
/* wait until HSI clock is used */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PLL */
|
||||
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
|
||||
/* wait until PLL is inactive */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) != 0)
|
||||
;
|
||||
|
||||
/* set latency to 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* At this point the HSI runs with 4 MHz */
|
||||
/* Multiply by 16 device by 2 --> 32 MHz */
|
||||
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
|
||||
|
||||
/* enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* wait until the PLL is ready */
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
;
|
||||
|
||||
/* use the PLL has clock source */
|
||||
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
|
||||
/* wait until the PLL source is active */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
setHSIClock();
|
||||
SystemCoreClockUpdate(); /* Update SystemCoreClock() */
|
||||
//SystemCoreClock = 32000000UL;
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA13 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA13 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no Push/Pull for PA13 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA13 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA13 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
|
||||
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
|
||||
for(;;)
|
||||
{
|
||||
delay_micro_seconds(500000);
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */
|
||||
delay_micro_seconds(500000);
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=blink
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
#U8G2INC:=../../../../csrc/
|
||||
#U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
/* LED blink project for the STM32L031 */
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
if ( SysTickCount & 1 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setHSIClock()
|
||||
{
|
||||
|
||||
|
||||
/* test if the current clock source is something else than HSI */
|
||||
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
{
|
||||
/* enable HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
/* wait until HSI becomes ready */
|
||||
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
|
||||
;
|
||||
|
||||
/* enable the HSI "divide by 4" bit */
|
||||
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
|
||||
/* wait until the "divide by 4" flag is enabled */
|
||||
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
|
||||
;
|
||||
|
||||
|
||||
/* then use the HSI clock */
|
||||
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
|
||||
|
||||
/* wait until HSI clock is used */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PLL */
|
||||
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
|
||||
/* wait until PLL is inactive */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) != 0)
|
||||
;
|
||||
|
||||
/* set latency to 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* At this point the HSI runs with 4 MHz */
|
||||
/* Multiply by 16 device by 2 --> 32 MHz */
|
||||
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
|
||||
|
||||
/* enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* wait until the PLL is ready */
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
;
|
||||
|
||||
/* use the PLL has clock source */
|
||||
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
|
||||
/* wait until the PLL source is active */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
setHSIClock();
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA13 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA13 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no Push/Pull for PA13 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA13 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA13 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
|
||||
SysTick->LOAD = 2000*500 - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
|
||||
for(;;)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=boost_converter
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
#U8G2INC:=../../../../csrc/
|
||||
#U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/* LED blink project for the STM32L031 */
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/*===============================================*/
|
||||
/*
|
||||
systick IRQ
|
||||
*/
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
if ( SysTickCount & 1 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
}
|
||||
|
||||
/*===============================================*/
|
||||
/*
|
||||
boost converter
|
||||
PA6=Output to N-MOS Gate
|
||||
PA7=Reference Input
|
||||
*/
|
||||
void boost_converter(void)
|
||||
{
|
||||
/* assumes, that SYSCFG_CRGR3 is not locked */
|
||||
/* assumes, that COMP2 is not locked */
|
||||
|
||||
/* setup internal reference */
|
||||
|
||||
SYSCFG->CFGR3 |= SYSCFG_CFGR3_ENBUFLP_VREFINT_COMP; /* enable VREFINT during low power mode */
|
||||
while( (SYSCFG->CFGR3 & SYSCFG_CFGR3_VREFINT_RDYF) == 0 ) /* wait for VREFINT until it becomes ready */
|
||||
;
|
||||
|
||||
/* setup COMP2 */
|
||||
|
||||
/* select PA7 as positive input --> 101 */
|
||||
COMP2->CSR &= ~(uint32_t)COMP_CSR_COMP2INPSEL;
|
||||
COMP2->CSR |= COMP_CSR_COMP2INPSEL_0 | COMP_CSR_COMP2INPSEL_2;
|
||||
|
||||
/* select 1/4 internal reference voltage --> 0.306 Volt -->100 */
|
||||
COMP2->CSR &= ~(uint32_t)COMP_CSR_COMP2INNSEL;
|
||||
COMP2->CSR |= COMP_CSR_COMP2INNSEL_2;
|
||||
|
||||
/* invert polarity */
|
||||
COMP2->CSR |= COMP_CSR_COMP2POLARITY;
|
||||
|
||||
/* comparator enable */
|
||||
COMP2->CSR |= COMP_CSR_COMP2EN;
|
||||
|
||||
/* setup PWM mode for TIM22 */
|
||||
|
||||
/* configure output compare for channel 1 of TIM22 */
|
||||
TIM22->CCMR1 &= ~(uint32_t)TIM_CCMR1_CC1S;
|
||||
|
||||
/* configure pwm mode 1 */
|
||||
TIM22->CCMR1 &= ~(uint32_t)TIM_CCMR1_OC1M; /* clear mode to 000 */
|
||||
TIM22->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; /* pwm mode 1 (110) */
|
||||
|
||||
TIM22->CCMR1 |= TIM_CCMR1_OC1PE; /* load modified CCR1 during update event only */
|
||||
|
||||
TIM22->PSC = 0; /* run with max speed (2 MHz after reset) */
|
||||
TIM22->ARR = 20; /* period of 20 clocks (100KHz if sys clock is not modified */
|
||||
TIM22->CCR1 = 10; /* a value between 0 and ARR, which defines the duty cycle */
|
||||
|
||||
/* output the result of channel 1 to PA6 */
|
||||
TIM22->CCER |= TIM_CCER_CC1E;
|
||||
/* do not invert the output polarity (this is also the default value) */
|
||||
TIM22->CCER &= ~(uint32_t)TIM_CCER_CC1P;
|
||||
|
||||
/* use up counter (this is also the default value) */
|
||||
TIM22->CR1 &= ~(uint32_t)TIM_CR1_DIR;
|
||||
|
||||
/* do not use "one pulse mode" (continues mode, this is also the default value) */
|
||||
TIM22->CR1 &= ~(uint32_t)TIM_CR1_OPM;
|
||||
|
||||
/* always generate an update event (this is also default) */
|
||||
TIM22->CR1 &= ~(uint32_t)TIM_CR1_UDIS;
|
||||
|
||||
/* update event can be caused by UG bit and overflow (this is default) */
|
||||
TIM22->CR1 &= ~(uint32_t)TIM_CR1_URS;
|
||||
|
||||
/* enable the counter */
|
||||
TIM22->CR1 |= TIM_CR1_CEN;
|
||||
|
||||
|
||||
|
||||
|
||||
TIMx->CR1 |= TIM_CR1_CEN; /* (6) */
|
||||
TIMx->EGR |= TIM_EGR_UG; /* (7) */
|
||||
|
||||
/* setup gated mode for TIM22 */
|
||||
|
||||
|
||||
/* (1) Configure channel 1 to detect low level on the TI1 input
|
||||
by writing CC1S = ‘01’,
|
||||
and configure the input filter duration by writing the IC1F[3:0]
|
||||
bits
|
||||
in the TIMx_CCMR1 register (if no filter is needed, keep
|
||||
IC1F=0000).*/
|
||||
/* (2) Select polarity by writing CC1P=1 in the TIMx_CCER register */
|
||||
/* (3) Configure the timer in gated mode by writing SMS=101
|
||||
Select TI1 as the trigger input source by writing TS=101
|
||||
in the TIMx_SMCR register.*/
|
||||
/* (4) Set prescaler to 4000-1 in order to get an increment each 250us */
|
||||
/* (5) Enable the counter by writing CEN=1 in the TIMx_CR1 register. */
|
||||
TIMx->CCMR1 |= TIM_CCMR1_CC1S_0; /* (1 */
|
||||
TIMx->CCER |= TIM_CCER_CC1P; /* (2) */
|
||||
TIMx->SMCR |= TIM_SMCR_SMS_2 | TIM_SMCR_SMS_0 \
|
||||
| TIM_SMCR_TS_2 | TIM_SMCR_TS_0; /* (3) */
|
||||
TIMx->PSC = 3999; /* (4) */
|
||||
TIMx->CR1 |= TIM_CR1_CEN; /* (5) */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA13 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA13 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no Push/Pull for PA13 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA13 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA13 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */
|
||||
|
||||
SysTick->LOAD = 2000*500 - 1;
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
|
||||
for(;;)
|
||||
;
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
14072
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock.dxf
Normal file
14072
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock.dxf
Normal file
File diff suppressed because it is too large
Load Diff
149
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/Makefile
Normal file
149
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/Makefile
Normal file
@@ -0,0 +1,149 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=clock
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c) ../../../sdl/clock/datecalc.c ../../../sdl/clock/guifn.c ../../../sdl/clock/guimenu.c ../../../sdl/clock/menu.c
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
U8G2INC:=../../../../csrc/
|
||||
U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99 -I. -I$(SYSINC) -I$(U8G2INC) -I../../../sdl/clock/
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
#stm32flash -b 115200 -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
stm32flash -b 230400 -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
129
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/delay.c
Normal file
129
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/delay.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
251
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/guihal.c
Normal file
251
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/guihal.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
|
||||
guihal.c
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "gui.h"
|
||||
|
||||
/*============================================*/
|
||||
/* reset */
|
||||
void do_reset(void)
|
||||
{
|
||||
/* clear the display first, to provide some visual feedback to the user */
|
||||
u8g2_ClearDisplay(gui_menu.u8g2);
|
||||
|
||||
__disable_irq();
|
||||
|
||||
/* Deactivate tamper so that the uC can be programmed via UART */
|
||||
/* This is required, because RX pin is shared with Tamp2 */
|
||||
|
||||
RTC->WPR = 0x0ca; /* disable RTC write protection */
|
||||
RTC->WPR = 0x053;
|
||||
|
||||
EXTI->IMR &= ~EXTI_IMR_IM19; /* disable tamper irq */
|
||||
|
||||
RTC->TAMPCR = 0; /* clear tamper detection */
|
||||
|
||||
RTC->WPR = 0; /* disable RTC write protection */
|
||||
RTC->WPR = 0;
|
||||
|
||||
/* execute reset */
|
||||
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/*============================================*/
|
||||
/* load & store from/to permanent memory */
|
||||
|
||||
|
||||
/* 5x 32bit */
|
||||
|
||||
void store_gui_data(uint32_t *data)
|
||||
{
|
||||
RTC->BKP0R = data[0];
|
||||
RTC->BKP1R = data[1];
|
||||
RTC->BKP2R = data[2];
|
||||
RTC->BKP3R = data[3];
|
||||
RTC->BKP4R = data[4];
|
||||
}
|
||||
|
||||
|
||||
void load_gui_data(uint32_t *data)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
for( i = 0; i < GUI_ALARM_CNT; i++ )
|
||||
data[i] = 0;
|
||||
|
||||
data[0] = RTC->BKP0R;
|
||||
data[1] = RTC->BKP1R;
|
||||
data[2] = RTC->BKP2R;
|
||||
data[3] = RTC->BKP3R;
|
||||
data[4] = RTC->BKP4R;
|
||||
}
|
||||
|
||||
|
||||
/*============================================*/
|
||||
/* input */
|
||||
|
||||
int is_por_reset(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_button_reset(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t get_boot_status_register(void)
|
||||
{
|
||||
/* POR: 00001100 (POR=1, PIN=1), reset pin has RC network connected */
|
||||
/* Boot via NVIC: 00011100, compared to POR, the SW Reset flag is also set */
|
||||
|
||||
return RCC->CSR >> 24;
|
||||
}
|
||||
|
||||
extern volatile unsigned long PWR_CSR_Backup;
|
||||
|
||||
uint32_t get_pwr_status_register(void)
|
||||
{
|
||||
|
||||
/*
|
||||
Bit 1 SBF: Standby flag
|
||||
This bit is set by hardware and cleared only by a POR/PDR (power-on reset/power-down
|
||||
reset) or by setting the CSBF bit in the PWR power control register (PWR_CR)
|
||||
0: Device has not been in Standby mode
|
||||
1: Device has been in Standby mode
|
||||
|
||||
Bit 0 WUF: Wakeup flag
|
||||
This bit is set by hardware and cleared by a system reset or by setting the CWUF bit in the
|
||||
PWR power control register (PWR_CR)
|
||||
0: No wakeup event occurred
|
||||
1: A wakeup event was received from the WKUP pin or from the RTC
|
||||
|
||||
|
||||
POR (voltage off-on): 00
|
||||
Reset Button: 00
|
||||
WUF Reset: 11
|
||||
|
||||
|
||||
*/
|
||||
|
||||
return PWR_CSR_Backup & 255;
|
||||
}
|
||||
|
||||
|
||||
extern volatile unsigned long ResetReason;
|
||||
uint32_t get_reset_reason(void)
|
||||
{
|
||||
return ResetReason;
|
||||
}
|
||||
|
||||
extern volatile unsigned long RTCWUCount;
|
||||
|
||||
uint32_t get_wakeup_count(void)
|
||||
{
|
||||
return RTCWUCount;
|
||||
}
|
||||
|
||||
int is_dst_by_date(uint8_t region);
|
||||
|
||||
uint32_t get_dst_by_date(void)
|
||||
{
|
||||
return is_dst_by_date(1);
|
||||
}
|
||||
|
||||
uint32_t get_dst_by_RTC(void)
|
||||
{
|
||||
uint32_t dst_state = 0;
|
||||
if ( RTC->CR & RTC_CR_BCK ) /* BKP flag in the CR register */
|
||||
dst_state = 1;
|
||||
return dst_state;
|
||||
}
|
||||
|
||||
|
||||
/*============================================*/
|
||||
/* output */
|
||||
|
||||
void SetAlarmSequence(const uint8_t *alarm_sequence);
|
||||
extern const uint8_t ASeqTrippleBeep[];
|
||||
|
||||
|
||||
void enable_alarm(void)
|
||||
{
|
||||
SetAlarmSequence(ASeqTrippleBeep);
|
||||
}
|
||||
|
||||
void disable_alarm(void)
|
||||
{
|
||||
SetAlarmSequence(NULL);
|
||||
|
||||
}
|
||||
|
||||
void set_time(uint8_t ht, uint8_t ho, uint8_t mt, uint8_t mo, uint8_t st, uint8_t so)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = ht;
|
||||
v <<= 4,
|
||||
v |= ho;
|
||||
v <<= 4;
|
||||
v |= mt;
|
||||
v <<= 4;
|
||||
v |= mo;
|
||||
v <<= 4;
|
||||
v |= st;
|
||||
v <<= 4;
|
||||
v |= so;
|
||||
|
||||
__disable_irq();
|
||||
RTC->WPR = 0x0ca; /* disable RTC write protection */
|
||||
RTC->WPR = 0x053;
|
||||
|
||||
RTC->ISR = RTC_ISR_INIT; /* request RTC stop */
|
||||
while((RTC->ISR & RTC_ISR_INITF)!=RTC_ISR_INITF) /* wait for stop */
|
||||
;
|
||||
RTC->PRER = 0x07f00ff; /* 1 Hz clock */
|
||||
RTC->TR = v;
|
||||
RTC->ISR =~ RTC_ISR_INIT; /* start RTC */
|
||||
|
||||
RTC->WPR = 0; /* enable RTC write protection */
|
||||
RTC->WPR = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
weekday: 0 = monday
|
||||
*/
|
||||
void set_date(uint8_t yt, uint8_t yo, uint8_t mt, uint8_t mo, uint8_t dayt, uint8_t dayo, uint8_t weekday)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
v = yt;
|
||||
|
||||
v <<= 4,
|
||||
v |= yo;
|
||||
|
||||
v <<= 3;
|
||||
v |= weekday+1; /* monday starts with 1 on the STM32L0 */
|
||||
v <<= 1;
|
||||
v |= mt;
|
||||
|
||||
v <<= 4;
|
||||
v |= mo;
|
||||
|
||||
v <<= 4;
|
||||
v |= dayt;
|
||||
|
||||
v <<= 4;
|
||||
v |= dayo;
|
||||
|
||||
__disable_irq();
|
||||
RTC->WPR = 0x0ca; /* disable RTC write protection */
|
||||
RTC->WPR = 0x053;
|
||||
|
||||
RTC->ISR = RTC_ISR_INIT; /* request RTC stop */
|
||||
while((RTC->ISR & RTC_ISR_INITF)!=RTC_ISR_INITF) /* wait for stop */
|
||||
;
|
||||
RTC->PRER = 0x07f00ff; /* 1 Hz clock */
|
||||
RTC->DR = v;
|
||||
RTC->ISR =~ RTC_ISR_INIT; /* start RTC */
|
||||
|
||||
RTC->WPR = 0; /* enable RTC write protection */
|
||||
RTC->WPR = 0;
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
/* value 1..7, 0 is default (do not set) */
|
||||
void set_contrast(void)
|
||||
{
|
||||
uint8_t v = gui_data.contrast;
|
||||
if ( v > 0 )
|
||||
{
|
||||
v = v * 36;
|
||||
u8g2_SetContrast(gui_menu.u8g2, v);
|
||||
}
|
||||
}
|
||||
47
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/key.c
Normal file
47
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/key.c
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
key.c
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "stm32l031xx.h" /* IRQ disable/enable */
|
||||
#include "key.h"
|
||||
|
||||
#define KEY_QUEUE_MASK 0x0f
|
||||
#define KEY_QUEUE_MAX (KEY_QUEUE_MASK+1)
|
||||
uint8_t volatile key_queue[KEY_QUEUE_MAX];
|
||||
uint8_t volatile key_queue_start = 0;
|
||||
uint8_t volatile key_queue_end = 0;
|
||||
|
||||
|
||||
int key_add(uint8_t key)
|
||||
{
|
||||
uint8_t new_end;
|
||||
new_end = key_queue_end;
|
||||
new_end++;
|
||||
new_end &= KEY_QUEUE_MASK;
|
||||
if ( new_end == key_queue_start )
|
||||
return 0; /* buffer is full */
|
||||
key_queue[key_queue_end] = key;
|
||||
key_queue_end = new_end;
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t key_get(void)
|
||||
{
|
||||
uint8_t key;
|
||||
uint8_t new_start;
|
||||
|
||||
if ( key_queue_start == key_queue_end )
|
||||
{
|
||||
return KEY_NONE;
|
||||
}
|
||||
//__disable_irq();
|
||||
key = key_queue[key_queue_start];
|
||||
new_start = key_queue_start;
|
||||
new_start++;
|
||||
new_start &= KEY_QUEUE_MASK;
|
||||
key_queue_start = new_start;
|
||||
//__enable_irq();
|
||||
return key;
|
||||
}
|
||||
|
||||
19
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/key.h
Normal file
19
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/key.h
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
key.h
|
||||
*/
|
||||
|
||||
#ifndef _KEY_H
|
||||
#define KEY_H
|
||||
|
||||
#define KEY_NONE 0
|
||||
#define KEY_SELECT 1
|
||||
#define KEY_NEXT 2
|
||||
|
||||
int key_add(uint8_t key);
|
||||
uint8_t key_get(void);
|
||||
|
||||
extern volatile uint8_t key_queue_start;
|
||||
extern volatile uint8_t key_queue_end;
|
||||
|
||||
|
||||
#endif
|
||||
1021
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/main.c
Normal file
1021
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/main.c
Normal file
File diff suppressed because it is too large
Load Diff
82
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/rtc.c
Normal file
82
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/rtc.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
|
||||
rtc.c
|
||||
|
||||
PA0 TAMP2 Button
|
||||
PA2 TAMP3 Button
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8g2.h"
|
||||
#include "rtc.h"
|
||||
|
||||
#ifdef NOT_USED
|
||||
|
||||
/* read RTC register into bcd array */
|
||||
void rtc_register_to_bcd(rtc_t *rtc)
|
||||
{
|
||||
uint32_t r;
|
||||
int i;
|
||||
|
||||
r = RTC->TR;
|
||||
i = 0;
|
||||
do
|
||||
{
|
||||
rtc->bcd[i] = r & 15;
|
||||
r >>= 4;
|
||||
i++;
|
||||
} while( i < 6 );
|
||||
|
||||
rtc->bcd[1] &= 7; /* seconds */
|
||||
rtc->bcd[3] &= 7; /* minutes */
|
||||
rtc->bcd[5] &= 3; /* hours */
|
||||
|
||||
r = RTC->DR;
|
||||
i = 6;
|
||||
do
|
||||
{
|
||||
rtc->bcd[i] = r & 15;
|
||||
r >>= 4;
|
||||
i++;
|
||||
} while( i < 12 );
|
||||
|
||||
rtc->bcd[7] &= 3; /* days */
|
||||
rtc->bcd[9] &= 1; /* months */
|
||||
}
|
||||
|
||||
static uint8_t rtc_bcd_to_uint8(rtc_t *rtc, int idx) U8G2_NOINLINE;
|
||||
static uint8_t rtc_bcd_to_uint8(rtc_t *rtc, int idx)
|
||||
{
|
||||
return rtc->bcd[idx+1]*10 + rtc->bcd[idx];
|
||||
}
|
||||
|
||||
/* convert the content of the bcd array to the ymd&hms vars */
|
||||
void rtc_bcd_to_ymd_hms(rtc_t *rtc)
|
||||
{
|
||||
rtc->sec = rtc_bcd_to_uint8(rtc, 0);
|
||||
rtc->min = rtc_bcd_to_uint8(rtc, 2);
|
||||
rtc->hour = rtc_bcd_to_uint8(rtc, 4);
|
||||
rtc->day = rtc_bcd_to_uint8(rtc, 6);
|
||||
rtc->month = rtc_bcd_to_uint8(rtc, 8);
|
||||
rtc->year = rtc_bcd_to_uint8(rtc, 10);
|
||||
}
|
||||
|
||||
void rtc_draw_time(rtc_t *rtc, u8g2_t *u8g2)
|
||||
{
|
||||
char s[10];
|
||||
strcpy(s, u8x8_u8toa(rtc->hour, 2));
|
||||
strcat(s, ":");
|
||||
strcat(s, u8x8_u8toa(rtc->min, 2));
|
||||
strcat(s, ":");
|
||||
strcat(s, u8x8_u8toa(rtc->sec, 2));
|
||||
|
||||
u8g2_SetFont(u8g2, u8g2_font_helvB18_tn);
|
||||
u8g2_DrawStr(u8g2, 0,23, s);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
43
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/rtc.h
Normal file
43
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/rtc.h
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
|
||||
rtc.h
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _RTC_VIEW_H
|
||||
#define _RTC_VIEW_H
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#define BCD_SEC_UNITS 0
|
||||
#define BCD_SEC_TENS 1
|
||||
#define BCD_MIN_UNITS 2
|
||||
#define BCD_MIN_TENS 3
|
||||
#define BCD_HOUR_UNITS 4
|
||||
#define BCD_HOUR_TENS 5
|
||||
#define BCD_DAY_UNITS 6
|
||||
#define BCD_DAY_TENS 7
|
||||
#define BCD_MONTH_UNITS 8
|
||||
#define BCD_MONTH_TENS 9
|
||||
#define BCD_YEAR_UNITS 10
|
||||
#define BCD_YEAR_TENS 11
|
||||
|
||||
|
||||
struct _rtc_struct
|
||||
{
|
||||
uint8_t bcd[12];
|
||||
|
||||
uint8_t sec; /* 0..59 */
|
||||
uint8_t min; /* 0..59 */
|
||||
uint8_t hour; /* 0..23 */
|
||||
uint8_t day; /* 1..31 */
|
||||
uint8_t month; /* 1..12 */
|
||||
uint8_t year; /* 0..99 */
|
||||
};
|
||||
typedef struct _rtc_struct rtc_t;
|
||||
|
||||
void rtc_register_to_bcd(rtc_t *rtc);
|
||||
void rtc_bcd_to_ymd_hms(rtc_t *rtc);
|
||||
void rtc_draw_time(rtc_t *rtc, u8g2_t *u8g2);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
271
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/summer.c
Normal file
271
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/summer.c
Normal file
@@ -0,0 +1,271 @@
|
||||
/*
|
||||
|
||||
summer.c
|
||||
|
||||
stm32l0 daylight savings time (DST) calculation
|
||||
|
||||
US:
|
||||
Der Energy Policy Act of 2005 (Public Law 109-58) bestimmt in Sec. 110 mit dem Titel Daylight Savings,
|
||||
dass ab 2007 die Sommerzeit am zweiten Sonntag im März beginnt und am ersten Sonntag im November endet.
|
||||
|
||||
|
||||
EU:
|
||||
Central European Summer Time (CEST, britisch) oder Central European Daylight Saving Time
|
||||
(applies to almost all european countries)
|
||||
|
||||
Die mitteleuropäische Sommerzeit beginnt jeweils am letzten Sonntag im März um 2:00 Uhr MEZ,
|
||||
indem die Stundenzählung um eine Stunde von 2:00 Uhr auf 3:00 Uhr vorgestellt wird. Sie endet jeweils am letzten Sonntag im Oktober um
|
||||
3:00 Uhr MESZ, indem die Stundenzählung um eine Stunde von 3:00 Uhr auf 2:00 Uhr zurückgestellt wird. Die Stunde von 2:00 Uhr bis 3:00 Uhr erscheint im Herbst also zweimal.
|
||||
*/
|
||||
|
||||
#ifdef __unix
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
static uint8_t is_leap_year(uint16_t y)
|
||||
{
|
||||
if (
|
||||
((y % 4 == 0) && (y % 100 != 0)) ||
|
||||
(y % 400 == 0)
|
||||
)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t get_year_day_number(uint16_t y, uint8_t m, uint8_t d)
|
||||
{
|
||||
uint8_t tmp1;
|
||||
uint16_t tmp2;
|
||||
tmp1 = 0;
|
||||
if ( m >= 3 )
|
||||
tmp1++;
|
||||
tmp2 = m;
|
||||
tmp2 +=2;
|
||||
tmp2 *=611;
|
||||
tmp2 /= 20;
|
||||
tmp2 += d;
|
||||
tmp2 -= 91;
|
||||
tmp1 <<=1;
|
||||
tmp2 -= tmp1;
|
||||
if ( tmp1 != 0 )
|
||||
tmp2 += is_leap_year(y);
|
||||
return tmp2;
|
||||
}
|
||||
|
||||
uint8_t get_weekday_by_year_day_number(uint16_t y, uint16_t ydn)
|
||||
{
|
||||
uint8_t j, c, tmp8;
|
||||
uint16_t tmp16;
|
||||
y--;
|
||||
j = y % 100;
|
||||
c = y / 100;
|
||||
tmp16 = c;
|
||||
tmp16 *= 5;
|
||||
tmp16 += ydn;
|
||||
tmp8 = j;
|
||||
j >>= 2;
|
||||
c >>= 2;
|
||||
tmp8 += j;
|
||||
tmp8 += c;
|
||||
tmp8 += 28;
|
||||
tmp16 += tmp8;
|
||||
tmp16 %= 7;
|
||||
return tmp16;
|
||||
}
|
||||
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
uint16_t day;
|
||||
uint16_t hour;
|
||||
|
||||
#else
|
||||
#include "datecalc.h"
|
||||
#include "stm32l031xx.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
this function does not require gui_date_adjust() to be called
|
||||
0: no DST (Wintertime)
|
||||
1: DST (Summertime)
|
||||
-1: unknown (last sunday in oct, between 2am and 3am )
|
||||
|
||||
region
|
||||
0: do nothing
|
||||
1: EU
|
||||
2: US
|
||||
|
||||
*/
|
||||
int is_dst_by_date(uint8_t region)
|
||||
{
|
||||
uint16_t ydn;
|
||||
uint16_t ydn_change_to_wintertime;
|
||||
uint16_t ydn_change_to_summertime;
|
||||
|
||||
|
||||
#ifndef __unix
|
||||
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
uint16_t day;
|
||||
uint16_t hour;
|
||||
|
||||
|
||||
/* read date from date register */
|
||||
|
||||
year = ((RTC->DR >> 20) & 15);
|
||||
year *= 10;
|
||||
year += ((RTC->DR >> 16) & 15);
|
||||
year += 2000;
|
||||
|
||||
month = ((RTC->DR >> 12) & 1);
|
||||
month *= 10;
|
||||
month += ((RTC->DR >> 8) & 15);
|
||||
|
||||
day = ((RTC->DR >> 4) & 3);
|
||||
day *= 10;
|
||||
day += ((RTC->DR) & 15);
|
||||
|
||||
/* also get the hour for later comparison */
|
||||
|
||||
hour = ((RTC->TR >> 20) & 3); /* assuming 24-hour clock, not sure about PM flag */
|
||||
hour *= 10;
|
||||
hour += ((RTC->TR >> 16) & 15);
|
||||
|
||||
#endif
|
||||
|
||||
/* convert all dates to date numbers of the current year*/
|
||||
|
||||
if ( region == 1 ) /* EU */
|
||||
{
|
||||
/* European Summer Time: Last Sunday in March and last Sunday in October */
|
||||
ydn_change_to_summertime = get_year_day_number(year, 3, 31);
|
||||
ydn_change_to_wintertime = get_year_day_number(year, 10, 31);
|
||||
}
|
||||
else if ( region == 2 ) /* US */
|
||||
{
|
||||
/* US DST rules: Second Sunday in March and First Sunday in November */
|
||||
ydn_change_to_summertime = get_year_day_number(year, 2, 28+is_leap_year(year));
|
||||
ydn_change_to_summertime += 14;
|
||||
|
||||
ydn_change_to_wintertime = get_year_day_number(year, 10, 31);
|
||||
ydn_change_to_wintertime += 7;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
ydn_change_to_summertime -= get_weekday_by_year_day_number(year, ydn_change_to_summertime);
|
||||
ydn_change_to_wintertime -= get_weekday_by_year_day_number(year, ydn_change_to_wintertime);
|
||||
|
||||
ydn = get_year_day_number(year, month, day);
|
||||
|
||||
if ( ydn == ydn_change_to_summertime )
|
||||
if ( hour >= 2 )
|
||||
return 1; /* yes, it is DST */
|
||||
|
||||
if ( ydn == ydn_change_to_wintertime )
|
||||
{
|
||||
if ( hour < 2 )
|
||||
return 1; /* still DST */
|
||||
if ( hour > 3 )
|
||||
return 0; /* not DST any more */
|
||||
return -1; /* not sure whether DST or not */
|
||||
}
|
||||
|
||||
if ( ydn > ydn_change_to_summertime && ydn < ydn_change_to_wintertime )
|
||||
return 1; /* within DST */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __unix
|
||||
|
||||
int main()
|
||||
{
|
||||
int dd;
|
||||
int d = -2;
|
||||
for( year = 2000; year < 2030; year++ )
|
||||
{
|
||||
printf("%d: ", year);
|
||||
for( month = 3; month <= 11; month ++ )
|
||||
{
|
||||
for( day = 1; day<= 31; day++ )
|
||||
{
|
||||
hour = 2;
|
||||
dd = is_dst_by_date(1);
|
||||
if ( d == 0 && dd == 1 )
|
||||
{
|
||||
printf("%d.%d.%d", day, month, year);
|
||||
}
|
||||
switch(dd)
|
||||
{
|
||||
//case -1: printf("%d.%d.%d", day, month, year); break;
|
||||
//case 0: printf("w"); break;
|
||||
//case 1: printf("s"); break;
|
||||
|
||||
}
|
||||
d = dd;
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
region
|
||||
0: do nothing
|
||||
1: EU
|
||||
2: US
|
||||
|
||||
*/
|
||||
|
||||
void adjustDST(uint8_t region)
|
||||
{
|
||||
int is_dst;
|
||||
int dst_state;
|
||||
|
||||
is_dst = is_dst_by_date(region);
|
||||
|
||||
if ( is_dst >= 0 )
|
||||
{
|
||||
dst_state = 0;
|
||||
if ( RTC->CR & RTC_CR_BCK ) /* BKP flag in the CR register */
|
||||
dst_state = 1;
|
||||
|
||||
if ( is_dst != dst_state )
|
||||
{
|
||||
|
||||
__disable_irq();
|
||||
|
||||
PWR->CR |= PWR_CR_DBP; /* disable write protection (step 1) */
|
||||
|
||||
RTC->WPR = 0x0ca; /* disable RTC write protection (step 2) */
|
||||
RTC->WPR = 0x053;
|
||||
|
||||
if ( is_dst != 0 )
|
||||
{
|
||||
RTC->CR |= RTC_CR_BCK; /* the RTC will now run in summer time (set DST flag) */
|
||||
RTC->CR |= RTC_CR_ADD1H; /* change to DST (Summertime): add one hour */
|
||||
}
|
||||
else
|
||||
{
|
||||
RTC->CR &= ~RTC_CR_BCK; /* the RTC will now run in winter time (turn off DST flag) */
|
||||
RTC->CR |= RTC_CR_SUB1H; /* change back to none DST (Wintertime): subtract one hour */
|
||||
}
|
||||
|
||||
RTC->WPR = 0; /* enable RTC write protection (step 2) */
|
||||
RTC->WPR = 0;
|
||||
|
||||
__enable_irq();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
112
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/u8x8cb.c
Normal file
112
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock/u8x8cb.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
u8x8cb.c
|
||||
|
||||
STM32L031
|
||||
|
||||
PA9: Clock
|
||||
PA10: Data
|
||||
Both lines have a pullup resistor
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* only support for software I2C*/
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE10; /* clear mode for PA10 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE10_0; /* Output mode for PA10 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_10; /* no open drain for PA10 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED10; /* low speed for PA10 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD10; /* no pullup/pulldown for PA10 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_10; /* atomic set PA10 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode for PA9 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE9_0; /* Output mode for PA9 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_9; /* no open drain for PA9 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED9; /* low speed for PA9 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD9; /* no pullup/pulldown for PA9 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_9; /* atomic set PA9 */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
/* not required for SW I2C */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
delay_micro_seconds(arg_int*1000UL);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_I2C:
|
||||
/* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
|
||||
//delay_micro_seconds(arg_int<=2?5:1);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE9_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_9; /* atomic clr PA9 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_9; /* atomic set PA9 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode for PA9: input mode */
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE10; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE10_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_10; /* atomic clr PA10 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_10; /* atomic set PA10 */
|
||||
// input mode
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE10; /* clear mode for PA10: input mode */
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case U8X8_MSG_GPIO_MENU_SELECT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_NEXT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_PREV:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN));
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_MENU_HOME:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN));
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
21624
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock_2.dxf
Normal file
21624
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock_2.dxf
Normal file
File diff suppressed because it is too large
Load Diff
4712
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock_cube.dxf
Normal file
4712
basic-setup/components/u8g2/sys/arm/stm32l031x6/clock_cube.dxf
Normal file
File diff suppressed because it is too large
Load Diff
148
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/Makefile
Normal file
148
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/Makefile
Normal file
@@ -0,0 +1,148 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=drv8871
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
U8G2INC:=../../../../csrc/
|
||||
U8G2SRC:=$(wildcard ../../../../csrc/*.c)
|
||||
|
||||
# directory for FatFS
|
||||
#FFINC:=../fatfs
|
||||
#FFSRC:=$(wildcard ../fatfs/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
129
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/delay.c
Normal file
129
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/delay.c
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
1424
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/main.c
Normal file
1424
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/main.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
112
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/u8x8cb.c
Normal file
112
basic-setup/components/u8g2/sys/arm/stm32l031x6/drv8871/u8x8cb.c
Normal file
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
u8x8cb.c
|
||||
|
||||
STM32L031
|
||||
|
||||
PA13: Clock
|
||||
PA14: Data
|
||||
Both lines have a pullup resistor
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_GPIO_AND_DELAY_INIT:
|
||||
/* only support for software I2C*/
|
||||
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no open drain for PA10 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed for PA10 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown for PA10 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9 */
|
||||
//GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA9 */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no open drain for PA9 */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA9 */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA9 */
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
/* not required for SW I2C */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
/* not used at the moment */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_MILLI:
|
||||
delay_micro_seconds(arg_int*1000UL);
|
||||
break;
|
||||
case U8X8_MSG_DELAY_I2C:
|
||||
/* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */
|
||||
delay_micro_seconds(arg_int<=2?5:1);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_I2C_CLOCK:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_3; /* atomic clr PA9 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA9 */
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA9: input mode */
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_GPIO_I2C_DATA:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10 */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode for PA10 */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr PA10 */
|
||||
}
|
||||
else
|
||||
{
|
||||
//GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set PA10 */
|
||||
// input mode
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode for PA10: input mode */
|
||||
}
|
||||
break;
|
||||
/*
|
||||
case U8X8_MSG_GPIO_MENU_SELECT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_NEXT:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN));
|
||||
break;
|
||||
case U8X8_MSG_GPIO_MENU_PREV:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN));
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_MENU_HOME:
|
||||
u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN));
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
#
|
||||
# Generic and Simple GNU ARM Makefile
|
||||
#
|
||||
# Desinged for the gnu-arm-none-eabi tool chain
|
||||
#
|
||||
# Features
|
||||
# - create hex file
|
||||
# - create assembler listing (.dis)
|
||||
#
|
||||
# Limitations
|
||||
# - only C-files supported
|
||||
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
|
||||
#
|
||||
# Targets:
|
||||
# make
|
||||
# create hex file, no upload
|
||||
# make upload
|
||||
# create and upload hex file
|
||||
# make clean
|
||||
# delete all generated files
|
||||
#
|
||||
# Note:
|
||||
# Display list make database: make -p -f/dev/null | less
|
||||
#
|
||||
#================================================
|
||||
# External tools
|
||||
|
||||
# The base directory of gcc-arm-none-eabi
|
||||
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
|
||||
# If set, GCCBINPATH must contain a "/" at the end.
|
||||
GCCBINPATH:=/usr/bin/
|
||||
|
||||
#================================================
|
||||
# Project Information
|
||||
|
||||
# The name for the project
|
||||
TARGETNAME:=eval_board
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
|
||||
|
||||
# The CPU architecture (will be used for -mcpu)
|
||||
# for the LPC824, can we use "cortex-m0plus"?
|
||||
MCPU:=cortex-m0plus
|
||||
|
||||
# Include directory for the system include files
|
||||
SYSINC:=../stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
|
||||
|
||||
# Include directory for the u8g2 include files
|
||||
U8G2INC:=./u8x8/
|
||||
U8G2SRC:=$(wildcard ./u8x8/*.c)
|
||||
|
||||
# Directory for the linker script
|
||||
LDSCRIPTDIR:=.
|
||||
# Name of the linker script (must be the "keep" script, because the other script is not always working)
|
||||
LDSCRIPT:=stm32l031x6.ld
|
||||
|
||||
#================================================
|
||||
# Main part of the Makefile starts here. Usually no changes are needed.
|
||||
|
||||
# Internal Variable Names
|
||||
LIBNAME:=$(TARGETNAME).a
|
||||
ELFNAME:=$(TARGETNAME).elf
|
||||
HEXNAME:=$(TARGETNAME).hex
|
||||
DISNAME:=$(TARGETNAME).dis
|
||||
MAPNAME:=$(TARGETNAME).map
|
||||
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o)
|
||||
# $(SYSSRC:.c=.o) $(FFSRC:.c=.o)
|
||||
|
||||
# Replace standard build tools by arm tools
|
||||
AS:=$(GCCBINPATH)arm-none-eabi-as
|
||||
CC:=$(GCCBINPATH)arm-none-eabi-gcc
|
||||
AR:=$(GCCBINPATH)arm-none-eabi-ar
|
||||
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
|
||||
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
|
||||
SIZE:=$(GCCBINPATH)arm-none-eabi-size
|
||||
|
||||
# Common flags
|
||||
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
|
||||
COMMON_FLAGS += -DSTM32L031xx
|
||||
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
|
||||
# define stack size (defaults to 0x0100)
|
||||
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
|
||||
# COMMON_FLAGS += -Os -flto
|
||||
COMMON_FLAGS += -Os
|
||||
# COMMON_FLAGS += -fstack-protector
|
||||
# COMMON_FLAGS += -finstrument-functions
|
||||
# Do not use stand libs startup code. Uncomment this for gcclib procedures
|
||||
# memcpy still works, but might be required for __aeabi_uidiv
|
||||
# COMMON_FLAGS += -nostdlib
|
||||
# remove unused data and function
|
||||
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
|
||||
COMMON_FLAGS += -ffunction-sections -fdata-sections
|
||||
# the following seems to be required for newlib nano
|
||||
# COMMON_FLAGS += -fno-builtin
|
||||
# C flags
|
||||
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
|
||||
# LD flags
|
||||
# remove unreferenced procedures and variables, but __isr_vector
|
||||
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
|
||||
MAP:=-Wl,-Map=$(MAPNAME)
|
||||
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
|
||||
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
#LDLIBS:=--specs=nano.specs -specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
|
||||
|
||||
# implicit rules
|
||||
.elf.hex:
|
||||
$(OBJCOPY) -O ihex $< $@
|
||||
|
||||
|
||||
|
||||
# explicit rules
|
||||
|
||||
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
|
||||
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
|
||||
|
||||
$(DISNAME): $(ELFNAME)
|
||||
$(OBJDUMP) -D -S $< > $@
|
||||
|
||||
# create empty ssp libs for -fstack-protector-all -fstack-protector
|
||||
libssp.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
libssp_nonshared.a:
|
||||
$(AR) rcs $@
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
delay.c
|
||||
|
||||
The delay function delay_micro_seconds() will use the global variable
|
||||
SystemCoreClock. A call to SystemCoreClockUpdate() is required before
|
||||
using delay_micro_seconds().
|
||||
|
||||
STM32L031 Project (U8g2 Library)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
|
||||
/* Generic ARM delay procedure, based on the system timer (SysTick) */
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
The delay must be smaller than the RELOAD value.
|
||||
This delay has an imprecision of about +/- 20 system ticks.
|
||||
*/
|
||||
static void _delay_system_ticks_sub(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t start_val, end_val, curr_val;
|
||||
uint32_t load;
|
||||
|
||||
start_val = SysTick->VAL;
|
||||
start_val &= 0x0ffffffUL;
|
||||
end_val = start_val;
|
||||
|
||||
if ( end_val < sys_ticks )
|
||||
{
|
||||
/* check, if the operation after this if clause would lead to a negative result */
|
||||
/* if this would be the case, then add the reload value first */
|
||||
load = SysTick->LOAD;
|
||||
load &= 0x0ffffffUL;
|
||||
end_val += load;
|
||||
}
|
||||
/* counter goes towards zero, so end_val is below start value */
|
||||
end_val -= sys_ticks;
|
||||
|
||||
|
||||
/* wait until interval is left */
|
||||
if ( start_val >= end_val )
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val )
|
||||
break;
|
||||
if ( curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for(;;)
|
||||
{
|
||||
curr_val = SysTick->VAL;
|
||||
curr_val &= 0x0ffffffUL;
|
||||
if ( curr_val <= end_val && curr_val > start_val )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks)
|
||||
{
|
||||
uint32_t load4;
|
||||
load4 = SysTick->LOAD;
|
||||
load4 &= 0x0ffffffUL;
|
||||
load4 >>= 2;
|
||||
|
||||
while ( sys_ticks > load4 )
|
||||
{
|
||||
sys_ticks -= load4;
|
||||
_delay_system_ticks_sub(load4);
|
||||
}
|
||||
_delay_system_ticks_sub(sys_ticks);
|
||||
}
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must not overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us)
|
||||
{
|
||||
uint32_t sys_ticks;
|
||||
|
||||
sys_ticks = SystemCoreClock;
|
||||
sys_ticks /=1000000UL;
|
||||
sys_ticks *= us;
|
||||
delay_system_ticks(sys_ticks);
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
delay.h
|
||||
|
||||
LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _DELAY_H
|
||||
#define _DELAY_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*
|
||||
Delay by the provided number of system ticks.
|
||||
Any values between 0 and 0x0ffffffff are allowed.
|
||||
*/
|
||||
void delay_system_ticks(uint32_t sys_ticks);
|
||||
|
||||
/*
|
||||
Delay by the provided number of micro seconds.
|
||||
Limitation: "us" * System-Freq in MHz must now overflow in 32 bit.
|
||||
Values between 0 and 1.000.000 (1 second) are ok.
|
||||
|
||||
Important: Call SystemCoreClockUpdate() before calling this function.
|
||||
*/
|
||||
void delay_micro_seconds(uint32_t us);
|
||||
|
||||
#endif /* _DELAY_H */
|
||||
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
|
||||
Example for the STM32L031 Eval Board with 128x64 OLED at PA13/PA14
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
/*=======================================================================*/
|
||||
/* external functions */
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
/*=======================================================================*/
|
||||
/* global variables */
|
||||
|
||||
u8x8_t u8x8; // u8x8 object
|
||||
uint8_t u8x8_x, u8x8_y; // current position on the screen
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
|
||||
{
|
||||
SysTickCount++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setHSIClock()
|
||||
{
|
||||
|
||||
/* test if the current clock source is something else than HSI */
|
||||
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
{
|
||||
/* enable HSI */
|
||||
RCC->CR |= RCC_CR_HSION;
|
||||
/* wait until HSI becomes ready */
|
||||
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
|
||||
;
|
||||
|
||||
/* enable the HSI "divide by 4" bit */
|
||||
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
|
||||
/* wait until the "divide by 4" flag is enabled */
|
||||
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
|
||||
;
|
||||
|
||||
|
||||
/* then use the HSI clock */
|
||||
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
|
||||
|
||||
/* wait until HSI clock is used */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
|
||||
;
|
||||
}
|
||||
|
||||
/* disable PLL */
|
||||
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
|
||||
/* wait until PLL is inactive */
|
||||
while((RCC->CR & RCC_CR_PLLRDY) != 0)
|
||||
;
|
||||
|
||||
/* set latency to 1 wait state */
|
||||
FLASH->ACR |= FLASH_ACR_LATENCY;
|
||||
|
||||
/* At this point the HSI runs with 4 MHz */
|
||||
/* Multiply by 16 device by 2 --> 32 MHz */
|
||||
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
|
||||
|
||||
/* enable PLL */
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
|
||||
/* wait until the PLL is ready */
|
||||
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
|
||||
;
|
||||
|
||||
/* use the PLL has clock source */
|
||||
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
|
||||
/* wait until the PLL source is active */
|
||||
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
|
||||
;
|
||||
|
||||
SystemCoreClockUpdate(); /* Update SystemCoreClock global variable */
|
||||
}
|
||||
|
||||
/*
|
||||
Enable several power regions: PWR, GPIOA
|
||||
|
||||
This must be executed after each reset.
|
||||
*/
|
||||
void startUp(void)
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface (PWR) */
|
||||
PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR and RTC */
|
||||
|
||||
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/* u8x8 display procedures */
|
||||
|
||||
void initDisplay(void)
|
||||
{
|
||||
u8x8_Setup(&u8x8, u8x8_d_ssd1306_128x64_noname, u8x8_cad_ssd13xx_i2c, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0);
|
||||
u8x8_InitDisplay(&u8x8);
|
||||
u8x8_ClearDisplay(&u8x8);
|
||||
u8x8_SetPowerSave(&u8x8, 0);
|
||||
u8x8_SetFont(&u8x8, u8x8_font_amstrad_cpc_extended_r);
|
||||
u8x8_x = 0;
|
||||
u8x8_y = 0;
|
||||
}
|
||||
|
||||
|
||||
void outChar(uint8_t c)
|
||||
{
|
||||
if ( u8x8_x >= u8x8_GetCols(&u8x8) )
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y++;
|
||||
}
|
||||
u8x8_DrawGlyph(&u8x8, u8x8_x, u8x8_y, c);
|
||||
u8x8_x++;
|
||||
}
|
||||
|
||||
void outStr(const char *s)
|
||||
{
|
||||
while( *s )
|
||||
outChar(*s++);
|
||||
}
|
||||
|
||||
void outHexHalfByte(uint8_t b)
|
||||
{
|
||||
b &= 0x0f;
|
||||
if ( b < 10 )
|
||||
outChar(b+'0');
|
||||
else
|
||||
outChar(b+'a'-10);
|
||||
}
|
||||
|
||||
void outHex8(uint8_t b)
|
||||
{
|
||||
outHexHalfByte(b >> 4);
|
||||
outHexHalfByte(b);
|
||||
}
|
||||
|
||||
void outHex16(uint16_t v)
|
||||
{
|
||||
outHex8(v>>8);
|
||||
outHex8(v);
|
||||
}
|
||||
|
||||
void outHex32(uint32_t v)
|
||||
{
|
||||
outHex16(v>>16);
|
||||
outHex16(v);
|
||||
}
|
||||
|
||||
void setRow(uint8_t r)
|
||||
{
|
||||
u8x8_x = 0;
|
||||
u8x8_y = r;
|
||||
}
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
int main()
|
||||
{
|
||||
|
||||
setHSIClock(); /* enable 32 MHz Clock */
|
||||
startUp(); /* enable systick irq and several power regions */
|
||||
initDisplay(); /* aktivate display */
|
||||
|
||||
setRow(0); outStr("Hello World!");
|
||||
setRow(2); outStr("RCC_CSR:"); outHex32(RCC->CSR);
|
||||
setRow(3); outStr("PWR_CSR:"); outHex32(PWR->CSR);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x6.ld
|
||||
|
||||
Modified for stm32l0 from the original nokeep.ld script from the
|
||||
arm-none-eabi examples by olikraus@gmail.com
|
||||
|
||||
Assuming, that the original nokeep.ld file is available under
|
||||
the GNU General Public License, this file is available under the
|
||||
same license.
|
||||
|
||||
There are three modifications:
|
||||
|
||||
1. Provide symbols for the stm32l0 startup code
|
||||
|
||||
The following symbols are required for the stm32l0 startup
|
||||
code (e.g. startup_stm32l031xx.s)
|
||||
|
||||
_sidata start address for the initialization values of the .data section
|
||||
_sdata start address for the .data section. defined in linker script
|
||||
_edata end address for the .data section. defined in linker script
|
||||
_sbss start address for the .bss section. defined in linker script
|
||||
_ebss end address for the .bss section. defined in linker script
|
||||
_estack top address of the stack
|
||||
|
||||
2. Stack size estimation / calculation
|
||||
|
||||
_Stack_Size has been added to allow better stack size calculation
|
||||
|
||||
3. KEEP keywords
|
||||
|
||||
Additionall KEEPs added for .init and .fini. Without this KEEP the
|
||||
generated code will not work, because of the missing _init function.
|
||||
|
||||
4. Bugfix: Allign the end of the flash area
|
||||
|
||||
*/
|
||||
|
||||
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
|
||||
|
||||
|
||||
/* Linker script to configure memory regions.
|
||||
* Need modifying for a specific board.
|
||||
* FLASH.ORIGIN: starting address of flash
|
||||
* FLASH.LENGTH: length of flash
|
||||
* RAM.ORIGIN: starting address of RAM bank 0
|
||||
* RAM.LENGTH: length of RAM bank 0
|
||||
*/
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
|
||||
}
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with other linker script that defines memory regions FLASH and RAM.
|
||||
* It references following symbols, which must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines following symbols, which code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __copy_table_start__
|
||||
* __copy_table_end__
|
||||
* __zero_table_start__
|
||||
* __zero_table_end__
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.isr_vector))
|
||||
*(.text*)
|
||||
|
||||
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
|
||||
/* ... sooo.... better keep the init and fini sections */
|
||||
|
||||
KEEP ( *(.init) )
|
||||
KEEP ( *(.fini) )
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
*(.eh_frame*)
|
||||
|
||||
/* allign the end of the flash area */
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
/* To copy multiple ROM to RAM sections,
|
||||
* uncomment .copy.table section and,
|
||||
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.copy.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__copy_table_start__ = .;
|
||||
LONG (__etext)
|
||||
LONG (__data_start__)
|
||||
LONG (__data_end__ - __data_start__)
|
||||
LONG (__etext2)
|
||||
LONG (__data2_start__)
|
||||
LONG (__data2_end__ - __data2_start__)
|
||||
__copy_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
/* To clear multiple BSS sections,
|
||||
* uncomment .zero.table section and,
|
||||
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
|
||||
/*
|
||||
.zero.table :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__zero_table_start__ = .;
|
||||
LONG (__bss_start__)
|
||||
LONG (__bss_end__ - __bss_start__)
|
||||
LONG (__bss2_start__)
|
||||
LONG (__bss2_end__ - __bss2_start__)
|
||||
__zero_table_end__ = .;
|
||||
} > FLASH
|
||||
*/
|
||||
|
||||
__etext = .;
|
||||
_sidata = .; /* for stm32l0 startup code */
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
_sdata = .; /* for stm32l0 startup code */
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
*(.preinit_array)
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
*(SORT(.init_array.*))
|
||||
*(.init_array)
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
*(SORT(.fini_array.*))
|
||||
*(.fini_array)
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
_edata = .; /* for stm32l0 startup code */
|
||||
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
_sbss = .; /* for stm32l0 startup code */
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
_ebss = .; /* for stm32l0 startup code */
|
||||
} > RAM
|
||||
|
||||
.heap (COPY):
|
||||
{
|
||||
__end__ = .;
|
||||
PROVIDE(end = .);
|
||||
*(.heap*)
|
||||
__HeapLimit = .;
|
||||
} > RAM
|
||||
|
||||
/* .stack_dummy section doesn't contains any symbols. It is only
|
||||
* used for linker to calculate size of stack sections, and assign
|
||||
* values to stack symbols later */
|
||||
.stack_dummy (COPY):
|
||||
{
|
||||
*(.stack*)
|
||||
. = . + _Stack_Size; /* estimated stack size */
|
||||
} > RAM
|
||||
|
||||
/* Set stack top to end of RAM, and stack limit move down by
|
||||
* size of stack_dummy section */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_estack = __StackTop; /* for stm32l0 startup code */
|
||||
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
|
||||
/* Check if data + heap + stack exceeds RAM limit */
|
||||
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
|
||||
}
|
||||
@@ -0,0 +1,965 @@
|
||||
/*
|
||||
|
||||
u8x8.h
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
U8glib has several layers. Each layer is implemented with a callback function.
|
||||
This callback function handels the messages for the layer.
|
||||
|
||||
The topmost level is the display layer. It includes the following messages:
|
||||
|
||||
U8X8_MSG_DISPLAY_SETUP_MEMORY no communicaation with the display, setup memory ony
|
||||
U8X8_MSG_DISPLAY_INIT
|
||||
U8X8_MSG_DISPLAY_SET_FLIP_MODE
|
||||
U8X8_MSG_DISPLAY_SET_POWER_SAVE
|
||||
U8X8_MSG_DISPLAY_SET_CONTRAST
|
||||
U8X8_MSG_DISPLAY_DRAW_TILE
|
||||
|
||||
A display driver may decided to breakdown these messages to a lower level interface or
|
||||
implement this functionality directly.
|
||||
|
||||
|
||||
One layer is the Command/Arg/Data interface. It can be used by the display layer
|
||||
to communicate with the display hardware.
|
||||
This layer only deals with data, commands and arguments. D/C line is unknown.
|
||||
U8X8_MSG_CAD_INIT
|
||||
U8X8_MSG_CAD_SET_I2C_ADR (obsolete)
|
||||
U8X8_MSG_CAD_SET_DEVICE (obsolete)
|
||||
U8X8_MSG_CAD_START_TRANSFER
|
||||
U8X8_MSG_CAD_SEND_CMD
|
||||
U8X8_MSG_CAD_SEND_ARG
|
||||
U8X8_MSG_CAD_SEND_DATA
|
||||
U8X8_MSG_CAD_END_TRANSFER
|
||||
|
||||
The byte interface is there to send 1 byte (8 bits) to the display hardware.
|
||||
This layer depends on the hardware of a microcontroller, if a specific hardware
|
||||
should be used (I2C or SPI).
|
||||
If this interface is implemented via software, it may use the GPIO level for sending
|
||||
bytes.
|
||||
U8X8_MSG_BYTE_INIT
|
||||
U8X8_MSG_BYTE_SEND 30
|
||||
U8X8_MSG_BYTE_SET_DC 31
|
||||
U8X8_MSG_BYTE_START_TRANSFER
|
||||
U8X8_MSG_BYTE_END_TRANSFER
|
||||
U8X8_MSG_BYTE_SET_I2C_ADR (obsolete)
|
||||
U8X8_MSG_BYTE_SET_DEVICE (obsolete)
|
||||
|
||||
GPIO and Delay
|
||||
U8X8_MSG_GPIO_INIT
|
||||
U8X8_MSG_DELAY_MILLI
|
||||
U8X8_MSG_DELAY_10MICRO
|
||||
U8X8_MSG_DELAY_100NANO
|
||||
U8X8_MSG_DELAY_NANO
|
||||
*/
|
||||
|
||||
#ifndef _U8X8_H
|
||||
#define _U8X8_H
|
||||
|
||||
/*==========================================*/
|
||||
/* Global Defines */
|
||||
|
||||
/* Undefine this to remove u8x8_SetContrast function */
|
||||
#define U8X8_WITH_SET_CONTRAST
|
||||
|
||||
/* Define this for an additional user pointer inside the u8x8 data struct */
|
||||
//#define U8X8_WITH_USER_PTR
|
||||
|
||||
|
||||
/* Undefine this to remove u8x8_SetFlipMode function */
|
||||
/* 26 May 2016: Obsolete */
|
||||
//#define U8X8_WITH_SET_FLIP_MODE
|
||||
|
||||
/* Select 0 or 1 for the default flip mode. This is not affected by U8X8_WITH_FLIP_MODE */
|
||||
/* Note: Not all display types support a mirror functon for the frame buffer */
|
||||
/* 26 May 2016: Obsolete */
|
||||
//#define U8X8_DEFAULT_FLIP_MODE 0
|
||||
|
||||
/*==========================================*/
|
||||
/* Includes */
|
||||
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#if defined(__GNUC__) && defined(__AVR__)
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
/*==========================================*/
|
||||
/* C++ compatible */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* U8G2 internal defines */
|
||||
|
||||
/* the following macro returns the first value for the normal mode */
|
||||
/* or the second argument for the flip mode */
|
||||
|
||||
/* 26 May 2016: Obsolete
|
||||
#if U8X8_DEFAULT_FLIP_MODE == 0
|
||||
#define U8X8_IF_DEFAULT_NORMAL_OR_FLIP(normal, flipmode) (normal)
|
||||
#else
|
||||
#define U8X8_IF_DEFAULT_NORMAL_OR_FLIP(normal, flipmode) (flipmode)
|
||||
#endif
|
||||
*/
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define U8X8_NOINLINE __attribute__((noinline))
|
||||
# define U8X8_SECTION(name) __attribute__ ((section (name)))
|
||||
# define U8X8_UNUSED __attribute__((unused))
|
||||
#else
|
||||
# define U8X8_SECTION(name)
|
||||
# define U8X8_NOINLINE
|
||||
# define U8X8_UNUSED
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(__AVR__)
|
||||
# define U8X8_FONT_SECTION(name) U8X8_SECTION(".progmem." name)
|
||||
# define u8x8_pgm_read(adr) pgm_read_byte_near(adr)
|
||||
# define U8X8_PROGMEM PROGMEM
|
||||
#endif
|
||||
|
||||
#if defined(ESP8266)
|
||||
uint8_t u8x8_pgm_read_esp(const uint8_t * addr); /* u8x8_8x8.c */
|
||||
# define U8X8_FONT_SECTION(name) __attribute__((section(".text." name)))
|
||||
# define u8x8_pgm_read(adr) u8x8_pgm_read_esp(adr)
|
||||
# define U8X8_PROGMEM
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef U8X8_FONT_SECTION
|
||||
# define U8X8_FONT_SECTION(name)
|
||||
#endif
|
||||
|
||||
#ifndef u8x8_pgm_read
|
||||
# define u8x8_pgm_read(adr) (*(const uint8_t *)(adr))
|
||||
#endif
|
||||
|
||||
#ifndef U8X8_PROGMEM
|
||||
# define U8X8_PROGMEM
|
||||
#endif
|
||||
|
||||
#ifdef ARDUINO
|
||||
#define U8X8_USE_PINS
|
||||
#endif
|
||||
|
||||
/*==========================================*/
|
||||
/* U8X8 typedefs and data structures */
|
||||
|
||||
|
||||
typedef struct u8x8_struct u8x8_t;
|
||||
typedef struct u8x8_display_info_struct u8x8_display_info_t;
|
||||
typedef struct u8x8_tile_struct u8x8_tile_t;
|
||||
|
||||
typedef uint8_t (*u8x8_msg_cb)(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
typedef uint16_t (*u8x8_char_cb)(u8x8_t *u8x8, uint8_t b);
|
||||
|
||||
|
||||
|
||||
|
||||
//struct u8x8_mcd_struct
|
||||
//{
|
||||
// u8x8_msg_cb cb; /* current callback function */
|
||||
// u8x8_t *u8g2; /* pointer to the u8g2 parent to minimize the number of args */
|
||||
// u8x8_mcd_t *next;
|
||||
//};
|
||||
|
||||
struct u8x8_tile_struct
|
||||
{
|
||||
uint8_t *tile_ptr; /* pointer to one or more tiles... should be "const" */
|
||||
uint8_t cnt; /* number of tiles */
|
||||
uint8_t x_pos; /* tile x position */
|
||||
uint8_t y_pos; /* tile x position */
|
||||
};
|
||||
|
||||
|
||||
struct u8x8_display_info_struct
|
||||
{
|
||||
/* == general == */
|
||||
|
||||
uint8_t chip_enable_level; /* UC1601: 0 */
|
||||
uint8_t chip_disable_level; /* opposite of chip_enable_level */
|
||||
|
||||
uint8_t post_chip_enable_wait_ns; /* UC1601: 5ns */
|
||||
uint8_t pre_chip_disable_wait_ns; /* UC1601: 5ns */
|
||||
uint8_t reset_pulse_width_ms; /* UC1601: 0.003ms --> 1ms */
|
||||
uint8_t post_reset_wait_ms; /* UC1601: 6ms */
|
||||
|
||||
|
||||
/* == SPI interface == */
|
||||
|
||||
/* after SDA has been applied, wait this much time for the SCK data takeover edge */
|
||||
/* if this is smaller than sck_pulse_width_ns, then use the value from sck_pulse_width_ns */
|
||||
uint8_t sda_setup_time_ns; /* UC1601: 12ns */
|
||||
/* the pulse width of the the clock signal, cycle time is twice this value */
|
||||
/* max freq is 1/(2*sck_pulse_width_ns) */
|
||||
/* AVR: below 70: DIV2, 8 MHz, >= 70 --> 4MHz clock (DIV4) */
|
||||
uint8_t sck_pulse_width_ns; /* UC1701: 50ns */
|
||||
|
||||
/* until here we have 8 bytes (uint8_t). Newly introduced for SPI.beginTransaction */
|
||||
uint32_t sck_clock_hz;
|
||||
|
||||
/* previous name "sck_takeover_edge" renamed to "spi_mode" */
|
||||
/* bit 0 of spi_mode is equal to the value of the previous variable sck_takeover_edge, 20 Aug 16: This is wrong the bit is actually inverted */
|
||||
/* SPI has four clock modes: */
|
||||
/* 0: clock active high, data out on falling edge, clock default value is zero, takover on rising edge */
|
||||
/* 1: clock active high, data out on rising edge, clock default value is zero, takover on falling edge */
|
||||
/* 2: clock active low, data out on rising edge */
|
||||
/* 3: clock active low, data out on falling edge */
|
||||
/* most displays have clock mode 1 */
|
||||
uint8_t spi_mode;
|
||||
|
||||
/* == I2C == */
|
||||
uint8_t i2c_bus_clock_100kHz; /* UC1601: 1000000000/275 = 37 *100k */
|
||||
|
||||
|
||||
/* == 8 bit interface == */
|
||||
|
||||
/* how long to wait after all data line are set */
|
||||
uint8_t data_setup_time_ns; /* UC1601: 30ns */
|
||||
/* write enable pulse width */
|
||||
uint8_t write_pulse_width_ns; /* UC1601: 40ns */
|
||||
|
||||
/* == layout == */
|
||||
uint8_t tile_width;
|
||||
uint8_t tile_height;
|
||||
|
||||
uint8_t default_x_offset; /* default x offset for the display */
|
||||
uint8_t flipmode_x_offset; /* x offset, if flip mode is enabled */
|
||||
|
||||
/* pixel width is not used by the u8x8 procedures */
|
||||
/* instead it will be used by the u8g2 procedures, because the pixel dimension can */
|
||||
/* not always be calculated from the tile_width/_height */
|
||||
/* the following conditions must be true: */
|
||||
/* pixel_width <= tile_width*8 */
|
||||
/* pixel_height <= tile_height*8 */
|
||||
uint16_t pixel_width;
|
||||
uint16_t pixel_height;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* list of U8x8 pins */
|
||||
#define U8X8_PIN_D0 0
|
||||
#define U8X8_PIN_SPI_CLOCK 0
|
||||
#define U8X8_PIN_D1 1
|
||||
#define U8X8_PIN_SPI_DATA 1
|
||||
#define U8X8_PIN_D2 2
|
||||
#define U8X8_PIN_D3 3
|
||||
#define U8X8_PIN_D4 4
|
||||
#define U8X8_PIN_D5 5
|
||||
#define U8X8_PIN_D6 6
|
||||
#define U8X8_PIN_D7 7
|
||||
|
||||
#define U8X8_PIN_E 8
|
||||
#define U8X8_PIN_CS 9 /* parallel, SPI */
|
||||
#define U8X8_PIN_DC 10 /* parallel, SPI */
|
||||
#define U8X8_PIN_RESET 11 /* parallel, SPI, I2C */
|
||||
|
||||
#define U8X8_PIN_I2C_CLOCK 12 /* 1 = Input/high impedance, 0 = drive low */
|
||||
#define U8X8_PIN_I2C_DATA 13 /* 1 = Input/high impedance, 0 = drive low */
|
||||
|
||||
#define U8X8_PIN_CS1 14 /* KS0108 extra chip select */
|
||||
#define U8X8_PIN_CS2 15 /* KS0108 extra chip select */
|
||||
|
||||
#define U8X8_PIN_OUTPUT_CNT 16
|
||||
|
||||
#define U8X8_PIN_MENU_SELECT 16
|
||||
#define U8X8_PIN_MENU_NEXT 17
|
||||
#define U8X8_PIN_MENU_PREV 18
|
||||
#define U8X8_PIN_MENU_HOME 19
|
||||
#define U8X8_PIN_MENU_UP 20
|
||||
#define U8X8_PIN_MENU_DOWN 21
|
||||
|
||||
#define U8X8_PIN_INPUT_CNT 6
|
||||
|
||||
#ifdef U8X8_USE_PINS
|
||||
#define U8X8_PIN_CNT (U8X8_PIN_OUTPUT_CNT+U8X8_PIN_INPUT_CNT)
|
||||
#define U8X8_PIN_NONE 255
|
||||
#endif
|
||||
|
||||
struct u8x8_struct
|
||||
{
|
||||
const u8x8_display_info_t *display_info;
|
||||
u8x8_char_cb next_cb; /* procedure, which will be used to get the next char from the string */
|
||||
u8x8_msg_cb display_cb;
|
||||
u8x8_msg_cb cad_cb;
|
||||
u8x8_msg_cb byte_cb;
|
||||
u8x8_msg_cb gpio_and_delay_cb;
|
||||
const uint8_t *font;
|
||||
uint16_t encoding; /* encoding result for utf8 decoder in next_cb */
|
||||
uint8_t x_offset; /* copied from info struct, can be modified in flip mode */
|
||||
uint8_t is_font_inverse_mode; /* 0: normal, 1: font glyphs are inverted */
|
||||
uint8_t i2c_address; /* a valid i2c adr. Initially this is 255, but this is set to something usefull during DISPLAY_INIT */
|
||||
/* i2c_address is the address for writing data to the display */
|
||||
/* usually, the lowest bit must be zero for a valid address */
|
||||
uint8_t i2c_started; /* for i2c interface */
|
||||
uint8_t device_address; /* this is the device address, replacement for U8X8_MSG_CAD_SET_DEVICE */
|
||||
uint8_t utf8_state; /* number of chars which are still to scan */
|
||||
uint8_t gpio_result; /* return value from the gpio call (only for MENU keys at the moment) */
|
||||
uint8_t debounce_default_pin_state;
|
||||
uint8_t debounce_last_pin_state;
|
||||
uint8_t debounce_state;
|
||||
uint8_t debounce_result_msg; /* result msg or event after debounce */
|
||||
#ifdef U8X8_WITH_USER_PTR
|
||||
void *user_ptr;
|
||||
#endif
|
||||
#ifdef U8X8_USE_PINS
|
||||
uint8_t pins[U8X8_PIN_CNT]; /* defines a pinlist: Mainly a list of pins for the Arduino Envionment, use U8X8_PIN_xxx to access */
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef U8X8_WITH_USER_PTR
|
||||
#define u8x8_GetUserPtr(u8x8) ((u8x8)->user_ptr)
|
||||
#define u8x8_SetUserPtr(u8x8, p) ((u8x8)->user_ptr = (p))
|
||||
#endif
|
||||
|
||||
|
||||
#define u8x8_GetCols(u8x8) ((u8x8)->display_info->tile_width)
|
||||
#define u8x8_GetRows(u8x8) ((u8x8)->display_info->tile_height)
|
||||
#define u8x8_GetI2CAddress(u8x8) ((u8x8)->i2c_address)
|
||||
#define u8x8_SetI2CAddress(u8x8, address) ((u8x8)->i2c_address = (address))
|
||||
|
||||
#define u8x8_SetGPIOResult(u8x8, val) ((u8x8)->gpio_result = (val))
|
||||
#define u8x8_GetSPIClockPhase(u8x8) ((u8x8)->display_info->spi_mode & 0x01) /* 0 means rising edge */
|
||||
#define u8x8_GetSPIClockPolarity(u8x8) (((u8x8)->display_info->spi_mode & 0x02) >> 1)
|
||||
#define u8x8_GetSPIClockDefaultLevel(u8x8) (((u8x8)->display_info->spi_mode & 0x02) >> 1)
|
||||
|
||||
|
||||
#ifdef U8X8_USE_PINS
|
||||
#define u8x8_SetPin(u8x8,pin,val) (u8x8)->pins[pin] = (val)
|
||||
#define u8x8_SetMenuSelectPin(u8x8, val) u8x8_SetPin((u8x8),U8X8_PIN_MENU_SELECT,(val))
|
||||
#define u8x8_SetMenuNextPin(u8x8, val) u8x8_SetPin((u8x8),U8X8_PIN_MENU_NEXT,(val))
|
||||
#define u8x8_SetMenuPrevPin(u8x8, val) u8x8_SetPin((u8x8),U8X8_PIN_MENU_PREV,(val))
|
||||
#define u8x8_SetMenuHomePin(u8x8, val) u8x8_SetPin((u8x8),U8X8_PIN_MENU_HOME,(val))
|
||||
#define u8x8_SetMenuUpPin(u8x8, val) u8x8_SetPin((u8x8),U8X8_PIN_MENU_UP,(val))
|
||||
#define u8x8_SetMenuDownPin(u8x8, val) u8x8_SetPin((u8x8),U8X8_PIN_MENU_DOWN,(val))
|
||||
#endif
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
|
||||
/* helper functions */
|
||||
void u8x8_d_helper_display_setup_memory(u8x8_t *u8x8, const u8x8_display_info_t *display_info);
|
||||
void u8x8_d_helper_display_init(u8x8_t *u8g2);
|
||||
|
||||
/* Display Interface */
|
||||
|
||||
/*
|
||||
Name: U8X8_MSG_DISPLAY_SETUP_MEMORY
|
||||
Args: None
|
||||
Tasks:
|
||||
1) setup u8g2->display_info
|
||||
copy u8g2->display_info->default_x_offset to u8g2->x_offset
|
||||
|
||||
usually calls u8x8_d_helper_display_setup_memory()
|
||||
*/
|
||||
#define U8X8_MSG_DISPLAY_SETUP_MEMORY 9
|
||||
|
||||
/*
|
||||
Name: U8X8_MSG_DISPLAY_INIT
|
||||
Args: None
|
||||
Tasks:
|
||||
|
||||
2) put interface into default state:
|
||||
execute u8x8_gpio_Init for port directions
|
||||
execute u8x8_cad_Init for default port levels
|
||||
3) set CS status (not clear, may be done in cad/byte interface
|
||||
4) execute display reset (gpio interface)
|
||||
5) send setup sequence to display, do not activate display, disable "power save" will follow
|
||||
*/
|
||||
#define U8X8_MSG_DISPLAY_INIT 10
|
||||
|
||||
/*
|
||||
Name: U8X8_MSG_DISPLAY_SET_POWER_SAVE
|
||||
Args: arg_int: 0: normal mode (RAM is visible on the display), 1: nothing is shown
|
||||
Tasks:
|
||||
Depending on arg_int, put the display into normal or power save mode.
|
||||
Send the corresponding sequence to the display.
|
||||
In power save mode, it must be possible to modify the RAM content.
|
||||
*/
|
||||
#define U8X8_MSG_DISPLAY_SET_POWER_SAVE 11
|
||||
|
||||
/*
|
||||
Name: U8X8_MSG_DISPLAY_SET_FLIP_MODE
|
||||
Args: arg_int: 0: normal mode, 1: flipped HW screen (180 degree)
|
||||
Tasks:
|
||||
Reprogramms the display controller to rotate the display by
|
||||
180 degree (arg_int = 1) or not (arg_int = 0)
|
||||
This may change u8g2->x_offset if the display is smaller than the controller ram
|
||||
This message should only be supported if U8X8_WITH_FLIP_MODE is defined.
|
||||
*/
|
||||
#define U8X8_MSG_DISPLAY_SET_FLIP_MODE 13
|
||||
|
||||
/* arg_int: 0..255 contrast value */
|
||||
#define U8X8_MSG_DISPLAY_SET_CONTRAST 14
|
||||
|
||||
/*
|
||||
Name: U8X8_MSG_DISPLAY_DRAW_TILE
|
||||
Args:
|
||||
arg_int: How often to repeat this tile pattern
|
||||
arg_ptr: pointer to u8x8_tile_t
|
||||
uint8_t *tile_ptr; pointer to one or more tiles (number is "cnt")
|
||||
uint8_t cnt; number of tiles
|
||||
uint8_t x_pos; first tile x position
|
||||
uint8_t y_pos; first tile y position
|
||||
Tasks:
|
||||
One tile has exactly 8 bytes (8x8 pixel monochrome bitmap).
|
||||
The lowest bit of the first byte is the upper left corner
|
||||
The highest bit of the first byte is the lower left corner
|
||||
The lowest bit of the last byte is the upper right corner
|
||||
The highest bit of the last byte is the lower left corner
|
||||
"tile_ptr" is the address of a memory area, which contains
|
||||
one or more tiles. "cnt" will contain the exact number of
|
||||
tiles in the memory areay. The size of the memory area is 8*cnt;
|
||||
Multiple tiles in the memory area form a horizontal sequence, this
|
||||
means the first tile is drawn at x_pos/y_pos, the second tile is drawn
|
||||
at x_pos+1/y_pos, third at x_pos+2/y_pos.
|
||||
"arg_int" tells how often the tile sequence should be repeated:
|
||||
For example if "cnt" is two and tile_ptr points to tiles A and B,
|
||||
then for arg_int = 3, the following tile sequence will be drawn:
|
||||
ABABAB. Totally, cnt*arg_int tiles will be drawn.
|
||||
|
||||
*/
|
||||
#define U8X8_MSG_DISPLAY_DRAW_TILE 15
|
||||
|
||||
|
||||
/*
|
||||
Name: U8X8_MSG_DISPLAY_REFRESH
|
||||
Args:
|
||||
arg_int: -
|
||||
arg_ptr: -
|
||||
|
||||
This was introduced for the SSD1606 eInk display.
|
||||
The problem is, that all RAM access will not appear on the screen
|
||||
unless a special command is executed. With this message, this command
|
||||
sequence is executed.
|
||||
Use
|
||||
void u8x8_RefreshDisplay(u8x8_t *u8x8)
|
||||
to send the message to the display handler.
|
||||
*/
|
||||
#define U8X8_MSG_DISPLAY_REFRESH 16
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_setup.c */
|
||||
|
||||
/*
|
||||
Setup u8x8 object itself. This should be the very first function
|
||||
called on the new u8x8 object. After this call, assign the callback
|
||||
functions. Optional: Set the pins
|
||||
*/
|
||||
|
||||
void u8x8_SetupDefaults(u8x8_t *u8x8); /* do not use this, use u8x8_Setup() instead */
|
||||
|
||||
void u8x8_Setup(u8x8_t *u8x8, u8x8_msg_cb display_cb, u8x8_msg_cb cad_cb, u8x8_msg_cb byte_cb, u8x8_msg_cb gpio_and_delay_cb);
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_display.c */
|
||||
uint8_t u8x8_DrawTile(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t cnt, uint8_t *tile_ptr);
|
||||
|
||||
/*
|
||||
After a call to u8x8_SetupDefaults,
|
||||
setup u8x8 memory structures & inform callbacks
|
||||
This function is also called from u8x8_Setup(), so do not call u8x8_SetupMemory()
|
||||
directly, but use u8x8_Setup() instead.
|
||||
*/
|
||||
void u8x8_SetupMemory(u8x8_t *u8x8);
|
||||
|
||||
/*
|
||||
After calling u8x8_SetupMemory()/u8x8_Setup(), init the display hardware itself.
|
||||
This will will the first time, u8x8 talks to the display.
|
||||
It will init the display, but keep display in power save mode.
|
||||
Usually this command must be followed by u8x8_SetPowerSave()
|
||||
*/
|
||||
void u8x8_InitDisplay(u8x8_t *u8x8);
|
||||
/* wake up display from power save mode */
|
||||
void u8x8_SetPowerSave(u8x8_t *u8x8, uint8_t is_enable);
|
||||
void u8x8_SetFlipMode(u8x8_t *u8x8, uint8_t mode);
|
||||
void u8x8_SetContrast(u8x8_t *u8x8, uint8_t value);
|
||||
void u8x8_ClearDisplayWithTile(u8x8_t *u8x8, const uint8_t *buf) U8X8_NOINLINE;
|
||||
void u8x8_ClearDisplay(u8x8_t *u8x8); // this does not work for u8g2 in some cases
|
||||
void u8x8_FillDisplay(u8x8_t *u8x8);
|
||||
void u8x8_RefreshDisplay(u8x8_t *u8x8); // make RAM content visible on the display (Dec 16: SSD1606 only)
|
||||
void u8x8_ClearLine(u8x8_t *u8x8, uint8_t line);
|
||||
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* Command Arg Data (CAD) Interface */
|
||||
|
||||
/*
|
||||
U8X8_MSG_CAD_INIT
|
||||
no args
|
||||
call U8X8_MSG_BYTE_INIT
|
||||
setup default values for the I/O lines
|
||||
*/
|
||||
#define U8X8_MSG_CAD_INIT 20
|
||||
|
||||
|
||||
#define U8X8_MSG_CAD_SEND_CMD 21
|
||||
/* arg_int: cmd byte */
|
||||
#define U8X8_MSG_CAD_SEND_ARG 22
|
||||
/* arg_int: arg byte */
|
||||
#define U8X8_MSG_CAD_SEND_DATA 23
|
||||
/* arg_int: expected cs level after processing this msg */
|
||||
#define U8X8_MSG_CAD_START_TRANSFER 24
|
||||
/* arg_int: expected cs level after processing this msg */
|
||||
#define U8X8_MSG_CAD_END_TRANSFER 25
|
||||
/* arg_int = 0: disable chip, arg_int = 1: enable chip */
|
||||
//#define U8X8_MSG_CAD_SET_I2C_ADR 26
|
||||
//#define U8X8_MSG_CAD_SET_DEVICE 27
|
||||
|
||||
|
||||
|
||||
/* u8g_cad.c */
|
||||
|
||||
#define u8x8_cad_Init(u8x8) ((u8x8)->cad_cb((u8x8), U8X8_MSG_CAD_INIT, 0, NULL ))
|
||||
|
||||
uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd) U8X8_NOINLINE;
|
||||
uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg) U8X8_NOINLINE;
|
||||
uint8_t u8x8_cad_SendMultipleArg(u8x8_t *u8x8, uint8_t cnt, uint8_t arg) U8X8_NOINLINE;
|
||||
uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data) U8X8_NOINLINE;
|
||||
uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8) U8X8_NOINLINE;
|
||||
uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8) U8X8_NOINLINE;
|
||||
|
||||
/*
|
||||
#define U8X8_C(c0) (0x04), (c0)
|
||||
#define U8X8_CA(c0,a0) (0x05), (c0), (a0)
|
||||
#define U8X8_CAA(c0,a0,a1) (0x06), (c0), (a0), (a1)
|
||||
#define U8X8_DATA() (0x10)
|
||||
#define U8X8_D1(d0) (0x11), (d0)
|
||||
*/
|
||||
|
||||
#define U8X8_C(c0) (U8X8_MSG_CAD_SEND_CMD), (c0)
|
||||
#define U8X8_A(a0) (U8X8_MSG_CAD_SEND_ARG), (a0)
|
||||
#define U8X8_CA(c0,a0) (U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_ARG), (a0)
|
||||
#define U8X8_CAA(c0,a0,a1) (U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1)
|
||||
#define U8X8_CAAAA(c0,a0,a1,a2,a3) (U8X8_MSG_CAD_SEND_CMD), (c0), (U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1), (U8X8_MSG_CAD_SEND_ARG), (a2), (U8X8_MSG_CAD_SEND_ARG), (a3)
|
||||
#define U8X8_AAC(a0,a1,c0) (U8X8_MSG_CAD_SEND_ARG), (a0), (U8X8_MSG_CAD_SEND_ARG), (a1), (U8X8_MSG_CAD_SEND_CMD), (c0)
|
||||
#define U8X8_D1(d0) (U8X8_MSG_CAD_SEND_DATA), (d0)
|
||||
|
||||
#define U8X8_A4(a0,a1,a2,a3) U8X8_A(a0), U8X8_A(a1), U8X8_A(a2), U8X8_A(a3)
|
||||
#define U8X8_A8(a0,a1,a2,a3,a4,a5,a6,a7) U8X8_A4((a0), (a1), (a2), (a3)), U8X8_A4((a4), (a5), (a6), (a7))
|
||||
|
||||
|
||||
#define U8X8_START_TRANSFER() (U8X8_MSG_CAD_START_TRANSFER)
|
||||
#define U8X8_END_TRANSFER() (U8X8_MSG_CAD_END_TRANSFER)
|
||||
#define U8X8_DLY(m) (0xfe),(m) /* delay in milli seconds */
|
||||
#define U8X8_END() (0xff)
|
||||
|
||||
void u8x8_cad_SendSequence(u8x8_t *u8x8, uint8_t const *data);
|
||||
uint8_t u8x8_cad_empty(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_110(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_001(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_011(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_st7920_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_st75256_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_ld7032_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_cad_uc16xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* Byte Interface */
|
||||
|
||||
#define U8X8_MSG_BYTE_INIT U8X8_MSG_CAD_INIT
|
||||
#define U8X8_MSG_BYTE_SET_DC 32
|
||||
|
||||
#define U8X8_MSG_BYTE_SEND U8X8_MSG_CAD_SEND_DATA
|
||||
|
||||
#define U8X8_MSG_BYTE_START_TRANSFER U8X8_MSG_CAD_START_TRANSFER
|
||||
#define U8X8_MSG_BYTE_END_TRANSFER U8X8_MSG_CAD_END_TRANSFER
|
||||
|
||||
//#define U8X8_MSG_BYTE_SET_I2C_ADR U8X8_MSG_CAD_SET_I2C_ADR
|
||||
//#define U8X8_MSG_BYTE_SET_DEVICE U8X8_MSG_CAD_SET_DEVICE
|
||||
|
||||
|
||||
uint8_t u8x8_byte_SetDC(u8x8_t *u8x8, uint8_t dc) U8X8_NOINLINE;
|
||||
uint8_t u8x8_byte_SendByte(u8x8_t *u8x8, uint8_t byte) U8X8_NOINLINE;
|
||||
uint8_t u8x8_byte_SendBytes(u8x8_t *u8x8, uint8_t cnt, uint8_t *data) U8X8_NOINLINE;
|
||||
uint8_t u8x8_byte_StartTransfer(u8x8_t *u8x8);
|
||||
uint8_t u8x8_byte_EndTransfer(u8x8_t *u8x8);
|
||||
|
||||
uint8_t u8x8_byte_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_byte_8bit_6800mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_byte_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_byte_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
/* uint8_t u8x8_byte_st7920_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); */
|
||||
void u8x8_byte_set_ks0108_cs(u8x8_t *u8x8, uint8_t arg) U8X8_NOINLINE;
|
||||
uint8_t u8x8_byte_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_byte_ssd13xx_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); /* OBSOLETE! */
|
||||
uint8_t u8x8_byte_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_byte_sed1520(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* GPIO Interface */
|
||||
|
||||
|
||||
/*
|
||||
U8X8_MSG_GPIO_AND_DELAY_INIT
|
||||
no args
|
||||
setup port directions, do not set IO levels, this is done with BYTE/CAD_INIT
|
||||
*/
|
||||
#define U8X8_MSG_GPIO_AND_DELAY_INIT 40
|
||||
|
||||
/* arg_int: milliseconds */
|
||||
#define U8X8_MSG_DELAY_MILLI 41
|
||||
|
||||
/* 10MICRO and 100NANO are not used at the moment */
|
||||
#define U8X8_MSG_DELAY_10MICRO 42
|
||||
#define U8X8_MSG_DELAY_100NANO 43
|
||||
|
||||
|
||||
#define U8X8_MSG_DELAY_NANO 44
|
||||
/* delay of one i2c unit, should be 5us for 100K, and 1.25us for 400K */
|
||||
#define U8X8_MSG_DELAY_I2C 45
|
||||
|
||||
#define U8X8_MSG_GPIO(x) (64+(x))
|
||||
#ifdef U8X8_USE_PINS
|
||||
#define u8x8_GetPinIndex(u8x8, msg) ((msg)&0x3f)
|
||||
#define u8x8_GetPinValue(u8x8, msg) ((u8x8)->pins[(msg)&0x3f])
|
||||
#endif
|
||||
|
||||
#define U8X8_MSG_GPIO_D0 U8X8_MSG_GPIO(U8X8_PIN_D0)
|
||||
#define U8X8_MSG_GPIO_SPI_CLOCK U8X8_MSG_GPIO(U8X8_PIN_SPI_CLOCK)
|
||||
#define U8X8_MSG_GPIO_D1 U8X8_MSG_GPIO(U8X8_PIN_D1)
|
||||
#define U8X8_MSG_GPIO_SPI_DATA U8X8_MSG_GPIO(U8X8_PIN_SPI_DATA)
|
||||
#define U8X8_MSG_GPIO_D2 U8X8_MSG_GPIO(U8X8_PIN_D2)
|
||||
#define U8X8_MSG_GPIO_D3 U8X8_MSG_GPIO(U8X8_PIN_D3)
|
||||
#define U8X8_MSG_GPIO_D4 U8X8_MSG_GPIO(U8X8_PIN_D4)
|
||||
#define U8X8_MSG_GPIO_D5 U8X8_MSG_GPIO(U8X8_PIN_D5)
|
||||
#define U8X8_MSG_GPIO_D6 U8X8_MSG_GPIO(U8X8_PIN_D6)
|
||||
#define U8X8_MSG_GPIO_D7 U8X8_MSG_GPIO(U8X8_PIN_D7)
|
||||
#define U8X8_MSG_GPIO_E U8X8_MSG_GPIO(U8X8_PIN_E) // used as E1 for the SED1520
|
||||
#define U8X8_MSG_GPIO_CS U8X8_MSG_GPIO(U8X8_PIN_CS) // used as E2 for the SED1520
|
||||
#define U8X8_MSG_GPIO_DC U8X8_MSG_GPIO(U8X8_PIN_DC)
|
||||
#define U8X8_MSG_GPIO_RESET U8X8_MSG_GPIO(U8X8_PIN_RESET)
|
||||
#define U8X8_MSG_GPIO_I2C_CLOCK U8X8_MSG_GPIO(U8X8_PIN_I2C_CLOCK)
|
||||
#define U8X8_MSG_GPIO_I2C_DATA U8X8_MSG_GPIO(U8X8_PIN_I2C_DATA)
|
||||
|
||||
|
||||
#define U8X8_MSG_GPIO_CS1 U8X8_MSG_GPIO(U8X8_PIN_CS1) /* KS0108 extra chip select */
|
||||
#define U8X8_MSG_GPIO_CS2 U8X8_MSG_GPIO(U8X8_PIN_CS2) /* KS0108 extra chip select */
|
||||
|
||||
|
||||
/* these message expect the return value in u8x8->gpio_result */
|
||||
#define U8X8_MSG_GPIO_MENU_SELECT U8X8_MSG_GPIO(U8X8_PIN_MENU_SELECT)
|
||||
#define U8X8_MSG_GPIO_MENU_NEXT U8X8_MSG_GPIO(U8X8_PIN_MENU_NEXT)
|
||||
#define U8X8_MSG_GPIO_MENU_PREV U8X8_MSG_GPIO(U8X8_PIN_MENU_PREV)
|
||||
#define U8X8_MSG_GPIO_MENU_HOME U8X8_MSG_GPIO(U8X8_PIN_MENU_HOME)
|
||||
#define U8X8_MSG_GPIO_MENU_UP U8X8_MSG_GPIO(U8X8_PIN_MENU_UP)
|
||||
#define U8X8_MSG_GPIO_MENU_DOWN U8X8_MSG_GPIO(U8X8_PIN_MENU_DOWN)
|
||||
|
||||
|
||||
#define u8x8_gpio_Init(u8x8) ((u8x8)->gpio_and_delay_cb((u8x8), U8X8_MSG_GPIO_AND_DELAY_INIT, 0, NULL ))
|
||||
|
||||
|
||||
/*
|
||||
#define u8x8_gpio_SetDC(u8x8, v) ((u8x8)->gpio_and_delay_cb((u8x8), U8X8_MSG_GPIO_DC, (v), NULL ))
|
||||
#define u8x8_gpio_SetCS(u8x8, v) ((u8x8)->gpio_and_delay_cb((u8x8), U8X8_MSG_GPIO_CS, (v), NULL ))
|
||||
#define u8x8_gpio_SetReset(u8x8, v) ((u8x8)->gpio_and_delay_cb((u8x8), U8X8_MSG_GPIO_RESET, (v), NULL ))
|
||||
*/
|
||||
|
||||
#define u8x8_gpio_SetDC(u8x8, v) u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_DC, (v))
|
||||
#define u8x8_gpio_SetCS(u8x8, v) u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS, (v))
|
||||
#define u8x8_gpio_SetReset(u8x8, v) u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_RESET, (v))
|
||||
#define u8x8_gpio_SetSPIClock(u8x8, v) u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_SPI_CLOCK, (v))
|
||||
#define u8x8_gpio_SetSPIData(u8x8, v) u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_SPI_DATA, (v))
|
||||
#define u8x8_gpio_SetI2CClock(u8x8, v) u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_I2C_CLOCK, (v))
|
||||
#define u8x8_gpio_SetI2CData(u8x8, v) u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_I2C_DATA, (v))
|
||||
|
||||
void u8x8_gpio_call(u8x8_t *u8x8, uint8_t msg, uint8_t arg) U8X8_NOINLINE;
|
||||
|
||||
#define u8x8_gpio_Delay(u8x8, msg, dly) u8x8_gpio_call((u8x8), (msg), (dly))
|
||||
//void u8x8_gpio_Delay(u8x8_t *u8x8, uint8_t msg, uint8_t dly) U8X8_NOINLINE;
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_debounce.c */
|
||||
/* return U8X8_MSG_GPIO_MENU_xxxxx messages */
|
||||
uint8_t u8x8_GetMenuEvent(u8x8_t *u8x8);
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_d_stdio.c */
|
||||
void u8x8_SetupStdio(u8x8_t *u8x8);
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_d_sdl_128x64.c */
|
||||
void u8x8_Setup_SDL_128x64(u8x8_t *u8x8);
|
||||
void u8x8_Setup_SDL_240x160(u8x8_t *u8x8);
|
||||
int u8g_sdl_get_key(void);
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_d_tga.c */
|
||||
void u8x8_Setup_TGA_DESC(u8x8_t *u8x8);
|
||||
void u8x8_Setup_TGA_LCD(u8x8_t *u8x8);
|
||||
void tga_save(const char *name);
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_d_bitmap.c */
|
||||
uint8_t u8x8_GetBitmapPixel(u8x8_t *u8x8, uint16_t x, uint16_t y);
|
||||
void u8x8_SaveBitmapTGA(u8x8_t *u8x8, const char *filename);
|
||||
void u8x8_SetupBitmap(u8x8_t *u8x8, uint16_t pixel_width, uint16_t pixel_height);
|
||||
uint8_t u8x8_ConnectBitmapToU8x8(u8x8_t *u8x8);
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_d_utf8.c */
|
||||
void u8x8_Setup_Utf8(u8x8_t *u8x8); /* stdout UTF-8 display */
|
||||
void utf8_show(void); /* show content of UTF-8 frame buffer */
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_d_XXX.c */
|
||||
uint8_t u8x8_d_uc1701_ea_dogs102(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1701_mini12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1305_128x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_128x64_alt0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1309_128x64_noname0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1309_128x64_noname2(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_sh1106_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_sh1106_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_sh1106_128x64_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7920_192x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7920_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_128x32_univision(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_64x48_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_64x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_64x32_1f(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1306_96x16_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ls013b7dh03_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_ea_dogm128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_64128n(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_ea_dogm132(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_zolen_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_nhd_c12832(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_nhd_c12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_lm6059(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7565_erc12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7567_pi_132x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st7588_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st75256_jlx256128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st75256_jlx25664(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_st75256_jlx172104(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_nt7534_tg12864r(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); /* u8x8_d_st7565.c */
|
||||
uint8_t u8x8_d_ld7032_60x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_t6963_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_t6963_240x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_t6963_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_t6963_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1322_nhd_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_a2printer_384x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_sed1330_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ra8835_nhd_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ra8835_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1325_nhd_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1327_seeed_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1327_midas_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1326_er_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1329_128x96_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1601_128x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1604_jlx19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1608_erc24064(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1608_erc240120(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1608_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1610_ea_dogxl160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1611_ea_dogm240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1611_ea_dogxl240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1611_ew50850(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); /* 240x160 */
|
||||
uint8_t u8x8_d_uc1617_jlx128128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_uc1638_160x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ks0108_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ks0108_erm19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_sbn1661_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_sed1520_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_pcd8544_84x48(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_pcf8812_96x65(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1606_172x72(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1607_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ssd1607_v2_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_il3820_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_il3820_v2_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_lc7981_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_lc7981_160x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_lc7981_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_ist3020_erc19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_d_max7219_32x8(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_8x8.c */
|
||||
|
||||
uint16_t u8x8_upscale_byte(uint8_t x) U8X8_NOINLINE;
|
||||
|
||||
|
||||
void u8x8_utf8_init(u8x8_t *u8x8);
|
||||
uint16_t u8x8_ascii_next(u8x8_t *u8x8, uint8_t b);
|
||||
uint16_t u8x8_utf8_next(u8x8_t *u8x8, uint8_t b);
|
||||
// the following two functions are replaced by the init/next functions
|
||||
//uint16_t u8x8_get_encoding_from_utf8_string(const char **str);
|
||||
//uint16_t u8x8_get_char_from_string(const char **str);
|
||||
|
||||
void u8x8_SetFont(u8x8_t *u8x8, const uint8_t *font_8x8);
|
||||
void u8x8_DrawGlyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding);
|
||||
void u8x8_Draw2x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding);
|
||||
uint8_t u8x8_DrawString(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s);
|
||||
uint8_t u8x8_DrawUTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s); /* return number of glyps */
|
||||
uint8_t u8x8_Draw2x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s);
|
||||
uint8_t u8x8_Draw2x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s);
|
||||
uint8_t u8x8_GetUTF8Len(u8x8_t *u8x8, const char *s);
|
||||
#define u8x8_SetInverseFont(u8x8, b) (u8x8)->is_font_inverse_mode = (b)
|
||||
|
||||
/*==========================================*/
|
||||
/* itoa procedures */
|
||||
const char *u8x8_u8toa(uint8_t v, uint8_t d);
|
||||
const char *u8x8_u16toa(uint16_t v, uint8_t d);
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* u8x8_string.c */
|
||||
|
||||
uint8_t u8x8_GetStringLineCnt(const char *str); /* return 0 for str==NULL */
|
||||
const char *u8x8_GetStringLineStart(uint8_t line_idx, const char *str );
|
||||
void u8x8_CopyStringLine(char *dest, uint8_t line_idx, const char *str);
|
||||
/* draw one line, consider \t for center */
|
||||
uint8_t u8x8_DrawUTF8Line(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t w, const char *s);
|
||||
/* draw multiple lines, handle \t */
|
||||
uint8_t u8x8_DrawUTF8Lines(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t w, const char *s);
|
||||
|
||||
/*==========================================*/
|
||||
|
||||
/* u8x8_selection_list.c */
|
||||
struct _u8sl_struct
|
||||
{
|
||||
uint8_t visible; /* number of visible elements in the menu */
|
||||
uint8_t total; /* total number of elements in the menu */
|
||||
uint8_t first_pos; /* position of the first visible line */
|
||||
uint8_t current_pos; /* current cursor position, starts at 0 */
|
||||
|
||||
uint8_t x; /* u8x8 only, not used in u8g2 */
|
||||
uint8_t y; /* u8x8 only, not used in u8g2 */
|
||||
};
|
||||
typedef struct _u8sl_struct u8sl_t;
|
||||
|
||||
typedef void (*u8x8_sl_cb)(u8x8_t *u8x8, u8sl_t *u8sl, uint8_t idx, const void *aux);
|
||||
|
||||
void u8sl_Next(u8sl_t *u8sl);
|
||||
void u8sl_Prev(u8sl_t *u8sl);
|
||||
|
||||
uint8_t u8x8_UserInterfaceSelectionList(u8x8_t *u8x8, const char *title, uint8_t start_pos, const char *sl);
|
||||
|
||||
/*==========================================*/
|
||||
|
||||
/* u8x8_message.c */
|
||||
uint8_t u8x8_UserInterfaceMessage(u8x8_t *u8x8, const char *title1, const char *title2, const char *title3, const char *buttons);
|
||||
|
||||
/*==========================================*/
|
||||
|
||||
/* u8x8_input_value.c */
|
||||
|
||||
uint8_t u8x8_UserInterfaceInputValue(u8x8_t *u8x8, const char *title, const char *pre, uint8_t *value, uint8_t lo, uint8_t hi, uint8_t digits, const char *post);
|
||||
|
||||
|
||||
/*==========================================*/
|
||||
/* start font list */
|
||||
extern const uint8_t u8x8_font_amstrad_cpc_extended_f[] U8X8_FONT_SECTION("u8x8_font_amstrad_cpc_extended_f");
|
||||
extern const uint8_t u8x8_font_amstrad_cpc_extended_r[] U8X8_FONT_SECTION("u8x8_font_amstrad_cpc_extended_r");
|
||||
extern const uint8_t u8x8_font_amstrad_cpc_extended_n[] U8X8_FONT_SECTION("u8x8_font_amstrad_cpc_extended_n");
|
||||
extern const uint8_t u8x8_font_amstrad_cpc_extended_u[] U8X8_FONT_SECTION("u8x8_font_amstrad_cpc_extended_u");
|
||||
extern const uint8_t u8x8_font_5x7_f[] U8X8_FONT_SECTION("u8x8_font_5x7_f");
|
||||
extern const uint8_t u8x8_font_5x7_r[] U8X8_FONT_SECTION("u8x8_font_5x7_r");
|
||||
extern const uint8_t u8x8_font_5x7_n[] U8X8_FONT_SECTION("u8x8_font_5x7_n");
|
||||
extern const uint8_t u8x8_font_5x8_f[] U8X8_FONT_SECTION("u8x8_font_5x8_f");
|
||||
extern const uint8_t u8x8_font_5x8_r[] U8X8_FONT_SECTION("u8x8_font_5x8_r");
|
||||
extern const uint8_t u8x8_font_5x8_n[] U8X8_FONT_SECTION("u8x8_font_5x8_n");
|
||||
extern const uint8_t u8x8_font_artossans8_r[] U8X8_FONT_SECTION("u8x8_font_artossans8_r");
|
||||
extern const uint8_t u8x8_font_artossans8_n[] U8X8_FONT_SECTION("u8x8_font_artossans8_n");
|
||||
extern const uint8_t u8x8_font_artossans8_u[] U8X8_FONT_SECTION("u8x8_font_artossans8_u");
|
||||
extern const uint8_t u8x8_font_artosserif8_r[] U8X8_FONT_SECTION("u8x8_font_artosserif8_r");
|
||||
extern const uint8_t u8x8_font_artosserif8_n[] U8X8_FONT_SECTION("u8x8_font_artosserif8_n");
|
||||
extern const uint8_t u8x8_font_artosserif8_u[] U8X8_FONT_SECTION("u8x8_font_artosserif8_u");
|
||||
extern const uint8_t u8x8_font_chroma48medium8_r[] U8X8_FONT_SECTION("u8x8_font_chroma48medium8_r");
|
||||
extern const uint8_t u8x8_font_chroma48medium8_n[] U8X8_FONT_SECTION("u8x8_font_chroma48medium8_n");
|
||||
extern const uint8_t u8x8_font_chroma48medium8_u[] U8X8_FONT_SECTION("u8x8_font_chroma48medium8_u");
|
||||
extern const uint8_t u8x8_font_saikyosansbold8_n[] U8X8_FONT_SECTION("u8x8_font_saikyosansbold8_n");
|
||||
extern const uint8_t u8x8_font_saikyosansbold8_u[] U8X8_FONT_SECTION("u8x8_font_saikyosansbold8_u");
|
||||
extern const uint8_t u8x8_font_torussansbold8_r[] U8X8_FONT_SECTION("u8x8_font_torussansbold8_r");
|
||||
extern const uint8_t u8x8_font_torussansbold8_n[] U8X8_FONT_SECTION("u8x8_font_torussansbold8_n");
|
||||
extern const uint8_t u8x8_font_torussansbold8_u[] U8X8_FONT_SECTION("u8x8_font_torussansbold8_u");
|
||||
extern const uint8_t u8x8_font_victoriabold8_r[] U8X8_FONT_SECTION("u8x8_font_victoriabold8_r");
|
||||
extern const uint8_t u8x8_font_victoriabold8_n[] U8X8_FONT_SECTION("u8x8_font_victoriabold8_n");
|
||||
extern const uint8_t u8x8_font_victoriabold8_u[] U8X8_FONT_SECTION("u8x8_font_victoriabold8_u");
|
||||
extern const uint8_t u8x8_font_victoriamedium8_r[] U8X8_FONT_SECTION("u8x8_font_victoriamedium8_r");
|
||||
extern const uint8_t u8x8_font_victoriamedium8_n[] U8X8_FONT_SECTION("u8x8_font_victoriamedium8_n");
|
||||
extern const uint8_t u8x8_font_victoriamedium8_u[] U8X8_FONT_SECTION("u8x8_font_victoriamedium8_u");
|
||||
extern const uint8_t u8x8_font_pressstart2p_f[] U8X8_FONT_SECTION("u8x8_font_pressstart2p_f");
|
||||
extern const uint8_t u8x8_font_pressstart2p_r[] U8X8_FONT_SECTION("u8x8_font_pressstart2p_r");
|
||||
extern const uint8_t u8x8_font_pressstart2p_n[] U8X8_FONT_SECTION("u8x8_font_pressstart2p_n");
|
||||
extern const uint8_t u8x8_font_pressstart2p_u[] U8X8_FONT_SECTION("u8x8_font_pressstart2p_u");
|
||||
extern const uint8_t u8x8_font_pcsenior_f[] U8X8_FONT_SECTION("u8x8_font_pcsenior_f");
|
||||
extern const uint8_t u8x8_font_pcsenior_r[] U8X8_FONT_SECTION("u8x8_font_pcsenior_r");
|
||||
extern const uint8_t u8x8_font_pcsenior_n[] U8X8_FONT_SECTION("u8x8_font_pcsenior_n");
|
||||
extern const uint8_t u8x8_font_pcsenior_u[] U8X8_FONT_SECTION("u8x8_font_pcsenior_u");
|
||||
extern const uint8_t u8x8_font_pxplusibmcgathin_f[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcgathin_f");
|
||||
extern const uint8_t u8x8_font_pxplusibmcgathin_r[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcgathin_r");
|
||||
extern const uint8_t u8x8_font_pxplusibmcgathin_n[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcgathin_n");
|
||||
extern const uint8_t u8x8_font_pxplusibmcgathin_u[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcgathin_u");
|
||||
extern const uint8_t u8x8_font_pxplusibmcga_f[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcga_f");
|
||||
extern const uint8_t u8x8_font_pxplusibmcga_r[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcga_r");
|
||||
extern const uint8_t u8x8_font_pxplusibmcga_n[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcga_n");
|
||||
extern const uint8_t u8x8_font_pxplusibmcga_u[] U8X8_FONT_SECTION("u8x8_font_pxplusibmcga_u");
|
||||
extern const uint8_t u8x8_font_pxplustandynewtv_f[] U8X8_FONT_SECTION("u8x8_font_pxplustandynewtv_f");
|
||||
extern const uint8_t u8x8_font_pxplustandynewtv_r[] U8X8_FONT_SECTION("u8x8_font_pxplustandynewtv_r");
|
||||
extern const uint8_t u8x8_font_pxplustandynewtv_n[] U8X8_FONT_SECTION("u8x8_font_pxplustandynewtv_n");
|
||||
extern const uint8_t u8x8_font_pxplustandynewtv_u[] U8X8_FONT_SECTION("u8x8_font_pxplustandynewtv_u");
|
||||
|
||||
/* end font list */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* _U8X8_H */
|
||||
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
|
||||
u8x8_8x8.c
|
||||
|
||||
font procedures, directly interfaces display procedures
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
#if defined(ESP8266)
|
||||
uint8_t u8x8_pgm_read_esp(const uint8_t * addr)
|
||||
{
|
||||
uint32_t bytes;
|
||||
bytes = *(uint32_t*)((uint32_t)addr & ~3);
|
||||
return ((uint8_t*)&bytes)[(uint32_t)addr & 3];
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void u8x8_SetFont(u8x8_t *u8x8, const uint8_t *font_8x8)
|
||||
{
|
||||
u8x8->font = font_8x8;
|
||||
}
|
||||
|
||||
/*
|
||||
Args:
|
||||
u8x8: ptr to u8x8 structure
|
||||
encoding: glyph for which the data is requested (must be between 0 and 255)
|
||||
buf: pointer to 8 bytes
|
||||
*/
|
||||
static void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf) U8X8_NOINLINE;
|
||||
static void u8x8_get_glyph_data(u8x8_t *u8x8, uint8_t encoding, uint8_t *buf)
|
||||
{
|
||||
uint8_t first, last, i;
|
||||
uint16_t offset;
|
||||
first = u8x8_pgm_read(u8x8->font+0);
|
||||
last = u8x8_pgm_read(u8x8->font+1);
|
||||
|
||||
/* get the glyph bitmap from the font */
|
||||
if ( first <= encoding && encoding <= last )
|
||||
{
|
||||
offset = encoding;
|
||||
offset -= first;
|
||||
offset *= 8;
|
||||
offset +=2;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
buf[i] = u8x8_pgm_read(u8x8->font+offset);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
buf[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* invert the bitmap if required */
|
||||
if ( u8x8->is_font_inverse_mode )
|
||||
{
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
buf[i] ^= 255;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void u8x8_DrawGlyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
|
||||
{
|
||||
uint8_t buf[8];
|
||||
u8x8_get_glyph_data(u8x8, encoding, buf);
|
||||
u8x8_DrawTile(u8x8, x, y, 1, buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Source: http://graphics.stanford.edu/~seander/bithacks.html
|
||||
Section: Interleave bits by Binary Magic Numbers
|
||||
Original codes is here:
|
||||
static const unsigned int B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF};
|
||||
static const unsigned int S[] = {1, 2, 4, 8};
|
||||
|
||||
unsigned int x; // Interleave lower 16 bits of x and y, so the bits of x
|
||||
unsigned int y; // are in the even positions and bits from y in the odd;
|
||||
unsigned int z; // z gets the resulting 32-bit Morton Number.
|
||||
// x and y must initially be less than 65536.
|
||||
|
||||
x = (x | (x << S[3])) & B[3];
|
||||
x = (x | (x << S[2])) & B[2];
|
||||
x = (x | (x << S[1])) & B[1];
|
||||
x = (x | (x << S[0])) & B[0];
|
||||
|
||||
y = (y | (y << S[3])) & B[3];
|
||||
y = (y | (y << S[2])) & B[2];
|
||||
y = (y | (y << S[1])) & B[1];
|
||||
y = (y | (y << S[0])) & B[0];
|
||||
|
||||
z = x | (y << 1);
|
||||
*/
|
||||
uint16_t u8x8_upscale_byte(uint8_t x)
|
||||
{
|
||||
uint16_t y = x;
|
||||
y |= (y << 4); // x = (x | (x << S[2])) & B[2];
|
||||
y &= 0x0f0f;
|
||||
y |= (y << 2); // x = (x | (x << S[1])) & B[1];
|
||||
y &= 0x3333;
|
||||
y |= (y << 1); // x = (x | (x << S[0])) & B[0];
|
||||
y &= 0x5555;
|
||||
|
||||
y |= (y << 1); // z = x | (y << 1);
|
||||
return y;
|
||||
}
|
||||
|
||||
static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest) U8X8_NOINLINE;
|
||||
static void u8x8_upscale_buf(uint8_t *src, uint8_t *dest)
|
||||
{
|
||||
uint8_t i = 4;
|
||||
do
|
||||
{
|
||||
*dest++ = *src;
|
||||
*dest++ = *src++;
|
||||
i--;
|
||||
} while( i > 0 );
|
||||
}
|
||||
|
||||
void u8x8_Draw2x2Glyph(u8x8_t *u8x8, uint8_t x, uint8_t y, uint8_t encoding)
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t t;
|
||||
uint8_t buf[8];
|
||||
uint8_t buf1[8];
|
||||
uint8_t buf2[8];
|
||||
u8x8_get_glyph_data(u8x8, encoding, buf);
|
||||
for( i = 0; i < 8; i ++ )
|
||||
{
|
||||
t = u8x8_upscale_byte(buf[i]);
|
||||
buf1[i] = t >> 8;
|
||||
buf2[i] = t & 255;
|
||||
}
|
||||
u8x8_upscale_buf(buf2, buf);
|
||||
u8x8_DrawTile(u8x8, x, y, 1, buf);
|
||||
|
||||
u8x8_upscale_buf(buf2+4, buf);
|
||||
u8x8_DrawTile(u8x8, x+1, y, 1, buf);
|
||||
|
||||
u8x8_upscale_buf(buf1, buf);
|
||||
u8x8_DrawTile(u8x8, x, y+1, 1, buf);
|
||||
|
||||
u8x8_upscale_buf(buf1+4, buf);
|
||||
u8x8_DrawTile(u8x8, x+1, y+1, 1, buf);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
source: https://en.wikipedia.org/wiki/UTF-8
|
||||
Bits from to bytes Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6
|
||||
7 U+0000 U+007F 1 0xxxxxxx
|
||||
11 U+0080 U+07FF 2 110xxxxx 10xxxxxx
|
||||
16 U+0800 U+FFFF 3 1110xxxx 10xxxxxx 10xxxxxx
|
||||
21 U+10000 U+1FFFFF 4 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
26 U+200000 U+3FFFFFF 5 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
31 U+4000000 U+7FFFFFFF 6 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||
|
||||
|
||||
*/
|
||||
|
||||
/* reset the internal state machine */
|
||||
void u8x8_utf8_init(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8->utf8_state = 0; /* also reset during u8x8_SetupDefaults() */
|
||||
}
|
||||
|
||||
uint16_t u8x8_ascii_next(U8X8_UNUSED u8x8_t *u8x8, uint8_t b)
|
||||
{
|
||||
if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
|
||||
return 0x0ffff; /* end of string detected*/
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
pass a byte from an utf8 encoded string to the utf8 decoder state machine
|
||||
returns
|
||||
0x0fffe: no glyph, just continue
|
||||
0x0ffff: end of string
|
||||
anything else: The decoded encoding
|
||||
*/
|
||||
uint16_t u8x8_utf8_next(u8x8_t *u8x8, uint8_t b)
|
||||
{
|
||||
if ( b == 0 || b == '\n' ) /* '\n' terminates the string to support the string list procedures */
|
||||
return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
|
||||
if ( u8x8->utf8_state == 0 )
|
||||
{
|
||||
if ( b >= 0xfc ) /* 6 byte sequence */
|
||||
{
|
||||
u8x8->utf8_state = 5;
|
||||
b &= 1;
|
||||
}
|
||||
else if ( b >= 0xf8 )
|
||||
{
|
||||
u8x8->utf8_state = 4;
|
||||
b &= 3;
|
||||
}
|
||||
else if ( b >= 0xf0 )
|
||||
{
|
||||
u8x8->utf8_state = 3;
|
||||
b &= 7;
|
||||
}
|
||||
else if ( b >= 0xe0 )
|
||||
{
|
||||
u8x8->utf8_state = 2;
|
||||
b &= 15;
|
||||
}
|
||||
else if ( b >= 0xc0 )
|
||||
{
|
||||
u8x8->utf8_state = 1;
|
||||
b &= 0x01f;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do nothing, just use the value as encoding */
|
||||
return b;
|
||||
}
|
||||
u8x8->encoding = b;
|
||||
return 0x0fffe;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8->utf8_state--;
|
||||
/* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
|
||||
u8x8->encoding<<=6;
|
||||
b &= 0x03f;
|
||||
u8x8->encoding |= b;
|
||||
if ( u8x8->utf8_state != 0 )
|
||||
return 0x0fffe; /* nothing to do yet */
|
||||
}
|
||||
return u8x8->encoding;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
|
||||
static uint8_t u8x8_draw_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
uint16_t e;
|
||||
uint8_t cnt = 0;
|
||||
u8x8_utf8_init(u8x8);
|
||||
for(;;)
|
||||
{
|
||||
e = u8x8->next_cb(u8x8, (uint8_t)*s);
|
||||
if ( e == 0x0ffff )
|
||||
break;
|
||||
s++;
|
||||
if ( e != 0x0fffe )
|
||||
{
|
||||
u8x8_DrawGlyph(u8x8, x, y, e);
|
||||
x++;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_DrawString(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->next_cb = u8x8_ascii_next;
|
||||
return u8x8_draw_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
uint8_t u8x8_DrawUTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->next_cb = u8x8_utf8_next;
|
||||
return u8x8_draw_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s) U8X8_NOINLINE;
|
||||
static uint8_t u8x8_draw_2x2_string(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
uint16_t e;
|
||||
uint8_t cnt = 0;
|
||||
u8x8_utf8_init(u8x8);
|
||||
for(;;)
|
||||
{
|
||||
e = u8x8->next_cb(u8x8, (uint8_t)*s);
|
||||
if ( e == 0x0ffff )
|
||||
break;
|
||||
s++;
|
||||
if ( e != 0x0fffe )
|
||||
{
|
||||
u8x8_Draw2x2Glyph(u8x8, x, y, e);
|
||||
x+=2;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_Draw2x2String(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->next_cb = u8x8_ascii_next;
|
||||
return u8x8_draw_2x2_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
uint8_t u8x8_Draw2x2UTF8(u8x8_t *u8x8, uint8_t x, uint8_t y, const char *s)
|
||||
{
|
||||
u8x8->next_cb = u8x8_utf8_next;
|
||||
return u8x8_draw_2x2_string(u8x8, x, y, s);
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint8_t u8x8_GetUTF8Len(u8x8_t *u8x8, const char *s)
|
||||
{
|
||||
uint16_t e;
|
||||
uint8_t cnt = 0;
|
||||
u8x8_utf8_init(u8x8);
|
||||
for(;;)
|
||||
{
|
||||
e = u8x8_utf8_next(u8x8, *s);
|
||||
if ( e == 0x0ffff )
|
||||
break;
|
||||
s++;
|
||||
if ( e != 0x0fffe )
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,653 @@
|
||||
/*
|
||||
|
||||
u8x8_byte.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
uint8_t u8x8_byte_SetDC(u8x8_t *u8x8, uint8_t dc)
|
||||
{
|
||||
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_SET_DC, dc, NULL);
|
||||
}
|
||||
|
||||
uint8_t u8x8_byte_SendBytes(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
|
||||
{
|
||||
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_SEND, cnt, (void *)data);
|
||||
}
|
||||
|
||||
uint8_t u8x8_byte_SendByte(u8x8_t *u8x8, uint8_t byte)
|
||||
{
|
||||
return u8x8_byte_SendBytes(u8x8, 1, &byte);
|
||||
}
|
||||
|
||||
uint8_t u8x8_byte_StartTransfer(u8x8_t *u8x8)
|
||||
{
|
||||
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_START_TRANSFER, 0, NULL);
|
||||
}
|
||||
|
||||
uint8_t u8x8_byte_EndTransfer(u8x8_t *u8x8)
|
||||
{
|
||||
return u8x8->byte_cb(u8x8, U8X8_MSG_BYTE_END_TRANSFER, 0, NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Uses:
|
||||
u8x8->display_info->sda_setup_time_ns
|
||||
u8x8->display_info->sck_pulse_width_ns
|
||||
u8x8->display_info->spi_mode
|
||||
u8x8->display_info->chip_disable_level
|
||||
u8x8->display_info->chip_enable_level
|
||||
u8x8->display_info->post_chip_enable_wait_ns
|
||||
u8x8->display_info->pre_chip_disable_wait_ns
|
||||
Calls to GPIO and DELAY:
|
||||
U8X8_MSG_DELAY_NANO
|
||||
U8X8_MSG_GPIO_DC
|
||||
U8X8_MSG_GPIO_CS
|
||||
U8X8_MSG_GPIO_CLOCK
|
||||
U8X8_MSG_GPIO_DATA
|
||||
Handles:
|
||||
U8X8_MSG_BYTE_INIT
|
||||
U8X8_MSG_BYTE_SEND
|
||||
U8X8_MSG_BYTE_SET_DC
|
||||
U8X8_MSG_BYTE_START_TRANSFER
|
||||
U8X8_MSG_BYTE_END_TRANSFER
|
||||
*/
|
||||
|
||||
uint8_t u8x8_byte_4wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t i, b;
|
||||
uint8_t *data;
|
||||
uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
|
||||
uint8_t not_takeover_edge = 1 - takeover_edge;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
b = *data;
|
||||
data++;
|
||||
arg_int--;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
if ( b & 128 )
|
||||
u8x8_gpio_SetSPIData(u8x8, 1);
|
||||
else
|
||||
u8x8_gpio_SetSPIData(u8x8, 0);
|
||||
b <<= 1;
|
||||
|
||||
u8x8_gpio_SetSPIClock(u8x8, not_takeover_edge);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sda_setup_time_ns);
|
||||
u8x8_gpio_SetSPIClock(u8x8, takeover_edge);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sck_pulse_width_ns);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
/* disable chipselect */
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
/* no wait required here */
|
||||
|
||||
/* for SPI: setup correct level of the clock signal */
|
||||
u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
|
||||
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_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_byte_8bit_6800mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t i, b;
|
||||
uint8_t *data;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
b = *data;
|
||||
data++;
|
||||
arg_int--;
|
||||
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
|
||||
{
|
||||
u8x8_gpio_call(u8x8, i, b&1);
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
/* disable chipselect */
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
/* ensure that the enable signal is high */
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
|
||||
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_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_byte_8bit_8080mode(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t i, b;
|
||||
uint8_t *data;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
b = *data;
|
||||
data++;
|
||||
arg_int--;
|
||||
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
|
||||
{
|
||||
u8x8_gpio_call(u8x8, i, b&1);
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
/* disable chipselect */
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
/* ensure that the enable signal is high */
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
|
||||
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_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_byte_3wire_sw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t *data;
|
||||
uint8_t takeover_edge = u8x8_GetSPIClockPhase(u8x8);
|
||||
uint8_t not_takeover_edge = 1 - takeover_edge;
|
||||
uint16_t b;
|
||||
static uint8_t last_dc;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
b = *data;
|
||||
if ( last_dc != 0 )
|
||||
b |= 256;
|
||||
data++;
|
||||
arg_int--;
|
||||
for( i = 0; i < 9; i++ )
|
||||
{
|
||||
if ( b & 256 )
|
||||
u8x8_gpio_SetSPIData(u8x8, 1);
|
||||
else
|
||||
u8x8_gpio_SetSPIData(u8x8, 0);
|
||||
b <<= 1;
|
||||
|
||||
u8x8_gpio_SetSPIClock(u8x8, not_takeover_edge);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sda_setup_time_ns);
|
||||
u8x8_gpio_SetSPIClock(u8x8, takeover_edge);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->sck_pulse_width_ns);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
/* disable chipselect */
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
/* no wait required here */
|
||||
|
||||
/* for SPI: setup correct level of the clock signal */
|
||||
u8x8_gpio_SetSPIClock(u8x8, u8x8_GetSPIClockPhase(u8x8));
|
||||
break;
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
last_dc = 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_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;
|
||||
}
|
||||
|
||||
/*=========================================*/
|
||||
|
||||
void u8x8_byte_set_ks0108_cs(u8x8_t *u8x8, uint8_t arg)
|
||||
{
|
||||
u8x8_gpio_SetCS(u8x8, arg&1);
|
||||
arg = arg >> 1;
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS1, arg&1);
|
||||
arg = arg >> 2;
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS2, arg&1);
|
||||
}
|
||||
|
||||
/* 6800 mode */
|
||||
uint8_t u8x8_byte_ks0108(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t i, b;
|
||||
uint8_t *data;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
b = *data;
|
||||
data++;
|
||||
arg_int--;
|
||||
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
|
||||
{
|
||||
u8x8_gpio_call(u8x8, i, b&1);
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 1);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
/* disable chipselect */
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
/* ensure that the enable signal is low */
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
u8x8_gpio_SetDC(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
/* expects 3 bits in arg_int for the chip select lines */
|
||||
u8x8_byte_set_ks0108_cs(u8x8, arg_int);
|
||||
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
|
||||
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_byte_set_ks0108_cs(u8x8, arg_int);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* sed1520 or sbn1661
|
||||
U8X8_MSG_GPIO_E --> E1
|
||||
U8X8_MSG_GPIO_CS --> E2
|
||||
*/
|
||||
uint8_t u8x8_byte_sed1520(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t i, b;
|
||||
uint8_t *data;
|
||||
static uint8_t enable_pin;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
b = *data;
|
||||
data++;
|
||||
arg_int--;
|
||||
for( i = U8X8_MSG_GPIO_D0; i <= U8X8_MSG_GPIO_D7; i++ )
|
||||
{
|
||||
u8x8_gpio_call(u8x8, i, b&1);
|
||||
b >>= 1;
|
||||
}
|
||||
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->data_setup_time_ns);
|
||||
u8x8_gpio_call(u8x8, enable_pin, 1);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->write_pulse_width_ns);
|
||||
u8x8_gpio_call(u8x8, enable_pin, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
/* disable chipselect */
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
/* ensure that the enable signals are low */
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_E, 0);
|
||||
u8x8_gpio_call(u8x8, U8X8_MSG_GPIO_CS, 0);
|
||||
enable_pin = U8X8_MSG_GPIO_E;
|
||||
break;
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
u8x8_gpio_SetDC(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
/* cs lines are not supported for the SED1520/SBN1661 */
|
||||
/* instead, this will select the E1 or E2 line */
|
||||
enable_pin = U8X8_MSG_GPIO_E;
|
||||
if ( arg_int != 0 )
|
||||
enable_pin = U8X8_MSG_GPIO_CS;
|
||||
break;
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=========================================*/
|
||||
|
||||
|
||||
/*
|
||||
software i2c,
|
||||
ignores ACK response (which is anyway not provided by some displays)
|
||||
also does not allow reading from the device
|
||||
*/
|
||||
static void i2c_delay(u8x8_t *u8x8) U8X8_NOINLINE;
|
||||
static void i2c_delay(u8x8_t *u8x8)
|
||||
{
|
||||
//u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_10MICRO, u8x8->display_info->i2c_bus_clock_100kHz);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_I2C, u8x8->display_info->i2c_bus_clock_100kHz);
|
||||
}
|
||||
|
||||
static void i2c_init(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8_gpio_SetI2CClock(u8x8, 1);
|
||||
u8x8_gpio_SetI2CData(u8x8, 1);
|
||||
|
||||
i2c_delay(u8x8);
|
||||
}
|
||||
|
||||
/* actually, the scl line is not observed, so this procedure does not return a value */
|
||||
|
||||
static void i2c_read_scl_and_delay(u8x8_t *u8x8)
|
||||
{
|
||||
/* set as input (line will be high) */
|
||||
u8x8_gpio_SetI2CClock(u8x8, 1);
|
||||
|
||||
i2c_delay(u8x8);
|
||||
}
|
||||
|
||||
static void i2c_clear_scl(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8_gpio_SetI2CClock(u8x8, 0);
|
||||
}
|
||||
|
||||
static void i2c_read_sda(u8x8_t *u8x8)
|
||||
{
|
||||
/* set as input (line will be high) */
|
||||
u8x8_gpio_SetI2CData(u8x8, 1);
|
||||
}
|
||||
|
||||
static void i2c_clear_sda(u8x8_t *u8x8)
|
||||
{
|
||||
/* set open collector and drive low */
|
||||
u8x8_gpio_SetI2CData(u8x8, 0);
|
||||
}
|
||||
|
||||
static void i2c_start(u8x8_t *u8x8)
|
||||
{
|
||||
if ( u8x8->i2c_started != 0 )
|
||||
{
|
||||
/* if already started: do restart */
|
||||
i2c_read_sda(u8x8); /* SDA = 1 */
|
||||
i2c_delay(u8x8);
|
||||
i2c_read_scl_and_delay(u8x8);
|
||||
}
|
||||
i2c_read_sda(u8x8);
|
||||
/* send the start condition, both lines go from 1 to 0 */
|
||||
i2c_clear_sda(u8x8);
|
||||
i2c_delay(u8x8);
|
||||
i2c_clear_scl(u8x8);
|
||||
u8x8->i2c_started = 1;
|
||||
}
|
||||
|
||||
|
||||
static void i2c_stop(u8x8_t *u8x8)
|
||||
{
|
||||
/* set SDA to 0 */
|
||||
i2c_clear_sda(u8x8);
|
||||
i2c_delay(u8x8);
|
||||
|
||||
/* now release all lines */
|
||||
i2c_read_scl_and_delay(u8x8);
|
||||
|
||||
/* set SDA to 1 */
|
||||
i2c_read_sda(u8x8);
|
||||
i2c_delay(u8x8);
|
||||
u8x8->i2c_started = 0;
|
||||
}
|
||||
|
||||
static void i2c_write_bit(u8x8_t *u8x8, uint8_t val)
|
||||
{
|
||||
if (val)
|
||||
i2c_read_sda(u8x8);
|
||||
else
|
||||
i2c_clear_sda(u8x8);
|
||||
|
||||
i2c_delay(u8x8);
|
||||
i2c_read_scl_and_delay(u8x8);
|
||||
i2c_clear_scl(u8x8);
|
||||
}
|
||||
|
||||
static void i2c_read_bit(u8x8_t *u8x8)
|
||||
{
|
||||
//uint8_t val;
|
||||
/* do not drive SDA */
|
||||
i2c_read_sda(u8x8);
|
||||
i2c_delay(u8x8);
|
||||
i2c_read_scl_and_delay(u8x8);
|
||||
i2c_read_sda(u8x8);
|
||||
i2c_delay(u8x8);
|
||||
i2c_clear_scl(u8x8);
|
||||
//return val;
|
||||
}
|
||||
|
||||
static void i2c_write_byte(u8x8_t *u8x8, uint8_t b)
|
||||
{
|
||||
i2c_write_bit(u8x8, b & 128);
|
||||
i2c_write_bit(u8x8, b & 64);
|
||||
i2c_write_bit(u8x8, b & 32);
|
||||
i2c_write_bit(u8x8, b & 16);
|
||||
i2c_write_bit(u8x8, b & 8);
|
||||
i2c_write_bit(u8x8, b & 4);
|
||||
i2c_write_bit(u8x8, b & 2);
|
||||
i2c_write_bit(u8x8, b & 1);
|
||||
|
||||
/* read ack from client */
|
||||
/* 0: ack was given by client */
|
||||
/* 1: nothing happend during ack cycle */
|
||||
i2c_read_bit(u8x8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef OBSOLETE_HANDLED_BY_CAD_PROCEDURE
|
||||
uint8_t u8x8_byte_ssd13xx_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t *data;
|
||||
static uint8_t last_dc = 0;
|
||||
static uint8_t is_send_dc = 0; /* instruction, whether i2c-start including dc has to be sent */
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
|
||||
if ( is_send_dc != 0 )
|
||||
{
|
||||
|
||||
i2c_start(u8x8);
|
||||
i2c_write_byte(u8x8, 0x078); /* write slave adr and read/write bit */
|
||||
|
||||
if ( last_dc == 0 )
|
||||
i2c_write_byte(u8x8, 0);
|
||||
else
|
||||
i2c_write_byte(u8x8, 0x040);
|
||||
is_send_dc = 0;
|
||||
}
|
||||
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
i2c_write_byte(u8x8, *data);
|
||||
data++;
|
||||
arg_int--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
i2c_init(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
if ( last_dc != arg_int )
|
||||
{
|
||||
last_dc = arg_int;
|
||||
is_send_dc = 1;
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
last_dc = 0;
|
||||
is_send_dc = 1;
|
||||
break;
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
i2c_stop(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8_t u8x8_byte_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t *data;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
i2c_write_byte(u8x8, *data);
|
||||
data++;
|
||||
arg_int--;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
i2c_init(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
break;
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
i2c_start(u8x8);
|
||||
i2c_write_byte(u8x8, u8x8_GetI2CAddress(u8x8));
|
||||
//i2c_write_byte(u8x8, 0x078);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
i2c_stop(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,643 @@
|
||||
/*
|
||||
|
||||
u8x8_cad.c
|
||||
|
||||
"command arg data" interface to the graphics controller
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
The following sequence must be used for any data, which is set to the display:
|
||||
|
||||
|
||||
uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
|
||||
|
||||
any of the following calls
|
||||
uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
|
||||
uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
|
||||
uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
|
||||
|
||||
uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
|
||||
|
||||
|
||||
|
||||
*/
|
||||
/*
|
||||
uint8_t u8x8_cad_template(u8x8_t *u8x8, uint8_t msg, uint16_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_mcd_byte_SetDC(mcd->next, 1);
|
||||
u8x8_mcd_byte_Send(mcd->next, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_mcd_byte_SetDC(mcd->next, 1);
|
||||
u8x8_mcd_byte_Send(mcd->next, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
u8x8_mcd_byte_SetDC(mcd->next, 0);
|
||||
for( i = 0; i < 8; i++ )
|
||||
u8x8_mcd_byte_Send(mcd->next, ((uint8_t *)arg_ptr)[i]);
|
||||
break;
|
||||
case U8X8_MSG_CAD_RESET:
|
||||
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
return mcd->next->cb(mcd->next, msg, arg_int, arg_ptr);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
uint8_t u8x8_cad_SendCmd(u8x8_t *u8x8, uint8_t cmd)
|
||||
{
|
||||
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_CMD, cmd, NULL);
|
||||
}
|
||||
|
||||
uint8_t u8x8_cad_SendArg(u8x8_t *u8x8, uint8_t arg)
|
||||
{
|
||||
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
|
||||
}
|
||||
|
||||
uint8_t u8x8_cad_SendMultipleArg(u8x8_t *u8x8, uint8_t cnt, uint8_t arg)
|
||||
{
|
||||
while( cnt > 0 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_ARG, arg, NULL);
|
||||
cnt--;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t u8x8_cad_SendData(u8x8_t *u8x8, uint8_t cnt, uint8_t *data)
|
||||
{
|
||||
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, cnt, data);
|
||||
}
|
||||
|
||||
uint8_t u8x8_cad_StartTransfer(u8x8_t *u8x8)
|
||||
{
|
||||
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
|
||||
}
|
||||
|
||||
uint8_t u8x8_cad_EndTransfer(u8x8_t *u8x8)
|
||||
{
|
||||
return u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
21 c send command c
|
||||
22 a send arg a
|
||||
23 d send data d
|
||||
24 CS on
|
||||
25 CS off
|
||||
254 milli delay by milliseconds
|
||||
255 end of sequence
|
||||
*/
|
||||
|
||||
void u8x8_cad_SendSequence(u8x8_t *u8x8, uint8_t const *data)
|
||||
{
|
||||
uint8_t cmd;
|
||||
uint8_t v;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
cmd = *data;
|
||||
data++;
|
||||
switch( cmd )
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
v = *data;
|
||||
u8x8->cad_cb(u8x8, cmd, v, NULL);
|
||||
data++;
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
v = *data;
|
||||
u8x8_cad_SendData(u8x8, 1, &v);
|
||||
data++;
|
||||
break;
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
u8x8->cad_cb(u8x8, cmd, 0, NULL);
|
||||
break;
|
||||
case 0x0fe:
|
||||
v = *data;
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_MILLI, v);
|
||||
data++;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_cad_empty(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
convert to bytes by using
|
||||
dc = 1 for commands and args and
|
||||
dc = 0 for data
|
||||
*/
|
||||
uint8_t u8x8_cad_110(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_byte_SetDC(u8x8, 1);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_SetDC(u8x8, 1);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
u8x8_byte_SetDC(u8x8, 0);
|
||||
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
|
||||
//break;
|
||||
/* fall through */
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
convert to bytes by using
|
||||
dc = 1 for commands and args and
|
||||
dc = 0 for data
|
||||
t6963
|
||||
*/
|
||||
uint8_t u8x8_cad_100(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_byte_SetDC(u8x8, 1);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_SetDC(u8x8, 0);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
u8x8_byte_SetDC(u8x8, 0);
|
||||
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
|
||||
//break;
|
||||
/* fall through */
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
convert to bytes by using
|
||||
dc = 0 for commands and args and
|
||||
dc = 1 for data
|
||||
*/
|
||||
uint8_t u8x8_cad_001(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_byte_SetDC(u8x8, 0);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_SetDC(u8x8, 0);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
u8x8_byte_SetDC(u8x8, 1);
|
||||
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
|
||||
//break;
|
||||
/* fall through */
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
convert to bytes by using
|
||||
dc = 0 for commands
|
||||
dc = 1 for args and data
|
||||
*/
|
||||
uint8_t u8x8_cad_011(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_byte_SetDC(u8x8, 0);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_SetDC(u8x8, 1);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
u8x8_byte_SetDC(u8x8, 1);
|
||||
//u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr);
|
||||
//break;
|
||||
/* fall through */
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cad procedure for the ST7920 in SPI mode */
|
||||
/* u8x8_byte_SetDC is not used */
|
||||
uint8_t u8x8_cad_st7920_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t *data;
|
||||
uint8_t b;
|
||||
uint8_t i;
|
||||
static uint8_t buf[16];
|
||||
uint8_t *ptr;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_byte_SendByte(u8x8, 0x0f8);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
|
||||
u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
|
||||
u8x8_byte_SendByte(u8x8, arg_int << 4);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_SendByte(u8x8, 0x0f8);
|
||||
u8x8_byte_SendByte(u8x8, arg_int & 0x0f0);
|
||||
u8x8_byte_SendByte(u8x8, arg_int << 4);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
|
||||
u8x8_byte_SendByte(u8x8, 0x0fa);
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
|
||||
|
||||
/* this loop should be optimized: multiple bytes should be sent */
|
||||
/* u8x8_byte_SendBytes(u8x8, arg_int, arg_ptr); */
|
||||
data = (uint8_t *)arg_ptr;
|
||||
|
||||
/* the following loop increases speed by 20% */
|
||||
while( arg_int >= 8 )
|
||||
{
|
||||
i = 8;
|
||||
ptr = buf;
|
||||
do
|
||||
{
|
||||
b = *data++;
|
||||
*ptr++= b & 0x0f0;
|
||||
b <<= 4;
|
||||
*ptr++= b;
|
||||
i--;
|
||||
} while( i > 0 );
|
||||
arg_int -= 8;
|
||||
u8x8_byte_SendBytes(u8x8, 16, buf);
|
||||
}
|
||||
|
||||
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
b = *data;
|
||||
u8x8_byte_SendByte(u8x8, b & 0x0f0);
|
||||
u8x8_byte_SendByte(u8x8, b << 4);
|
||||
data++;
|
||||
arg_int--;
|
||||
}
|
||||
u8x8_gpio_Delay(u8x8, U8X8_MSG_DELAY_NANO, 1);
|
||||
break;
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* cad procedure for the SSD13xx family in I2C mode */
|
||||
/* this procedure is also used by the ST7588 */
|
||||
/* u8x8_byte_SetDC is not used */
|
||||
/* U8X8_MSG_BYTE_START_TRANSFER starts i2c transfer, U8X8_MSG_BYTE_END_TRANSFER stops transfer */
|
||||
/* After transfer start, a full byte indicates command or data mode */
|
||||
|
||||
static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
|
||||
static void u8x8_i2c_data_transfer(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
u8x8_byte_SendByte(u8x8, 0x040);
|
||||
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, arg_ptr);
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
}
|
||||
|
||||
uint8_t u8x8_cad_ssd13xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t *p;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
/* 7 Nov 2016: Can this be improved? */
|
||||
//u8x8_byte_SetDC(u8x8, 0);
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
//u8x8_byte_SendByte(u8x8, u8x8_GetI2CAddress(u8x8));
|
||||
u8x8_byte_SendByte(u8x8, 0x000);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
//u8x8_byte_SetDC(u8x8, 1);
|
||||
|
||||
/* the FeatherWing OLED with the 32u4 transfer of long byte */
|
||||
/* streams was not possible. This is broken down to */
|
||||
/* smaller streams, 32 seems to be the limit... */
|
||||
/* I guess this is related to the size of the Wire buffers in Arduino */
|
||||
/* Unfortunately, this can not be handled in the byte level drivers, */
|
||||
/* so this is done here. Even further, only 24 bytes will be sent, */
|
||||
/* because there will be another byte (DC) required during the transfer */
|
||||
p = arg_ptr;
|
||||
while( arg_int > 24 )
|
||||
{
|
||||
u8x8_i2c_data_transfer(u8x8, 24, p);
|
||||
arg_int-=24;
|
||||
p+=24;
|
||||
}
|
||||
u8x8_i2c_data_transfer(u8x8, arg_int, p);
|
||||
break;
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
/* apply default i2c adr if required so that the start transfer msg can use this */
|
||||
if ( u8x8->i2c_address == 255 )
|
||||
u8x8->i2c_address = 0x078;
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
/* cad transfer commands are ignored */
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* the st75256 i2c driver is a copy of the ssd13xx driver, but with arg=1 */
|
||||
/* modified from cad001 (ssd13xx) to cad011 */
|
||||
uint8_t u8x8_cad_st75256_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t *p;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
u8x8_byte_SendByte(u8x8, 0x000);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
u8x8_byte_SendByte(u8x8, 0x040);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
/* see ssd13xx driver */
|
||||
p = arg_ptr;
|
||||
while( arg_int > 24 )
|
||||
{
|
||||
u8x8_i2c_data_transfer(u8x8, 24, p);
|
||||
arg_int-=24;
|
||||
p+=24;
|
||||
}
|
||||
u8x8_i2c_data_transfer(u8x8, arg_int, p);
|
||||
break;
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
/* apply default i2c adr if required so that the start transfer msg can use this */
|
||||
if ( u8x8->i2c_address == 255 )
|
||||
u8x8->i2c_address = 0x078; /* ST75256, often this is 0x07e */
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
/* cad transfer commands are ignored */
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cad i2c procedure for the ld7032 controller */
|
||||
uint8_t u8x8_cad_ld7032_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
static uint8_t in_transfer = 0;
|
||||
uint8_t *p;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
if ( in_transfer != 0 )
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
in_transfer = 1;
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
//u8x8_byte_SetDC(u8x8, 1);
|
||||
|
||||
/* the FeatherWing OLED with the 32u4 transfer of long byte */
|
||||
/* streams was not possible. This is broken down to */
|
||||
/* smaller streams, 32 seems to be the limit... */
|
||||
/* I guess this is related to the size of the Wire buffers in Arduino */
|
||||
/* Unfortunately, this can not be handled in the byte level drivers, */
|
||||
/* so this is done here. Even further, only 24 bytes will be sent, */
|
||||
/* because there will be another byte (DC) required during the transfer */
|
||||
p = arg_ptr;
|
||||
while( arg_int > 24 )
|
||||
{
|
||||
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
|
||||
arg_int-=24;
|
||||
p+=24;
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
u8x8_byte_SendByte(u8x8, 0x08); /* data write for LD7032 */
|
||||
}
|
||||
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
|
||||
break;
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
/* apply default i2c adr if required so that the start transfer msg can use this */
|
||||
if ( u8x8->i2c_address == 255 )
|
||||
u8x8->i2c_address = 0x060;
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
in_transfer = 0;
|
||||
break;
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
if ( in_transfer != 0 )
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* cad procedure for the UC16xx family in I2C mode */
|
||||
/* u8x8_byte_SetDC is not used */
|
||||
/* DC bit is encoded into the adr byte */
|
||||
uint8_t u8x8_cad_uc16xx_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
static uint8_t in_transfer = 0;
|
||||
static uint8_t is_data = 0;
|
||||
uint8_t *p;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_CAD_SEND_CMD:
|
||||
case U8X8_MSG_CAD_SEND_ARG:
|
||||
if ( in_transfer != 0 )
|
||||
{
|
||||
if ( is_data != 0 )
|
||||
{
|
||||
/* transfer mode is active, but data transfer */
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
/* clear the lowest two bits of the adr */
|
||||
u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clear the lowest two bits of the adr */
|
||||
u8x8_SetI2CAddress( u8x8, u8x8_GetI2CAddress(u8x8)&0x0fc );
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
}
|
||||
u8x8_byte_SendByte(u8x8, arg_int);
|
||||
in_transfer = 1;
|
||||
break;
|
||||
case U8X8_MSG_CAD_SEND_DATA:
|
||||
if ( in_transfer != 0 )
|
||||
{
|
||||
if ( is_data == 0 )
|
||||
{
|
||||
/* transfer mode is active, but data transfer */
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
/* clear the lowest two bits of the adr */
|
||||
u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* clear the lowest two bits of the adr */
|
||||
u8x8_SetI2CAddress( u8x8, (u8x8_GetI2CAddress(u8x8)&0x0fc)|2 );
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
}
|
||||
in_transfer = 1;
|
||||
|
||||
p = arg_ptr;
|
||||
while( arg_int > 24 )
|
||||
{
|
||||
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, 24, p);
|
||||
arg_int-=24;
|
||||
p+=24;
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
u8x8_byte_StartTransfer(u8x8);
|
||||
}
|
||||
u8x8->byte_cb(u8x8, U8X8_MSG_CAD_SEND_DATA, arg_int, p);
|
||||
|
||||
break;
|
||||
case U8X8_MSG_CAD_INIT:
|
||||
/* apply default i2c adr if required so that the start transfer msg can use this */
|
||||
if ( u8x8->i2c_address == 255 )
|
||||
u8x8->i2c_address = 0x070;
|
||||
return u8x8->byte_cb(u8x8, msg, arg_int, arg_ptr);
|
||||
case U8X8_MSG_CAD_START_TRANSFER:
|
||||
in_transfer = 0;
|
||||
/* actual start is delayed, because we do not whether this is data or cmd transfer */
|
||||
break;
|
||||
case U8X8_MSG_CAD_END_TRANSFER:
|
||||
if ( in_transfer != 0 )
|
||||
u8x8_byte_EndTransfer(u8x8);
|
||||
in_transfer = 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
|
||||
u8x8_d_a2printer.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
Use DC2 bitmap command of the A2 Micro panel termal printer
|
||||
double stroke
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
#define LINE_MIN_DELAY_MS 15
|
||||
/* higher values improve quality */
|
||||
/* however if the value is too high (>=5) then form feed does not work any more */
|
||||
#define LINE_EXTRA_8PIXEL_DELAY_MS 3
|
||||
/* this must be a power of two and between 1 and 8 */
|
||||
/* best quality only with 1 */
|
||||
#define NO_OF_LINES_TO_SEND_WITHOUT_DELAY 1
|
||||
|
||||
/* calculates the delay, based on the number of black pixel */
|
||||
/* actually only "none-zero" bytes are calculated which is, of course not so accurate, but should be good enough */
|
||||
uint16_t get_delay_in_milliseconds(uint8_t cnt, uint8_t *data)
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t time = LINE_MIN_DELAY_MS;
|
||||
for ( i = 0; i < cnt; i++ )
|
||||
if ( data[i] != 0 )
|
||||
time += LINE_EXTRA_8PIXEL_DELAY_MS;
|
||||
return time;
|
||||
}
|
||||
|
||||
uint8_t u8x8_d_a2printer_common(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t c, i, j;
|
||||
uint8_t *ptr;
|
||||
uint16_t delay_in_milliseconds;
|
||||
switch(msg)
|
||||
{
|
||||
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
|
||||
/*
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
// no setup required
|
||||
// u8x8_cad_SendSequence(u8x8, u8x8_d_a2printer_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
// no powersave
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 27); /* ESC */
|
||||
u8x8_cad_SendCmd(u8x8, 55 ); /* parameter command */
|
||||
/* increasing the "max printing dots" requires a good power supply, but LINE_EXTRA_8PIXEL_DELAY_MS could be reduced then */
|
||||
u8x8_cad_SendCmd(u8x8, 0); /* Max printing dots,Unit(8dots),Default:7(64 dots) 8*(x+1) ... lower values improve, probably my current supply is not sufficient */
|
||||
u8x8_cad_SendCmd(u8x8, 200); /* 3-255 Heating time,Unit(10us),Default:80(800us) */
|
||||
u8x8_cad_SendCmd(u8x8, 2); /* 0-255 Heating interval,Unit(10us),Default:2(20us) ... does not have much influence */
|
||||
|
||||
//c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
|
||||
c = u8x8->display_info->tile_width;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 18); /* DC2 */
|
||||
u8x8_cad_SendCmd(u8x8, 42 ); /* * */
|
||||
u8x8_cad_SendCmd(u8x8, 8 ); /* height */
|
||||
u8x8_cad_SendCmd(u8x8, c ); /* c, u8x8->display_info->tile_width */
|
||||
|
||||
for( j = 0; j < 8 / NO_OF_LINES_TO_SEND_WITHOUT_DELAY; j ++ )
|
||||
{
|
||||
|
||||
delay_in_milliseconds = 0;
|
||||
for( i = 0; i < NO_OF_LINES_TO_SEND_WITHOUT_DELAY; i++ )
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, c, ptr); /* c, note: SendData can not handle more than 255 bytes, send one line of data */
|
||||
delay_in_milliseconds += get_delay_in_milliseconds(c, ptr);
|
||||
ptr += c;
|
||||
}
|
||||
|
||||
while( delay_in_milliseconds > 200 )
|
||||
{
|
||||
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_MILLI, 200, NULL);
|
||||
delay_in_milliseconds -= 200;
|
||||
}
|
||||
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_MILLI, delay_in_milliseconds, NULL);
|
||||
}
|
||||
|
||||
/* set parameters back to their default values */
|
||||
u8x8_cad_SendCmd(u8x8, 27); /* ESC */
|
||||
u8x8_cad_SendCmd(u8x8, 55 ); /* parameter command */
|
||||
u8x8_cad_SendCmd(u8x8, 7); /* Max printing dots,Unit(8dots),Default:7(64 dots) 8*(x+1)*/
|
||||
u8x8_cad_SendCmd(u8x8, 80); /* 3-255 Heating time,Unit(10us),Default:80(800us) */
|
||||
u8x8_cad_SendCmd(u8x8, 2); /* 0-255 Heating interval,Unit(10us),Default:2(20us)*/
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_a2printer_384x240_display_info =
|
||||
{
|
||||
/* most of the settings are not required, because this is a serial RS232 printer */
|
||||
|
||||
/* chip_enable_level = */ 1,
|
||||
/* chip_disable_level = */ 0,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 5,
|
||||
/* pre_chip_disable_wait_ns = */ 5,
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 6,
|
||||
/* sda_setup_time_ns = */ 20,
|
||||
/* sck_pulse_width_ns = */ 140,
|
||||
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* old: sck_takeover_edge, new: active high (bit 1), rising edge (bit 0) */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 30,
|
||||
/* write_pulse_width_ns = */ 40,
|
||||
/* tile_width = */ 48,
|
||||
/* tile_hight = */ 30,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 384,
|
||||
/* pixel_height = */ 240
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_a2printer_384x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_a2printer_384x240_display_info);
|
||||
break;
|
||||
default:
|
||||
return u8x8_d_a2printer_common(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,552 @@
|
||||
/*
|
||||
|
||||
u8x8_d_il3820_296x128.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
il3820: 200x300x1
|
||||
|
||||
command
|
||||
0x22: assign actions
|
||||
0x20: execute actions
|
||||
|
||||
action for command 0x022 are (more or less guessed)
|
||||
bit 7: Enable Clock
|
||||
bit 6: Enable Charge Pump
|
||||
bit 5: Load Temparture Value (???)
|
||||
bit 4: Load LUT (???)
|
||||
bit 3: Initial Display (???)
|
||||
bit 2: Pattern Display --> Requires about 945ms with the LUT from below
|
||||
bit 1: Disable Charge Pump
|
||||
bit 0: Disable Clock
|
||||
|
||||
Disable Charge Pump and Clock require about 10ms
|
||||
Enable Charge Pump and Clock require about 100 to 300ms
|
||||
|
||||
Notes:
|
||||
- Introduced a refresh display message, which copies RAM to display
|
||||
- Charge pump is always enabled. Charge pump can be enabled/disabled via power save message
|
||||
- U8x8 will not really work because of the two buffers in the SSD1606, however U8g2 should be ok.
|
||||
|
||||
LUT for the 296x128 device (IL3820)
|
||||
LUT (cmd: 0x032 has 30 bytes)
|
||||
section 6.8 of the datasheet mentions 256 bits = 32 bytes for the LUT
|
||||
chapter 7 tells 30 bytes
|
||||
|
||||
according to section 6.8:
|
||||
20 bytes waveform
|
||||
10 bytes timing
|
||||
1 byte named as VSH/VSL
|
||||
1 empty byte
|
||||
according to the command table, the lut has 240 bits (=30 bytes * 8 bits)
|
||||
|
||||
|
||||
LUT / Refresh time
|
||||
total_refresh_time = (refresh_lines + dummy_lines*2)*TGate*TS_Sum/f_OSC
|
||||
|
||||
f_OSC=1MHz (according to the datasheets)
|
||||
refreh_lines = 296 (for the waveshare display, 0x045 cmd)
|
||||
dummy_lines = 22 (for the upcoming u8g2 code, 0x03a cmd)
|
||||
TGate = 62 (POR default, 0x03b cmd)
|
||||
TS_Sum: Sum of all TS entries of the second part of the LUT
|
||||
f_OSC: 1MHz according to the datasheet.
|
||||
|
||||
so we have
|
||||
|
||||
total_refresh_time = 21080*TS_Sum/1000000 = 21ms * TS_Sum
|
||||
|
||||
|
||||
This file includes two devices:
|
||||
u8x8_d_il3820_296x128 --> includes LUT which is probably from the WaveShare 2.9 Vendor
|
||||
u8x8_d_il3820_v2_296x128 --> includes LUT which was optimized for faster speed and lesser flicker
|
||||
|
||||
*/
|
||||
|
||||
/* Waveform part of the LUT (20 bytes) */
|
||||
/* bit 7/6: 1 - 1 transition */
|
||||
/* bit 5/4: 1 - 0 transition */
|
||||
/* bit 3/2: 0 - 1 transition */
|
||||
/* bit 1/0: 0 - 0 transition */
|
||||
/* 00 – VSS */
|
||||
/* 01 – VSH */
|
||||
/* 10 – VSL */
|
||||
/* 11 – NA */
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
/*=================================================*/
|
||||
/* common code for all devices */
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_il3820_296x128_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x22, 0xc0), /* enable clock and charge pump */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(200), /* according to my measures it may take up to 150ms */
|
||||
U8X8_DLY(100), /* but it might take longer */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_il3820_296x128_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
/* disable clock and charge pump only, deep sleep is not entered, because we will loose RAM content */
|
||||
U8X8_CA(0x22, 0x02), /* only disable charge pump, HW reset seems to be required if the clock is disabled */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(20),
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_il3820_296x128_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_il3820_296x128_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_il3820_296x128_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 120,
|
||||
/* pre_chip_disable_wait_ns = */ 60,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100,
|
||||
/* sda_setup_time_ns = */ 50, /* IL3820 */
|
||||
/* sck_pulse_width_ns = */ 125, /* IL3820: 125ns, clock cycle = 250ns */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150,
|
||||
/* tile_width = */ 37, /* 37*8 = 296 */
|
||||
/* tile_hight = */ 16, /* 16*8 = 128 */
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 296,
|
||||
/* pixel_height = */ 128
|
||||
};
|
||||
|
||||
|
||||
static uint8_t *u8x8_convert_tile_for_il3820(uint8_t *t)
|
||||
{
|
||||
uint8_t i;
|
||||
static uint8_t buf[8];
|
||||
uint8_t *pbuf = buf;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
*pbuf++ = ~(*t++);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void u8x8_d_il3820_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
|
||||
static void u8x8_d_il3820_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint16_t x;
|
||||
uint8_t c, page;
|
||||
uint8_t *ptr;
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
page = u8x8->display_info->tile_height;
|
||||
page --;
|
||||
page -= (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
|
||||
//u8x8_cad_SendCmd(u8x8, 0x011 ); /* cursor increment mode */
|
||||
//u8x8_cad_SendArg(u8x8, 7);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x04f ); /* set cursor column */
|
||||
u8x8_cad_SendArg(u8x8, x&255);
|
||||
u8x8_cad_SendArg(u8x8, x>>8);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x04e ); /* set cursor row */
|
||||
u8x8_cad_SendArg(u8x8, page);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x024 );
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_il3820(ptr));
|
||||
ptr += 8;
|
||||
x += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_il3820_exec_1000dly_seq[] = {
|
||||
// assumes, that the start transfer has happend
|
||||
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static void u8x8_d_il3820_first_init(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8_ClearDisplay(u8x8);
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x032); // program update sequence
|
||||
u8x8_cad_SendMultipleArg(u8x8, 8, 0x055); // all black
|
||||
u8x8_cad_SendMultipleArg(u8x8, 12, 0x0aa); // all white
|
||||
u8x8_cad_SendMultipleArg(u8x8, 10, 0x022); // 830ms
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_exec_1000dly_seq);
|
||||
|
||||
}
|
||||
|
||||
#ifdef OBSOLETE
|
||||
static void u8x8_d_il3820_second_init(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8_ClearDisplay(u8x8);
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x032); // program update sequence
|
||||
u8x8_cad_SendMultipleArg(u8x8, 20, 0x000); // do nothing
|
||||
u8x8_cad_SendMultipleArg(u8x8, 10, 0x011); // 414ms dly
|
||||
/* reuse sequence from above, ok some time is wasted here, */
|
||||
/* delay could be lesser */
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_exec_1000dly_seq);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*=================================================*/
|
||||
/* first version, LUT from WaveShare */
|
||||
|
||||
|
||||
/* http://www.waveshare.com/wiki/File:2.9inch_e-Paper_Module_code.7z */
|
||||
static const uint8_t u8x8_d_il3820_296x128_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: Disable */
|
||||
U8X8_C(0x01),
|
||||
U8X8_A(295 % 256), U8X8_A(295/256), U8X8_A(0),
|
||||
|
||||
|
||||
U8X8_CA(0x03, 0x00), /* Gate Driving voltage: 15V (lowest value)*/
|
||||
U8X8_CA(0x04, 0x0a), /* Source Driving voltage: 15V (mid value and POR)*/
|
||||
|
||||
//U8X8_CA(0x22, 0xc0), /* display update seq. option: enable clk, enable CP, .... todo: this is never activated */
|
||||
|
||||
//U8X8_CA(0x0b, 7), /* Set Delay of gate and source non overlap period, POR = 7 */
|
||||
U8X8_CA(0x2c, 0xa8), /* write vcom value*/
|
||||
U8X8_CA(0x3a, 0x16), /* dummy lines POR=22 (0x016) */
|
||||
U8X8_CA(0x3b, 0x08), /* gate time POR=0x08*/
|
||||
U8X8_CA(0x3c, 0x33), /* select boarder waveform */
|
||||
//U8X8_CA(0x22, 0xc4), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
|
||||
|
||||
|
||||
U8X8_CA(0x11, 0x07), /* Define data entry mode, x&y inc, x first*/
|
||||
|
||||
U8X8_CAA(0x44, 0, 29), /* RAM x start & end, 32*4=128 */
|
||||
U8X8_CAAAA(0x45, 0, 0, 295&255, 295>>8), /* RAM y start & end, 0..295 */
|
||||
|
||||
//U8X8_CA(0x4e, 0), /* set x pos, 0..29? */
|
||||
//U8X8_CAA(0x4f, 0, 0), /* set y pos, 0...320??? */
|
||||
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_il3820_to_display_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
/*
|
||||
0x50, 0xAA, 0x55, 0xAA, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0xFF, 0xFF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
measured 1582 ms
|
||||
*/
|
||||
U8X8_C(0x32), /* write LUT register*/
|
||||
/* original values */
|
||||
U8X8_A(0x50),
|
||||
U8X8_A(0xaa),
|
||||
U8X8_A(0x55),
|
||||
U8X8_A(0xaa),
|
||||
U8X8_A(0x11),
|
||||
|
||||
U8X8_A(0x11),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
|
||||
U8X8_A(0xff),
|
||||
U8X8_A(0xff),
|
||||
U8X8_A(0x3f),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display, assumes clk and charge pump are enabled */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
|
||||
U8X8_DLY(250), /* delay for 1620ms. The current sequence takes 1582ms */
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(120),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_il3820_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_il3820_296x128_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_init_seq);
|
||||
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
|
||||
u8x8_d_il3820_first_init(u8x8);
|
||||
|
||||
/* usually the DISPLAY_INIT message leaves the display in power save state */
|
||||
/* however this is not done for e-paper devices, see: */
|
||||
/* https://github.com/olikraus/u8g2/wiki/internal#powersave-mode */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_d_il3820_draw_tile(u8x8, arg_int, arg_ptr);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_REFRESH:
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_to_display_seq);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=================================================*/
|
||||
/* second version for the IL3820 display */
|
||||
|
||||
|
||||
/* http://www.waveshare.com/wiki/File:2.9inch_e-Paper_Module_code.7z */
|
||||
static const uint8_t u8x8_d_il3820_v2_296x128_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
// U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: POR: Normal mode */
|
||||
U8X8_C(0x01),
|
||||
U8X8_A(295 % 256), U8X8_A(295/256), U8X8_A(0),
|
||||
|
||||
/* the driving voltagesmust not be that high, in order to aviod level change after */
|
||||
/* some seconds (which happens with 0xea */
|
||||
U8X8_CA(0x03, 0x75), /* Gate Driving voltage: +/-15V =0x00 POR (+22/-20V) = 0x0ea*/
|
||||
U8X8_CA(0x04, 0x0a), /* Source Driving voltage: (POR=0x0a=15V), max=0x0e*/
|
||||
|
||||
U8X8_CA(0x0b, 7), /* Set Delay of gate and source non overlap period, POR = 7 */
|
||||
U8X8_CA(0x2c, 0xa8), /* write vcom value*/
|
||||
U8X8_CA(0x3a, 0x16), /* dummy lines POR=22 (0x016) */
|
||||
U8X8_CA(0x3b, 0x08), /* gate time POR=0x08*/
|
||||
U8X8_CA(0x3c, 0x33), /* select boarder waveform */
|
||||
|
||||
U8X8_CA(0x11, 0x07), /* Define data entry mode, x&y inc, x first*/
|
||||
U8X8_CAA(0x44, 0, 29), /* RAM x start & end, 32*4=128 */
|
||||
U8X8_CAAAA(0x45, 0, 0, 295&255, 295>>8), /* RAM y start & end, 0..295 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_il3820_v2_to_display_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
/*
|
||||
0xaa, 0x09, 0x09, 0x19, 0x19,
|
||||
0x11, 0x11, 0x11, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x75, 0x77, 0x77, 0x77, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00
|
||||
measured 1240 ms
|
||||
*/
|
||||
U8X8_C(0x32), /* write LUT register*/
|
||||
/* https://github.com/olikraus/u8g2/issues/347 */
|
||||
U8X8_A(0xaa),
|
||||
U8X8_A(0x09),
|
||||
U8X8_A(0x09),
|
||||
U8X8_A(0x19),
|
||||
U8X8_A(0x19),
|
||||
|
||||
U8X8_A(0x11),
|
||||
U8X8_A(0x11),
|
||||
U8X8_A(0x11),
|
||||
U8X8_A(0x11),
|
||||
U8X8_A(0x00),
|
||||
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
|
||||
U8X8_A(0x75),
|
||||
U8X8_A(0x77),
|
||||
U8X8_A(0x77),
|
||||
U8X8_A(0x77),
|
||||
U8X8_A(0x07),
|
||||
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
|
||||
U8X8_DLY(250), /* delay for 1400ms. The current sequence takes 1240ms, it was reported, that longer delays are better */
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(150), /* extended, #318 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_il3820_v2_296x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_il3820_296x128_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_v2_296x128_init_seq);
|
||||
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
|
||||
u8x8_d_il3820_first_init(u8x8);
|
||||
/* u8x8_d_il3820_second_init(u8x8); */ /* not required, u8g2.begin() will also clear the display once more */
|
||||
|
||||
/* usually the DISPLAY_INIT message leaves the display in power save state */
|
||||
/* however this is not done for e-paper devices, see: */
|
||||
/* https://github.com/olikraus/u8g2/wiki/internal#powersave-mode */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_296x128_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_d_il3820_draw_tile(u8x8, arg_int, arg_ptr);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_REFRESH:
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_il3820_v2_to_display_seq);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ist3020.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ist3020_erc19264_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a4), /* all pixel off, issue 142 */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ist3020_erc19264_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ist3020_erc19264_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ist3020_erc19264_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ist3020_erc19264_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* IST3020 datasheet, page 56 */
|
||||
/* pre_chip_disable_wait_ns = */ 150, /* IST3020 datasheet, page 56 */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 100, /* IST3020 datasheet, page 56 */
|
||||
/* sck_pulse_width_ns = */ 100, /* IST3020 datasheet, page 56 */
|
||||
/* sck_clock_hz = */ 4000000UL, /* */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* IST3020 datasheet, page 54 */
|
||||
/* write_pulse_width_ns = */ 60, /* IST3020 datasheet, page 54 */
|
||||
/* tile_width = */ 24, /* width of 24*8=192 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 64,
|
||||
/* pixel_width = */ 192,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ist3020_erc19264_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ab), /* build in osc on, used in ER code, but not mentioned in data sheet */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
U8X8_C(0x0c8), /* common output mode */
|
||||
// Flipmode
|
||||
//U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a3), /* FIX: LCD bias 1/7, old value was 1/9 (0x0a2) */
|
||||
|
||||
U8X8_C(0x028|4), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
U8X8_C(0x028|6), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
U8X8_C(0x028|7), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
|
||||
U8X8_C(0x020), /* v0 voltage resistor ratio */
|
||||
U8X8_CA(0x081, 0x019), /* set contrast, contrast value (from ER code: 45) */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ist3020_erc19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ist3020_erc19264_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ist3020_erc19264_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
c *= 8;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ks0108.c
|
||||
|
||||
The classic 5V LCD
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ks0108_init_seq[] = {
|
||||
U8X8_C(0x0c0), /* satart at the top */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ks0108_powersave0_seq[] = {
|
||||
U8X8_C(0x03f), /* display on */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ks0108_powersave1_seq[] = {
|
||||
U8X8_C(0x03e), /* display off */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
struct u8x8_ks0108_vars
|
||||
{
|
||||
uint8_t *ptr;
|
||||
uint8_t x;
|
||||
uint8_t c;
|
||||
uint8_t arg_int;
|
||||
};
|
||||
|
||||
static void u8x8_ks0108_out(u8x8_t *u8x8, struct u8x8_ks0108_vars *v, void *arg_ptr)
|
||||
{
|
||||
uint8_t cnt;
|
||||
u8x8_cad_SendCmd(u8x8, 0x040 | ((v->x << 3) & 63) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
while( v->arg_int > 0 )
|
||||
{
|
||||
/* calculate tiles to next boundary (end or chip limit) */
|
||||
cnt = v->x;
|
||||
cnt += 8;
|
||||
cnt &= 0x0f8;
|
||||
cnt -= v->x;
|
||||
|
||||
if ( cnt > v->c )
|
||||
cnt = v->c;
|
||||
|
||||
/* of cours we still could use cnt=1 here... */
|
||||
/* but setting cnt to 1 is not very efficient */
|
||||
//cnt = 1;
|
||||
|
||||
v->x +=cnt;
|
||||
v->c-=cnt;
|
||||
cnt<<=3;
|
||||
u8x8_cad_SendData(u8x8, cnt, v->ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
v->ptr += cnt;
|
||||
|
||||
if ( v->c == 0 )
|
||||
{
|
||||
v->ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
v->c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
v->arg_int--;
|
||||
}
|
||||
if ( ((v->x) & 7) == 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ks0108_128x64_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0, /* KS0108: Not used */
|
||||
/* chip_disable_level = */ 1, /* KS0108: Not used */
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 100,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 6, /* could be faster for the KS0108 */
|
||||
/* sda_setup_time_ns = */ 12,
|
||||
/* sck_pulse_width_ns = */ 75, /* KS0108: Not used */
|
||||
/* sck_clock_hz = */ 4000000UL, /* KS0108: Not used */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4, /* KS0108: Not used */
|
||||
/* data_setup_time_ns = */ 200,
|
||||
/* write_pulse_width_ns = */ 200, /* KS0108: actially 450 ns */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ks0108_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
struct u8x8_ks0108_vars v;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ks0108_128x64_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
}
|
||||
break;
|
||||
// The KS0108 can not mirror the cols and rows, use U8g2 for rotation
|
||||
// case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
// break;
|
||||
// The KS0108 has no internal contrast command
|
||||
// case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
// break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
|
||||
v.ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
v.x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
v.c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
v.arg_int = arg_int;
|
||||
|
||||
|
||||
if ( v.x < 8 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_ks0108_out(u8x8, &v, arg_ptr);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
}
|
||||
if ( v.x < 16 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 2, NULL);
|
||||
u8x8_ks0108_out(u8x8, &v, arg_ptr);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
}
|
||||
//if ( v.x < 24 )
|
||||
//{
|
||||
//u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 4, NULL);
|
||||
//u8x8_ks0108_out(u8x8, &v, arg_ptr);
|
||||
//u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
//}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* east rising (buydisplay.com) ERM19264 */
|
||||
/* left: 011, middle: 101, right: 110, no chip select: 111 */
|
||||
uint8_t u8x8_d_ks0108_erm19264(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
struct u8x8_ks0108_vars v;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ks0108_128x64_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_init_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave0_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ks0108_powersave1_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
|
||||
}
|
||||
break;
|
||||
// The KS0108 can not mirror the cols and rows, use U8g2 for rotation
|
||||
// case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
// break;
|
||||
// The KS0108 has no internal contrast command
|
||||
// case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
// break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
|
||||
v.ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
v.x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
v.c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
v.arg_int = arg_int;
|
||||
|
||||
|
||||
if ( v.x < 8 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 3, NULL);
|
||||
u8x8_ks0108_out(u8x8, &v, arg_ptr);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
}
|
||||
if ( v.x < 16 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 5, NULL);
|
||||
u8x8_ks0108_out(u8x8, &v, arg_ptr);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
}
|
||||
if ( v.x < 24 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 6, NULL);
|
||||
u8x8_ks0108_out(u8x8, &v, arg_ptr);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 7, NULL);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
|
||||
u8x8_d_lc7981.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
/* no powersave mode for the LC7981 */
|
||||
static const uint8_t u8x8_d_lc7981_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_lc7981_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
/* no hardware flip for the LC7981 */
|
||||
static const uint8_t u8x8_d_lc7981_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_lc7981_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
/* http://graphics.stanford.edu/~seander/bithacks.html */
|
||||
static uint8_t reverse_byte(uint8_t v)
|
||||
{
|
||||
// if ( v != 0 && v != 255 ) does not help much
|
||||
{
|
||||
// swap odd and even bits
|
||||
v = ((v >> 1) & 0x055) | ((v & 0x055) << 1);
|
||||
// swap consecutive pairs
|
||||
v = ((v >> 2) & 0x033) | ((v & 0x033) << 2);
|
||||
// swap nibbles ...
|
||||
v = ((v >> 4) & 0x00F) | ((v & 0x00F) << 4);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
static uint8_t u8x8_d_lc7981_common(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t c, i, j;
|
||||
uint16_t y;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
y*=8;
|
||||
y*= u8x8->display_info->tile_width;
|
||||
/* x = ((u8x8_tile_t *)arg_ptr)->x_pos; x is ignored... no u8x8 support */
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
/*
|
||||
Tile structure is reused here for the t6963, however u8x8 is not supported
|
||||
tile_ptr points to data which has cnt*8 bytes (same as SSD1306 tiles)
|
||||
Buffer is expected to have 8 lines of code fitting to the t6963 internal memory
|
||||
"cnt" includes the number of horizontal bytes. width is equal to cnt*8
|
||||
|
||||
x is assumed to be zero
|
||||
|
||||
TODO: Consider arg_int, however arg_int is not used by u8g2
|
||||
*/
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
u8x8_cad_SendCmd(u8x8, 0x0a ); /* display ram (cursor) address low byte */
|
||||
u8x8_cad_SendArg(u8x8, y&255);
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b ); /* display ram (cursor) address high byte */
|
||||
u8x8_cad_SendArg(u8x8, y>>8);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x0c ); /* write start */
|
||||
/*
|
||||
The LC7981 has the MSB at the right position, which is exactly the opposite to the T6963.
|
||||
Instead of writing a third hvline procedure for this device, we just revert the bytes before
|
||||
transmit. This is slow because:
|
||||
- the bit reverse itself
|
||||
- the single byte transfer
|
||||
The one byte is transmitted via SendArg, which is ok, because CAD = 100
|
||||
*/
|
||||
for( j = 0; j < c; j++ )
|
||||
u8x8_cad_SendArg(u8x8, reverse_byte(*ptr++));
|
||||
|
||||
//u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes, send one line of data */
|
||||
//ptr += u8x8->display_info->tile_width;
|
||||
|
||||
y += u8x8->display_info->tile_width;
|
||||
}
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
/* handled in the calling procedure
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_128x64_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
|
||||
break;
|
||||
*/
|
||||
/* power save is not there...
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_powersave1_seq);
|
||||
break;
|
||||
*/
|
||||
/* hardware flip not is not available
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
*/
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
/* no contrast setting :-(
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int );
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
*/
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
/* LC7981 160x80 LCD*/
|
||||
|
||||
static const u8x8_display_info_t u8x8_lc7981_160x80_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0, /* LC7981 has a low active CS*/
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* from here... */
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 10,
|
||||
/* sda_setup_time_ns = */ 30,
|
||||
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* ... to here, values are ignored, because this is a parallel interface only */
|
||||
|
||||
/* data_setup_time_ns = */ 220,
|
||||
/* write_pulse_width_ns = */ 20,
|
||||
/* tile_width = */ 20, /* width of 20*8=160 pixel */
|
||||
/* tile_hight = */ 10,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 160,
|
||||
/* pixel_height = */ 80
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_lc7981_160x80_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_DLY(50),
|
||||
|
||||
U8X8_CA(0x00, 0x32), /* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
|
||||
U8X8_CA(0x01, 0x07), /* character/bits per pixel pitch */
|
||||
U8X8_CA(0x02, 160/8-1), /* number of chars/byte width of the screen */
|
||||
U8X8_CA(0x03, 0x50), /* time division: 50 (1/80 duty cycle) */
|
||||
U8X8_CA(0x08, 0x00), /* display start low */
|
||||
U8X8_CA(0x09, 0x00), /* display start high */
|
||||
|
||||
U8X8_DLY(10),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_lc7981_160x80(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_160x80_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_160x80_init_seq);
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*================================================*/
|
||||
/* LC7981 160x160 LCD*/
|
||||
|
||||
static const u8x8_display_info_t u8x8_lc7981_160x160_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0, /* LC7981 has a low active CS*/
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* from here... */
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 10,
|
||||
/* sda_setup_time_ns = */ 30,
|
||||
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* ... to here, values are ignored, because this is a parallel interface only */
|
||||
|
||||
/* data_setup_time_ns = */ 220,
|
||||
/* write_pulse_width_ns = */ 20,
|
||||
/* tile_width = */ 20, /* width of 20*8=160 pixel */
|
||||
/* tile_hight = */ 20,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 160,
|
||||
/* pixel_height = */ 160
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_lc7981_160x160_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_DLY(50),
|
||||
|
||||
U8X8_CA(0x00, 0x32), /* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
|
||||
U8X8_CA(0x01, 0x07), /* character/bits per pixel pitch */
|
||||
U8X8_CA(0x02, 160/8-1), /* number of chars/byte width of the screen */
|
||||
U8X8_CA(0x03, 159), /* time division */
|
||||
U8X8_CA(0x08, 0x00), /* display start low */
|
||||
U8X8_CA(0x09, 0x00), /* display start high */
|
||||
|
||||
U8X8_DLY(10),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_lc7981_160x160(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_160x160_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_160x160_init_seq);
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*================================================*/
|
||||
/* LC7981 240x128 LCD*/
|
||||
|
||||
/*
|
||||
|
||||
*/
|
||||
static const u8x8_display_info_t u8x8_lc7981_240x128_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0, /* LC7981 has a low active CS*/
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* from here... */
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 10,
|
||||
/* sda_setup_time_ns = */ 30,
|
||||
/* sck_pulse_width_ns = */ 65, /* half of cycle time */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* ... to here, values are ignored, because this is a parallel interface only */
|
||||
|
||||
/* data_setup_time_ns = */ 220,
|
||||
/* write_pulse_width_ns = */ 20,
|
||||
/* tile_width = */ 30, /* width of 30*8=240 pixel */
|
||||
/* tile_hight = */ 16,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 240,
|
||||
/* pixel_height = */ 128
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_lc7981_240x128_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_DLY(50),
|
||||
|
||||
U8X8_CA(0x00, 0x32), /* display on (bit 5), master mode on (bit 4), graphics mode on (bit 1) */
|
||||
U8X8_CA(0x01, 0x07), /* character/bits per pixel pitch */
|
||||
U8X8_CA(0x02, 240/8-1), /* number of chars/byte width of the screen */
|
||||
U8X8_CA(0x03, 0x7f), /* time division */
|
||||
U8X8_CA(0x08, 0x00), /* display start low */
|
||||
U8X8_CA(0x09, 0x00), /* display start high */
|
||||
|
||||
U8X8_DLY(10),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_lc7981_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_lc7981_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_lc7981_240x128_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_lc7981_240x128_init_seq);
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ld7032_60x32.c
|
||||
Note: Flip Mode is NOT supported
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
/* testboard U8GLIB_LD7032_60x32 u8g(11, 12, 9, 10, 8); // SPI Com: SCK = 11, MOSI = 12, CS = 9, A0 = 10, RST = 8 (SW SPI Nano Board) */
|
||||
/* http://www.seeedstudio.com/document/pdf/0.5OLED%20SPEC.pdf */
|
||||
static const uint8_t u8x8_d_ld7032_60x32_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
//U8X8_CA(0x002, 0x001), /* Dot Matrix Display ON */
|
||||
U8X8_CA(0x014, 0x000), /* Stand-by OFF */
|
||||
U8X8_CA(0x01a, 0x004), /* Dot Matrix Frame Rate, special value for this OLED from manual*/
|
||||
U8X8_CA(0x01d, 0x000), /* Graphics Memory Writing Direction: reset default (right down, horizontal) */
|
||||
U8X8_CA(0x009, 0x000), /* Display Direction: reset default (x,y: min --> max) */
|
||||
U8X8_CAA(0x030, 0x000, 0x03b), /* Display Size X, Column Start - End*/
|
||||
U8X8_CAA(0x032, 0x000, 0x01f), /* Display Size Y, Row Start - End*/
|
||||
U8X8_CA(0x010, 0x000), /* Peak Pulse Width Set: 0 SCLK */
|
||||
U8X8_CA(0x016, 0x000), /* Peak Pulse Delay Set: 0 SCLK */
|
||||
U8X8_CA(0x012, 0x040), /* Dot Matrix Current Level Set: 0x050 * 1 uA = 80 uA */
|
||||
U8X8_CA(0x018, 0x003), /* Pre-Charge Pulse Width: 3 SCLK */
|
||||
U8X8_CA(0x044, 0x002), /* Pre-Charge Mode: Every Time */
|
||||
U8X8_CA(0x048, 0x003), /* Row overlap timing: Pre-Charge + Peak Delay + Peak boot Timing */
|
||||
U8X8_CA(0x03f, 0x011), /* VCC_R_SEL: ??? */
|
||||
U8X8_CA(0x03d, 0x000), /* VSS selection: 2.8V */
|
||||
//U8X8_CA(0x002, 0x001), /* Dot Matrix Display ON */
|
||||
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ld7032_60x32_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x002, 0x001), /* Dot Matrix Display ON */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ld7032_60x32_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x002, 0x000), /* Dot Matrix Display ON */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ld7032_60x32_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x009, 0x000), /* Display Direction: reset default (x,y: min --> max) */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ld7032_60x32_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
//U8X8_CA(0x009, 0x002), /* Display Direction: reset default (x,y: min --> max) */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ld7032_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ld7032_60x32_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ld7032_60x32_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x012 );
|
||||
if ( arg_int > 0x07f ) /* default is 0x040, limit to 0x07f to be on the safe side (hopefully) */
|
||||
arg_int= 0x07f;
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* values from 0x00 to 0x0ff are allowed, bit will all values be safe??? */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x += u8x8->x_offset/8;
|
||||
u8x8_cad_SendCmd(u8x8, 0x034 );
|
||||
u8x8_cad_SendArg(u8x8, x );
|
||||
u8x8_cad_SendCmd(u8x8, 0x035 );
|
||||
u8x8_cad_SendArg(u8x8, 0x007 );
|
||||
u8x8_cad_SendCmd(u8x8, 0x036 );
|
||||
u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos)*8 );
|
||||
u8x8_cad_SendCmd(u8x8, 0x037 );
|
||||
u8x8_cad_SendArg(u8x8, 0x01f );
|
||||
u8x8_cad_SendCmd(u8x8, 0x008 );
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ld7032_60x32_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 15,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100,
|
||||
/* sda_setup_time_ns = */ 30, /* 20ns, but cycle time is 60ns, so use 60/2 */
|
||||
/* sck_pulse_width_ns = */ 30, /* 20ns, but cycle time is 60ns, so use 60/2 */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 20,
|
||||
/* write_pulse_width_ns = */ 40,
|
||||
/* tile_width = */ 8,
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 60,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ld7032_60x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ld7032_60x32_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ld7032_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ls013b7dh03.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
The LS013B7DH02 is a simple display and controller
|
||||
--> no support for contrast adjustment, flip and power down.
|
||||
*/
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
#define SWAP8(a) ((((a) & 0x80) >> 7) | (((a) & 0x40) >> 5) | (((a) & 0x20) >> 3) | (((a) & 0x10) >> 1) | (((a) & 0x08) << 1) | (((a) & 0x04) << 3) | (((a) & 0x02) << 5) | (((a) & 0x01) << 7))
|
||||
|
||||
#define LS013B7DH03_CMD_UPDATE (0x01)
|
||||
#define LS013B7DH03_CMD_ALL_CLEAR (0x04)
|
||||
#define LS013B7DH03_VAL_TRAILER (0x00)
|
||||
|
||||
static const u8x8_display_info_t u8x8_ls013b7dh03_128x128_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 1,
|
||||
/* chip_disable_level = */ 0,
|
||||
/* post_chip_enable_wait_ns = */ 50,
|
||||
/* pre_chip_disable_wait_ns = */ 50,
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 6,
|
||||
/* sda_setup_time_ns = */ 227, /* 227 nsec according to the datasheet */
|
||||
/* sck_pulse_width_ns = */ 255, /* 450 nsec according to the datasheet */
|
||||
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 2, /* active low, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 100,
|
||||
/* write_pulse_width_ns = */ 100,
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 16,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 128
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ls013b7dh03_128x128(u8x8_t *u8x8, uint8_t msg, U8X8_UNUSED uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t y, c, i;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ls013b7dh03_128x128_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
|
||||
/* clear screen */
|
||||
u8x8_cad_SendCmd(u8x8, SWAP8(LS013B7DH03_CMD_ALL_CLEAR) );
|
||||
u8x8_cad_SendCmd(u8x8, LS013B7DH03_VAL_TRAILER);
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
/* not available for the ls013b7dh03 */
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
/* each tile is 8 lines, with the data starting at the left edge */
|
||||
y = ((((u8x8_tile_t *)arg_ptr)->y_pos) * 8) + 1;
|
||||
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
|
||||
/* send data mode byte */
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, SWAP8(LS013B7DH03_CMD_UPDATE) );
|
||||
|
||||
/* send 8 lines of 16 bytes (=128 pixels) */
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
u8x8_cad_SendCmd(u8x8, SWAP8(y + i) );
|
||||
u8x8_cad_SendData(u8x8, c, ptr);
|
||||
u8x8_cad_SendCmd(u8x8, LS013B7DH03_VAL_TRAILER);
|
||||
|
||||
ptr += c;
|
||||
}
|
||||
|
||||
/* finish with a trailing byte */
|
||||
u8x8_cad_SendCmd(u8x8, LS013B7DH03_VAL_TRAILER);
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
|
||||
u8x8_d_max7219.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_max7219_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(15, 0), /* test mode off */
|
||||
U8X8_CA(15, 0), /* test mode off */
|
||||
U8X8_CA(15, 0), /* test mode off */
|
||||
U8X8_CA(15, 0), /* test mode off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(12, 0), /* */
|
||||
U8X8_CA(12, 0), /* */
|
||||
U8X8_CA(12, 0), /* */
|
||||
U8X8_CA(12, 0), /* */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(9, 0), /* decode mode: graphics */
|
||||
U8X8_CA(9, 0), /* decode mode: graphics */
|
||||
U8X8_CA(9, 0), /* decode mode: graphics */
|
||||
U8X8_CA(9, 0), /* decode mode: graphics */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(10, 10), /* medium high intensity */
|
||||
U8X8_CA(10, 10), /* medium high intensity */
|
||||
U8X8_CA(10, 10), /* medium high intensity */
|
||||
U8X8_CA(10, 10), /* medium high intensity */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
|
||||
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
|
||||
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
|
||||
U8X8_CA(11, 7), /* scan limit: display all digits (assuming a 8x8 matrix) */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
|
||||
|
||||
//U8X8_CA(12, 0), /* shutdown */
|
||||
|
||||
//U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_max7219_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(12, 1), /* display on */
|
||||
U8X8_CA(12, 1), /* display on */
|
||||
U8X8_CA(12, 1), /* display on */
|
||||
U8X8_CA(12, 1), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_max7219_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(12, 0), /* shutdown */
|
||||
U8X8_CA(12, 0), /* shutdown */
|
||||
U8X8_CA(12, 0), /* shutdown */
|
||||
U8X8_CA(12, 0), /* shutdown */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_max7219_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t c, j, i;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcf8812_96x65_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_max7219_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_max7219_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_max7219_powersave1_seq);
|
||||
break;
|
||||
/* not supported by MAX7219
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
break;
|
||||
*/
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
|
||||
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
|
||||
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
|
||||
u8x8_cad_SendCmd(u8x8, 10 ); /* brightness */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int>>4) ); /* 0..15 for contrast */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
/* transfer always has to start at x pos 0 (u8x8 is not supported) */
|
||||
/* also y pos has to be 0 */
|
||||
/* arg_int is ignored */
|
||||
//x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
for( j = 0; j < c; j++ )
|
||||
{
|
||||
u8x8_cad_SendCmd(u8x8, i+1);
|
||||
u8x8_cad_SendArg(u8x8, *ptr );
|
||||
ptr++;
|
||||
}
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_max7219_32x8_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 100,
|
||||
/* pre_chip_disable_wait_ns = */ 100,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100,
|
||||
/* sda_setup_time_ns = */ 100,
|
||||
/* sck_pulse_width_ns = */ 100,
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150,
|
||||
/* tile_width = */ 4,
|
||||
/* tile_hight = */ 1,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 32,
|
||||
/* pixel_height = */ 16
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_max7219_32x8(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_max7219_32x8_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_max7219_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
|
||||
u8x8_d_pcd8544_84x48.c (so called "Nokia 5110" displays)
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_pcd8544_84x48_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x021), /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
|
||||
U8X8_C(0x006), /* temp. control: b10 = 2 */
|
||||
U8X8_C(0x013), /* bias system 1:48 */
|
||||
U8X8_C(0x0c0), /* medium Vop */
|
||||
|
||||
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
U8X8_C(0x008), /* blank */
|
||||
U8X8_C(0x024), /* power down (PD=1), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_pcd8544_84x48_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
U8X8_C(0x00c), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_pcd8544_84x48_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
U8X8_C(0x008), /* blank */
|
||||
U8X8_C(0x024), /* power down (PD=1), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_pcd8544_84x48_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 5,
|
||||
/* pre_chip_disable_wait_ns = */ 5,
|
||||
/* reset_pulse_width_ms = */ 2,
|
||||
/* post_reset_wait_ms = */ 2,
|
||||
/* sda_setup_time_ns = */ 12,
|
||||
/* sck_pulse_width_ns = */ 75, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 30,
|
||||
/* write_pulse_width_ns = */ 40,
|
||||
/* tile_width = */ 11, /* width of 11*8=88 pixel */
|
||||
/* tile_hight = */ 6,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 84,
|
||||
/* pixel_height = */ 48
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_pcd8544_84x48(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcd8544_84x48_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcd8544_84x48_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcd8544_84x48_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcd8544_84x48_powersave1_seq);
|
||||
break;
|
||||
// case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
// break; NOT SUPPORTED
|
||||
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x021 ); /* command mode, extended function set */
|
||||
u8x8_cad_SendCmd(u8x8, 0x080 | (arg_int >> 1) );
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x020 ); /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
u8x8_cad_SendCmd(u8x8, 0x080 | (x) ); /* set X address */
|
||||
u8x8_cad_SendCmd(u8x8, 0x040 | (((u8x8_tile_t *)arg_ptr)->y_pos) ); /* set Y address */
|
||||
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
c *= 8;
|
||||
do
|
||||
{
|
||||
if ( c + x > 84u )
|
||||
{
|
||||
if ( x >= 84u )
|
||||
break;
|
||||
c = 84u;
|
||||
c -= x;
|
||||
}
|
||||
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
x += c;
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
|
||||
u8x8_d_pcf8812.c
|
||||
|
||||
pcf8812: 65x102
|
||||
pcf8814: 65x96
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_pcf8812_96x65_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x020), /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
U8X8_C(0x008), /* blank display */
|
||||
|
||||
U8X8_C(0x021), /* activate chip (PD=0), horizontal increment (V=0), enter extended command set (H=1) */
|
||||
U8X8_C(0x006), /* temp. control: b10 = 2 */
|
||||
U8X8_C(0x013), /* bias system, 0x010..0x07 1:48 */
|
||||
U8X8_C(0x09f), /* contrast setting, 0..127 */
|
||||
//U8X8_CA(0x020 | 2, 0x080 | 0), /* contrast setting, pcf8814 */
|
||||
|
||||
U8X8_C(0x024), /* deactivate chip (PD=1), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_pcf8812_96x65_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x020), /* power on */
|
||||
U8X8_C(0x00c), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_pcf8812_96x65_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x020), /* power on */
|
||||
U8X8_C(0x008), /* blank display */
|
||||
U8X8_C(0x024), /* power down */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_pcf8812_96x65_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcf8812_96x65_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_powersave1_seq);
|
||||
break;
|
||||
/*
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_pcf8812_96x65_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
*/
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x021 ); /* command mode, extended function set */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int>>1)|0x80 ); /* 0..127 for contrast */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x020 ); /* activate chip (PD=0), horizontal increment (V=0), enter normal command set (H=0) */
|
||||
u8x8_cad_SendCmd(u8x8, 0x080 | x);
|
||||
u8x8_cad_SendCmd(u8x8, 0x040 | ((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
/*
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 8, ptr);
|
||||
ptr += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
*/
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_pcf8812_96x65_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 100,
|
||||
/* pre_chip_disable_wait_ns = */ 100,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100,
|
||||
/* sda_setup_time_ns = */ 100,
|
||||
/* sck_pulse_width_ns = */ 100,
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150,
|
||||
/* tile_width = */ 12,
|
||||
/* tile_hight = */ 9,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 96,
|
||||
/* pixel_height = */ 65
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_pcf8812_96x65(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_pcf8812_96x65_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_pcf8812_96x65_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
|
||||
u8x8_d_sbn1661.c
|
||||
|
||||
SED1520 / SBN1661 122x32 5V LCD
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_sbn1661_init_seq[] = {
|
||||
U8X8_C(0x0c0), /* display start at line 0 */
|
||||
U8X8_C(0x0a0), /* a0: ADC forward, a1: ADC reverse */
|
||||
U8X8_C(0x0a4), /* a4: normal driving, a5: power save */
|
||||
U8X8_C(0x0a9), /* a8: 1/16, a9: 1/32 duty */
|
||||
|
||||
//U8X8_C(0x0af), /* display on */
|
||||
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_sbn1661_powersave0_seq[] = {
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_sbn1661_powersave1_seq[] = {
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
struct u8x8_sbn1661_vars
|
||||
{
|
||||
uint8_t *ptr;
|
||||
uint8_t x;
|
||||
uint8_t c;
|
||||
uint8_t arg_int;
|
||||
};
|
||||
|
||||
static void u8x8_sbn1661_out(u8x8_t *u8x8, struct u8x8_sbn1661_vars *v, void *arg_ptr)
|
||||
{
|
||||
uint8_t cnt;
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((v->x << 3) & 63) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
while( v->arg_int > 0 )
|
||||
{
|
||||
/* calculate tiles to next boundary (end or chip limit) */
|
||||
cnt = v->x;
|
||||
cnt += 8;
|
||||
cnt &= 0x0f8;
|
||||
cnt -= v->x;
|
||||
|
||||
if ( cnt > v->c )
|
||||
cnt = v->c;
|
||||
|
||||
/* of course we still could use cnt=1 here... */
|
||||
/* but setting cnt to 1 is not very efficient */
|
||||
//cnt = 1;
|
||||
|
||||
v->x +=cnt;
|
||||
v->c-=cnt;
|
||||
cnt<<=3;
|
||||
u8x8_cad_SendData(u8x8, cnt, v->ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
v->ptr += cnt;
|
||||
|
||||
if ( v->c == 0 )
|
||||
{
|
||||
v->ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
v->c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
v->arg_int--;
|
||||
}
|
||||
if ( ((v->x) & 7) == 0 )
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_sbn1661_122x32_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0, /* sbn1661: Not used */
|
||||
/* chip_disable_level = */ 1, /* sbn1661: Not used */
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 100,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 6, /* */
|
||||
/* sda_setup_time_ns = */ 12,
|
||||
/* sck_pulse_width_ns = */ 75, /* sbn1661: Not used */
|
||||
/* sck_clock_hz = */ 4000000UL, /* sbn1661: Not used */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4, /* sbn1661: Not used */
|
||||
/* data_setup_time_ns = */ 200,
|
||||
/* write_pulse_width_ns = */ 200, /* */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 122,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_sbn1661_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
//uint8_t x;
|
||||
//uint8_t c;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sbn1661_122x32_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_init_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_init_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave0_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave0_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave1_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sbn1661_powersave1_seq);
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
|
||||
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
// x and c are ignored (u8g2 only)
|
||||
//x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
//c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 0, NULL);
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | 0); // column 0
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
u8x8_cad_SendData(u8x8, 61, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 0, NULL);
|
||||
|
||||
ptr += 61;
|
||||
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_START_TRANSFER, 1, NULL);
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | 0); // column 0
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b8 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
u8x8_cad_SendData(u8x8, 61, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
u8x8->cad_cb(u8x8, U8X8_MSG_CAD_END_TRANSFER, 1, NULL);
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t u8x8_d_sed1520_122x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
return u8x8_d_sbn1661_122x32(u8x8, msg, arg_int, arg_ptr);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,351 @@
|
||||
/*
|
||||
|
||||
u8x8_d_sed1330.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
The device might also work with the RA8835, SED1335 and SED1336 controller.
|
||||
The following devices might be compatible:
|
||||
RA8835
|
||||
SED1330
|
||||
SED1335
|
||||
S1D13700
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_sed1330_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
|
||||
U8X8_CA(0x059, 0x004), /* send display on command (hex 0x059, see p37 ) */
|
||||
/* display cmd has one arg: 01010100 should enable all three blocks, but disable the cursor*/
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_sed1330_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x058, 0x000), /* send display off command (hex 0x059, see p37) and turn of all banks */
|
||||
/* maybe send a sleep in cmd */
|
||||
//U8X8_C(0x053) /* sleep in: 0x053 */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_sed1330_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t c, i;
|
||||
uint16_t y;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
|
||||
/*
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
y*=8;
|
||||
y*= u8x8->display_info->tile_width;
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt; /* number of tiles */
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr; /* data ptr to the tiles */
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
u8x8_cad_SendCmd(u8x8, 0x046 ); /* CSRW command*/
|
||||
u8x8_cad_SendArg(u8x8, y&255); /* CSRW low adr byte */
|
||||
u8x8_cad_SendArg(u8x8, y>>8); /* CSRW high adr byte */
|
||||
u8x8_cad_SendCmd(u8x8, 0x042 ); /* MWRITE */
|
||||
|
||||
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes, send one line of data */
|
||||
|
||||
ptr += u8x8->display_info->tile_width;
|
||||
y += u8x8->display_info->tile_width;
|
||||
}
|
||||
|
||||
/* sometimes the display switches off... so just sent a display on command */
|
||||
u8x8_cad_SendCmd(u8x8, 0x059 ); /* display on */
|
||||
u8x8_cad_SendArg(u8x8, 0x004); /* arg for display on */
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
//u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, 200, NULL); /* extra dely required */
|
||||
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=============================================*/
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_sed1330_240x128_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 30, /* G242CX Datasheet p5 */
|
||||
/* pre_chip_disable_wait_ns = */ 10, /* G242CX Datasheet p5 */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 6,
|
||||
/* sda_setup_time_ns = */ 20,
|
||||
/* sck_pulse_width_ns = */ 140,
|
||||
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0,
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 120, /* G242CX Datasheet p5 */
|
||||
/* write_pulse_width_ns = */ 220, /* G242CX Datasheet p5 */
|
||||
/* tile_width = */ 0x01e,
|
||||
/* tile_hight = */ 16,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 240,
|
||||
/* pixel_height = */ 128
|
||||
};
|
||||
|
||||
/* 240x128 Seiko G242C */
|
||||
static const uint8_t u8x8_d_sed1330_240x128_init_seq[] = {
|
||||
U8X8_DLY(100),
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_DLY(100),
|
||||
|
||||
/* system init command, see also u8x8_d_sed1330_powersave0_seq */
|
||||
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
|
||||
/* system init has total 8 parameters, so 7 more are here */
|
||||
U8X8_A(0x087), /* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
|
||||
U8X8_A(0x007), /* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
|
||||
U8X8_A(0x01d), /* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
|
||||
U8X8_A(0x050), /* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
|
||||
U8X8_A(0x080), /* L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
|
||||
U8X8_A(0x01e), /* Low byte of the virtual screen size. (Value confirmed with app notes p41) */
|
||||
U8X8_A(0), /* High byte of the virtual screen size, see also section 9.1.2 */
|
||||
|
||||
U8X8_C(0x044), /* SCROLL */
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x080),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x040),
|
||||
U8X8_A(0x080),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
|
||||
U8X8_CA(0x05a, 0), /* HDOT SCR: Horizontal dotwise scroll... set to 0 */
|
||||
|
||||
U8X8_CA(0x05b, 0x0c), /* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
|
||||
|
||||
|
||||
U8X8_DLY(100),
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_DLY(100),
|
||||
};
|
||||
|
||||
/* RA8835 NHD-240128BZ */
|
||||
static const uint8_t u8x8_d_rh8835_nhd_240128_init_seq[] = {
|
||||
U8X8_DLY(100),
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_DLY(100),
|
||||
|
||||
/* system init command, see also u8x8_d_sed1330_powersave0_seq */
|
||||
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
|
||||
/* system init has total 8 parameters, so 7 more are here */
|
||||
U8X8_A(0x087), /* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
|
||||
U8X8_A(0x007), /* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
|
||||
U8X8_A(0x01d), /* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
|
||||
U8X8_A(0x050), /* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
|
||||
U8X8_A(0x080), /* L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
|
||||
U8X8_A(0x01e), /* Low byte of the virtual screen size. (Value confirmed with app notes p41) */
|
||||
U8X8_A(0), /* High byte of the virtual screen size, see also section 9.1.2 */
|
||||
|
||||
U8X8_C(0x044), /* SCROLL */
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x080),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x040),
|
||||
U8X8_A(0x080),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
|
||||
//U8X8_CA(0x05a, 0), /* HDOT SCR: Horizontal dotwise scroll... set to 0 */
|
||||
|
||||
U8X8_CA(0x05b, 0x0c), /* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
|
||||
|
||||
//U8X8_CA(0x059, 0x04), /* send display on command (hex 0x059, see p37 ) */
|
||||
|
||||
U8X8_DLY(100),
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_DLY(100),
|
||||
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_sed1330_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_240x128_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_240x128_init_seq);
|
||||
break;
|
||||
default:
|
||||
return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_d_ra8835_nhd_240x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_240x128_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_rh8835_nhd_240128_init_seq);
|
||||
break;
|
||||
default:
|
||||
return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=============================================*/
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_sed1330_320x240_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 30, /* G242CX Datasheet p5 */
|
||||
/* pre_chip_disable_wait_ns = */ 10, /* G242CX Datasheet p5 */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 6,
|
||||
/* sda_setup_time_ns = */ 20,
|
||||
/* sck_pulse_width_ns = */ 140,
|
||||
/* sck_clock_hz = */ 1000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0,
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 120, /* G242CX Datasheet p5 */
|
||||
/* write_pulse_width_ns = */ 220, /* G242CX Datasheet p5 */
|
||||
/* tile_width = */ 40,
|
||||
/* tile_hight = */ 30,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 320,
|
||||
/* pixel_height = */ 240
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_sed1330_320x240_init_seq[] = {
|
||||
U8X8_DLY(100),
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_DLY(100),
|
||||
|
||||
/* system init command, see also u8x8_d_sed1330_powersave0_seq */
|
||||
U8X8_CA(0x040, 0x030), /* sys init (0x040) with one arg, where 0x030 is a wild guess */
|
||||
/* system init has total 8 parameters, so 7 more are here */
|
||||
U8X8_A(0x087), /* no idea here... WF (topmost bit) is set to one because it is suggested in the datasheet, lowest 3 bits refer to text mode only */
|
||||
U8X8_A(0x007), /* FY: height of a char+1, does not matter here (hopefully), because we use graphics mode only */
|
||||
U8X8_A(0x027), /* 40-1 */ /* C/R: this could be the number of horizontal bytes - 1 (Value confirmed with app notes p41) */
|
||||
U8X8_A(0x039), /* TC/R: According to app notes fOSC=6Mhz fFF=70Hz --> TC/R = 74d*/
|
||||
U8X8_A(0x0ef), /* L/F: Lines per frame - 1, probably this is the height of the display - 1 (value confirmed with app notes p41)*/
|
||||
U8X8_A(0x028), /* Low byte of the virtual screen size. (Value confirmed with app notes p41) */
|
||||
U8X8_A(0), /* High byte of the virtual screen size, see also section 9.1.2 */
|
||||
|
||||
U8X8_C(0x044), /* SCROLL */
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x0ef),
|
||||
U8X8_A(0x0b0),
|
||||
U8X8_A(0x004),
|
||||
U8X8_A(0x0ef),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
U8X8_A(0x000),
|
||||
|
||||
U8X8_CA(0x05a, 0), /* HDOT SCR: Horizontal dotwise scroll... set to 0 */
|
||||
|
||||
U8X8_CA(0x05b, 0x0c), /* OVLAY: 2-layer, all graphics, OR between layer 1 and 2 */
|
||||
|
||||
|
||||
U8X8_DLY(100),
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_DLY(100),
|
||||
};
|
||||
|
||||
|
||||
|
||||
uint8_t u8x8_d_ra8835_320x240(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sed1330_320x240_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sed1330_320x240_init_seq);
|
||||
break;
|
||||
default:
|
||||
return u8x8_d_sed1330_common(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1305.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1305_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1305_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1305_128x32_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0d3, 32), /* display offset to 32 */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1305_128x32_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0d3, 0), /* display offset to */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1305_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendArg(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos) );
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
/*
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 8, ptr);
|
||||
ptr += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
*/
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_powersave1_seq);
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1305 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* timing from SSD1306 */
|
||||
static const u8x8_display_info_t u8x8_ssd1305_128x32_noname_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 2,
|
||||
/* flipmode_x_offset = */ 2,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1305_128x32_noname_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
|
||||
U8X8_CA(0x0d3, 32), /* display offset to 32 */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
|
||||
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control */
|
||||
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
|
||||
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
|
||||
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
|
||||
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1305_128x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
|
||||
if ( u8x8_d_ssd1305_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1305_128x32_noname_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1305_128x32_noname_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1306_128x32.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
/* UG-2832HSWEG02 Datasheet, Section 4.4 */
|
||||
static const uint8_t u8x8_d_ssd1306_128x32_univision_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x002), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
U8X8_CA(0x081, 0x08f), /* [2] set contrast control */
|
||||
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
|
||||
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x32_univision_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x32_univision_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x32_univision_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x32_univision_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1306_128x32_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x32_univision_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x32_univision_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
/*
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 8, ptr);
|
||||
ptr += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
*/
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1306_128x32_univision_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1306_128x32_univision(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x32_univision_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1306_128x32_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,465 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1306_128x64_noname.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
/* more or less generic setup of all these small OLEDs */
|
||||
static const uint8_t u8x8_d_ssd1306_128x64_noname_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, SSD1306 only, should be removed for SH1106 */
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
|
||||
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control */
|
||||
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
|
||||
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
|
||||
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
|
||||
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
/* this setup maximizes the brightness range, that can be set with setContrast() */
|
||||
/* Drawback: VCOMH deselect level is set to 0, which das not work so good with all OLEDs, issue #116 */
|
||||
static const uint8_t u8x8_d_ssd1306_128x64_vcomh0_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
U8X8_CA(0x081, 0x0ef), /* [2] set contrast control, */
|
||||
U8X8_CA(0x0d9, 0x0a1), /* [2] pre-charge period 0x022/f1*/
|
||||
U8X8_CA(0x0db, 0x000), /* vcomh deselect level 0x000 .. 0x070, low nibble always 0 */
|
||||
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
/* same as u8x8_d_ssd1306_128x64_noname_init_seq, but 0x0da bit 4 is set to 0 */
|
||||
/* this will disable the alternative COM configuration */
|
||||
static const uint8_t u8x8_d_ssd1306_128x64_alt0_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, SSD1306 only, should be removed for SH1106 */
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x002), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
|
||||
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control */
|
||||
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x022/f1*/
|
||||
U8X8_CA(0x0db, 0x040), /* vcomh deselect level */
|
||||
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
|
||||
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* issue 316: a special sh1106 setup, https://www.mikrocontroller.net/topic/431371?goto=5087807#5087807 */
|
||||
static const uint8_t u8x8_d_sh1106_128x64_winstar_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0xae), // Display OFF/ON: off (POR = 0xae)
|
||||
U8X8_C(0xa4), // Set Entire Display OFF/ON: off (POR = 0xa4)
|
||||
U8X8_CA(0xd5, 0x50), // Divide Ratio/Oscillator FrequencyData Set: divide ratio = 1 (POR = 1), Oscillator Frequency = +/- 0% (POR = +/- 0%)
|
||||
U8X8_CA(0xa8, 0x3f), // Multiplex Ratio Data Set: 64 (POR = 0x3f, 64)
|
||||
U8X8_CA(0xd3, 0x00), // Display OffsetData Set: 0 (POR = 0x00)
|
||||
U8X8_C(0x40), // Set Display Start Line: 0
|
||||
U8X8_CA(0xad, 0x8b), // DC-DC ON/OFF Mode Set: Built-in DC-DC is used, Normal Display (POR = 0x8b)
|
||||
U8X8_CA(0xd9, 0x22), // Dis-charge/Pre-charge PeriodData Set: pre-charge 2 DCLKs, dis-charge 2 DCLKs (POR = 0x22, pre-charge 2 DCLKs, dis-charge 2 DCLKs)
|
||||
U8X8_CA(0xdb, 0x35), // VCOM Deselect LevelData Set: 0,770V (POR = 0x35, 0,770 V)
|
||||
U8X8_C(0x32), // Set Pump voltage value: 8,0 V (POR = 0x32, 8,0 V)
|
||||
U8X8_CA(0x81, 0xff), // Contrast Data Register Set: 255 (large) (POR = 0x80)
|
||||
U8X8_C(0x0a6), // Set Normal/Reverse Display: normal (POR = 0xa6)
|
||||
U8X8_CA(0x0da, 0x012), // com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5)
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x64_noname_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x64_noname_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x64_noname_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_128x64_noname_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1306_sh1106_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
|
||||
break;
|
||||
*/
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_init_seq);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x040 ); /* set line offset to 0 */
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendArg(u8x8, 0x000 | ((x&15))); /* probably wrong, should be SendCmd */
|
||||
u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos)); /* probably wrong, should be SendCmd */
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
/*
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 8, ptr);
|
||||
ptr += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
*/
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1306_128x64_noname_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1306_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
|
||||
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t u8x8_d_ssd1306_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
|
||||
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_vcomh0_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t u8x8_d_ssd1306_128x64_alt0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
|
||||
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_alt0_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_128x64_noname_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_sh1106_128x64_noname_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
|
||||
/* spi_mode = */ 3, /* active low (clock is high by default), rising edge, this seems to be a difference to the ssd1306 */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 2,
|
||||
/* flipmode_x_offset = */ 2,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_sh1106_128x64_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
/* maybe use a better init sequence */
|
||||
/* https://www.mikrocontroller.net/topic/431371 */
|
||||
/* the new sequence is added in the winstar constructor (see below), this is kept untouched */
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_noname_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_128x64_noname_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
uint8_t u8x8_d_sh1106_128x64_vcomh0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_128x64_vcomh0_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_128x64_noname_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
uint8_t u8x8_d_sh1106_128x64_winstar(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( u8x8_d_ssd1306_sh1106_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_sh1106_128x64_winstar_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_sh1106_128x64_noname_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1306_64x32.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x32_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x32_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x32_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x32_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1306_64x32_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x32_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_noname_init_seq);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*======================================================*/
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1306_64x32_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 8,
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 32,
|
||||
/* flipmode_x_offset = */ 32,
|
||||
/* pixel_width = */ 64,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
|
||||
/*======================================================*/
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x32_noname_init_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x02f), /* multiplex ratio: changed from 0x1f to 0x2f */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1 */
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control datasheet: 0xcf */
|
||||
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1 */
|
||||
U8X8_CA(0x0db, 0x000), /* vcomh deselect level */
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1306_64x32_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x32_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_noname_init_seq);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1306_64x32_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
/*======================================================*/
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x32_1f_init_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio: changed from 0x1f to 0x2f, 23 Sep 17: changed back to 1f */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable */
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1 */
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control datasheet: 0xcf */
|
||||
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1 */
|
||||
U8X8_CA(0x0db, 0x000), /* vcomh deselect level */
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1306_64x32_1f(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x32_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x32_1f_init_seq);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1306_64x32_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1306_64x48.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
/* EastRising 0.66 OLED */
|
||||
static const uint8_t u8x8_d_ssd1306_64x48_er_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x02f), /* multiplex ratio, 0.66 OLED: changed from 0x1f to 0x2f */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset, 0.66 OLED */
|
||||
U8X8_C(0x040), /* set display start line to 0, 0.66 OLED */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, 0.66 OLED 0x14*/
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1, 0.66 OLED */
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse, 0.66 OLED */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.66 OLED */
|
||||
U8X8_CA(0x081, 0x0cf), /* [2] set contrast control, 0.66 OLED datasheet: 0xcf */
|
||||
U8X8_CA(0x0d9, 0x022), /* [2] pre-charge period 0x022/f1, 0.66 OLED datasheet: 0x22 */
|
||||
U8X8_CA(0x0db, 0x000), /* vcomh deselect level, 0.66 OLED datasheet: 0x00 */
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x48_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x48_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x48_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_64x48_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1306_64x48_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x48_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_er_init_seq);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1306_64x48_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 8,
|
||||
/* tile_hight = */ 6,
|
||||
/* default_x_offset = */ 32,
|
||||
/* flipmode_x_offset = */ 32,
|
||||
/* pixel_width = */ 64,
|
||||
/* pixel_height = */ 48
|
||||
};
|
||||
|
||||
/* East Rising 0.66" OLED */
|
||||
uint8_t u8x8_d_ssd1306_64x48_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_64x48_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_64x48_er_init_seq);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1306_64x48_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1306_96x16.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
/* EastRising 0.69 OLED */
|
||||
static const uint8_t u8x8_d_ssd1306_96x16_er_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x080), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
U8X8_CA(0x0a8, 0x00f), /* multiplex ratio, 0.69 OLED: 0x0f */
|
||||
U8X8_CA(0x0d3, 0x000), /* display offset, 0.69 OLED */
|
||||
U8X8_C(0x040), /* set display start line to 0, 0.69 OLED */
|
||||
U8X8_CA(0x08d, 0x014), /* [2] charge pump setting (p62): 0x014 enable, 0x010 disable, 0.66 OLED 0x14*/
|
||||
U8X8_CA(0x020, 0x000), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1, 0.66 OLED */
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse, 0.66 OLED */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x002), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5), 0.66 OLED */
|
||||
U8X8_CA(0x081, 0x0af), /* [2] set contrast control, 0.69 OLED datasheet: 0xaf */
|
||||
U8X8_CA(0x0d9, 0x0f1), /* [2] pre-charge period 0x0f1, 0.69 OLED datasheet: 0xf1 */
|
||||
U8X8_CA(0x0db, 0x020), /* vcomh deselect level, 0.69 OLED datasheet: 0x20 */
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_96x16_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_96x16_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_96x16_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1306_96x16_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1306_96x16_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_96x16_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_er_init_seq);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1306 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1306_96x16_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 8000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215) */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 12,
|
||||
/* tile_hight = */ 2,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 32,
|
||||
/* pixel_width = */ 96,
|
||||
/* pixel_height = */ 16
|
||||
};
|
||||
|
||||
/* East Rising 0.69" OLED */
|
||||
uint8_t u8x8_d_ssd1306_96x16_er(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1306_96x16_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1306_96x16_er_init_seq);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1306_96x16_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1309.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1309_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1309_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1309_128x64_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1309_128x64_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1309_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendArg(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendArg(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos) );
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
/*
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 8, ptr);
|
||||
ptr += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
*/
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_powersave1_seq);
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1309 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=================================================*/
|
||||
/* offset 2 version */
|
||||
|
||||
/* timing from SSD1306 */
|
||||
static const u8x8_display_info_t u8x8_ssd1309_128x64_noname2_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 2,
|
||||
/* flipmode_x_offset = */ 2,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1309_128x64_noname_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0d5, 0x0a0), /* clock divide ratio (0x00=1) and oscillator frequency (0x8) */
|
||||
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
U8X8_CA(0x020, 0x002), /* page addressing mode */
|
||||
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
// U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
|
||||
U8X8_CA(0x0da, 0x012), /* com pin HW config, sequential com pin config (bit 4), disable left/right remap (bit 5) */
|
||||
|
||||
U8X8_CA(0x081, 0x06f), /* [2] set contrast control */
|
||||
U8X8_CA(0x0d9, 0x0d3), /* [2] pre-charge period 0x022/f1*/
|
||||
U8X8_CA(0x0db, 0x020), /* vcomh deselect level */
|
||||
// if vcomh is 0, then this will give the biggest range for contrast control issue #98
|
||||
// restored the old values for the noname constructor, because vcomh=0 will not work for all OLEDs, #116
|
||||
|
||||
U8X8_C(0x02e), /* Deactivate scroll */
|
||||
U8X8_C(0x0a4), /* output ram to display */
|
||||
U8X8_C(0x0a6), /* none inverted normal display mode */
|
||||
|
||||
//U8X8_C(0x0af), /* display on */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1309_128x64_noname2(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
|
||||
if ( u8x8_d_ssd1309_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_noname_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1309_128x64_noname2_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*=================================================*/
|
||||
/* offset 0 version */
|
||||
|
||||
/* timing from SSD1306 */
|
||||
static const u8x8_display_info_t u8x8_ssd1309_128x64_noname0_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1306: 3 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1306: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1306: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1306: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1309_128x64_noname0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
|
||||
if ( u8x8_d_ssd1309_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1309_128x64_noname_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1309_128x64_noname0_display_info);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1322.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1322_init_seq[] = {
|
||||
|
||||
U8X8_DLY(1),
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_DLY(1),
|
||||
|
||||
U8X8_CA(0xfd, 0x12), /* unlock */
|
||||
U8X8_C(0xae), /* display off */
|
||||
U8X8_CA(0xb3, 0x91), /* set display clock divide ratio/oscillator frequency (set clock as 80 frames/sec) */
|
||||
U8X8_CA(0xca, 0x3f), /* multiplex ratio 1/64 Duty (0x0F~0x3F) */
|
||||
U8X8_CA(0xa2, 0x00), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0xa1, 0x00), /* display start line */
|
||||
//U8X8_CAA(0xa0, 0x14, 0x11), /* Set Re-Map / Dual COM Line Mode */
|
||||
U8X8_CAA(0xa0, 0x06, 0x011), /* Set Re-Map / Dual COM Line Mode */
|
||||
U8X8_CA(0xab, 0x01), /* Enable Internal VDD Regulator */
|
||||
U8X8_CAA(0xb4, 0xa0, 0x005|0x0fd), /* Display Enhancement A */
|
||||
U8X8_CA(0xc1, 0x9f), /* contrast */
|
||||
U8X8_CA(0xc7, 0x0f), /* Set Scale Factor of Segment Output Current Control */
|
||||
U8X8_C(0xb9), /* linear grayscale */
|
||||
U8X8_CA(0xb1, 0xe2), /* Phase 1 (Reset) & Phase 2 (Pre-Charge) Period Adjustment */
|
||||
U8X8_CAA(0xd1, 0x082|0x020, 0x020), /* Display Enhancement B */
|
||||
U8X8_CA(0xbb, 0x1f), /* precharge voltage */
|
||||
U8X8_CA(0xb6, 0x08), /* precharge period */
|
||||
U8X8_CA(0xbe, 0x07), /* vcomh */
|
||||
U8X8_C(0xa6), /* normal display */
|
||||
U8X8_C(0xa9), /* exit partial display */
|
||||
|
||||
|
||||
U8X8_DLY(1), /* delay 2ms */
|
||||
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1322_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* ssd1322: display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1322_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* ssd1322: display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1322_256x64_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CAA(0x0a0, 0x006, 0x011), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1322_256x64_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CAA(0x0a0, 0x014, 0x011), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
/* interpret b as a monochrome bit pattern, write value 15 for high bit and value 0 for a low bit */
|
||||
/* topbit (msb) is sent last */
|
||||
/* example: b = 0x083 will send 0xff, 0x00, 0x00, 0xf0 */
|
||||
|
||||
/* 4 Jan 2017: I think this procedure not required any more. Delete? */
|
||||
uint8_t u8x8_write_byte_to_16gr_device(u8x8_t *u8x8, uint8_t b)
|
||||
{
|
||||
static uint8_t buf[4];
|
||||
static uint8_t map[4] = { 0, 0x00f, 0x0f0, 0x0ff };
|
||||
buf [3] = map[b & 3];
|
||||
b>>=2;
|
||||
buf [2] = map[b & 3];
|
||||
b>>=2;
|
||||
buf [1] = map[b & 3];
|
||||
b>>=2;
|
||||
buf [0] = map[b & 3];
|
||||
return u8x8_cad_SendData(u8x8, 4, buf); /* note: SendData can not handle more than 255 bytes, send one line of data */
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
input:
|
||||
one tile (8 Bytes)
|
||||
output:
|
||||
Tile for SSD1325 (32 Bytes)
|
||||
*/
|
||||
|
||||
static uint8_t u8x8_ssd1322_8to32_dest_buf[32];
|
||||
|
||||
static uint8_t *u8x8_ssd1322_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
|
||||
{
|
||||
uint8_t v;
|
||||
uint8_t a,b;
|
||||
uint8_t i, j;
|
||||
uint8_t *dest;
|
||||
|
||||
for( j = 0; j < 4; j++ )
|
||||
{
|
||||
dest = u8x8_ssd1322_8to32_dest_buf;
|
||||
dest += j;
|
||||
a =*ptr;
|
||||
ptr++;
|
||||
b = *ptr;
|
||||
ptr++;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
v = 0;
|
||||
if ( a&1 ) v |= 0xf0;
|
||||
if ( b&1 ) v |= 0x0f;
|
||||
*dest = v;
|
||||
dest+=4;
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return u8x8_ssd1322_8to32_dest_buf;
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1322_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x;
|
||||
uint8_t y, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* U8X8_MSG_DISPLAY_SETUP_MEMORY is handled by the calling function */
|
||||
/*
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1322_256x64_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x0C1 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1322 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 2; // only every 4th col can be addressed
|
||||
x += u8x8->x_offset;
|
||||
|
||||
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
y *= 8;
|
||||
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address, moved out of the loop (issue 302) */
|
||||
u8x8_cad_SendArg(u8x8, y);
|
||||
u8x8_cad_SendArg(u8x8, y+7);
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
|
||||
u8x8_cad_SendArg(u8x8, x ); /* start */
|
||||
u8x8_cad_SendArg(u8x8, x+1 ); /* end */
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x05c ); /* write to ram */
|
||||
|
||||
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1322_8to32(u8x8, ptr));
|
||||
|
||||
ptr += 8;
|
||||
x += 2;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
//x += 2;
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1322_256x64_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100, /* SSD1322: 2 us */
|
||||
/* post_reset_wait_ms = */ 100, /* far east OLEDs need much longer setup time */
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1322: 15ns, but cycle time is 100ns, so use 100/2 */
|
||||
/* sck_pulse_width_ns = */ 50, /* SSD1322: 20ns, but cycle time is 100ns, so use 100/2, AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 10000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns, increased to 8MHz (issue 215), 10 MHz (issue 301) */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 10,
|
||||
/* write_pulse_width_ns = */ 150, /* SSD1322: cycle time is 300ns, so use 300/2 = 150 */
|
||||
/* tile_width = */ 32, /* 256 pixel, so we require 32 bytes for this */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0x01c, /* this is the byte offset (there are two pixel per byte with 4 bit per pixel) */
|
||||
/* flipmode_x_offset = */ 0x01c,
|
||||
/* pixel_width = */ 256,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1322_nhd_256x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1322_256x64_display_info);
|
||||
break;
|
||||
|
||||
default:
|
||||
return u8x8_d_ssd1322_common(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1325.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
/* http://www.newhavendisplay.com/app_notes/OLED_2_7_12864.txt */
|
||||
static const uint8_t u8x8_d_ssd1325_128x64_nhd_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
|
||||
U8X8_CA(0x0a8, 0x03f), /* multiplex ratio: 0x03f * 1/64 duty */
|
||||
U8X8_CA(0x0a2, 0x04c), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a1, 0x000), /* display start line */
|
||||
U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
|
||||
U8X8_CA(0x0a0, 0x052), /* remap configuration, horizontal address increment (bit 2 = 0), enable nibble remap (upper nibble is left, bit 1 = 1) */
|
||||
U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
|
||||
U8X8_C(0x0b8), /* set gray scale table */
|
||||
U8X8_A(0x001), /* */
|
||||
U8X8_A(0x011), /* */
|
||||
U8X8_A(0x022), /* */
|
||||
U8X8_A(0x032), /* */
|
||||
U8X8_A(0x043), /* */
|
||||
U8X8_A(0x054), /* */
|
||||
U8X8_A(0x065), /* */
|
||||
U8X8_A(0x076), /* */
|
||||
|
||||
U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128, Newhaven: 0x040 */
|
||||
U8X8_CA(0x0b2, 0x051), /* frame frequency (row period) */
|
||||
U8X8_CA(0x0b1, 0x055), /* phase length */
|
||||
U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
|
||||
U8X8_CA(0x0b4, 0x002), /* set pre-charge compensation level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_CA(0x0b0, 0x028), /* enable pre-charge compensation (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
|
||||
U8X8_CA(0x0bf, 0x002|0x00d), /* VSL voltage level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_C(0x0a4), /* normal display mode */
|
||||
|
||||
U8X8_CA(0x023, 0x003), /* graphics accelleration: fill pixel */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1325_128x64_nhd_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1325_128x64_nhd_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1325_128x64_nhd_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a0, 0x052), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1325_128x64_nhd_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a0, 0x041), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
input:
|
||||
one tile (8 Bytes)
|
||||
output:
|
||||
Tile for SSD1325 (32 Bytes)
|
||||
*/
|
||||
|
||||
static uint8_t u8x8_ssd1325_8to32_dest_buf[32];
|
||||
|
||||
static uint8_t *u8x8_ssd1325_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
|
||||
{
|
||||
uint8_t v;
|
||||
uint8_t a,b;
|
||||
uint8_t i, j;
|
||||
uint8_t *dest;
|
||||
|
||||
for( j = 0; j < 4; j++ )
|
||||
{
|
||||
dest = u8x8_ssd1325_8to32_dest_buf;
|
||||
dest += j;
|
||||
a =*ptr;
|
||||
ptr++;
|
||||
b = *ptr;
|
||||
ptr++;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
v = 0;
|
||||
if ( a&1 ) v |= 0xf0;
|
||||
if ( b&1 ) v |= 0x0f;
|
||||
*dest = v;
|
||||
dest+=4;
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return u8x8_ssd1325_8to32_dest_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1325_128x64_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, y, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1325_128x64_nhd_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1325_128x64_nhd_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1325 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 4;
|
||||
|
||||
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
y *= 8;
|
||||
y += u8x8->x_offset; /* x_offset is used as y offset for the SSD1325 */
|
||||
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address */
|
||||
u8x8_cad_SendArg(u8x8, y);
|
||||
u8x8_cad_SendArg(u8x8, y+7);
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
|
||||
do
|
||||
{
|
||||
if ( ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5] | ptr[6] | ptr[7] )
|
||||
{
|
||||
/* draw the tile if pattern is not zero for all bytes */
|
||||
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
|
||||
u8x8_cad_SendArg(u8x8, x ); /* start */
|
||||
u8x8_cad_SendArg(u8x8, x+3 ); /* end */
|
||||
|
||||
|
||||
|
||||
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1325_8to32(u8x8, ptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tile is empty, use the graphics acceleration command */
|
||||
u8x8_cad_SendCmd(u8x8, 0x024 ); // draw rectangle
|
||||
u8x8_cad_SendArg(u8x8, x );
|
||||
u8x8_cad_SendArg(u8x8, y );
|
||||
u8x8_cad_SendArg(u8x8, x+3 );
|
||||
u8x8_cad_SendArg(u8x8, y+7 );
|
||||
u8x8_cad_SendArg(u8x8, 0 ); // clear
|
||||
}
|
||||
ptr += 8;
|
||||
x += 4;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
//x += 4;
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_nhd_ssd1325_128x64_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100, /**/
|
||||
/* sda_setup_time_ns = */ 100, /* SSD1325 */
|
||||
/* sck_pulse_width_ns = */ 100, /* SSD1325 */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 60, /* SSD1325 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0, /* x_offset is used as y offset for the SSD1325 */
|
||||
/* flipmode_x_offset = */ 8, /* x_offset is used as y offset for the SSD1325 */
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1325_nhd_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_nhd_ssd1325_128x64_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1325_128x64_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1326.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
/* ER OLED */
|
||||
static const uint8_t u8x8_d_ssd1326_er_256x32_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_CA(0x0fd, 0x012), /* unlock (not required, this is default by reset) */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0a8, 0x01f), /* multiplex ratio: 0x03f * 1/64 duty - changed by CREESOO, acc. to datasheet, 100317*/
|
||||
U8X8_CA(0x0a1, 0x000), /* display start line */
|
||||
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
|
||||
//U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
|
||||
U8X8_CA(0x0a0, 0x052), /* remap configuration, horizontal address increment (bit 2 = 0), enable nibble remap (upper nibble is left, bit 1 = 1) */
|
||||
U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
|
||||
|
||||
U8X8_C(0x0b7), /* set default gray scale table */
|
||||
|
||||
U8X8_CA(0x081, 0x027), /* contrast, brightness, 0..128 */
|
||||
U8X8_CA(0x0b1, 0x071), /* phase length */
|
||||
//U8X8_CA(0x0b2, 0x051), /* frame frequency (row period) */
|
||||
U8X8_CA(0x0b3, 0x0f0), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
|
||||
//U8X8_CA(0x0b4, 0x002), /* set pre-charge compensation level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
//U8X8_CA(0x0b0, 0x028), /* enable pre-charge compensation (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_CAA(0x0bb, 0x035, 0x0ff), /* set precharge */
|
||||
U8X8_CA(0x0bc, 0x01f), /* pre-charge voltage level */
|
||||
U8X8_CA(0x0be, 0x00f), /* VCOMH voltage */
|
||||
U8X8_CA(0x0bf, 0x002|0x00d), /* VSL voltage level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_C(0x0a4), /* normal display mode */
|
||||
|
||||
//U8X8_CA(0x023, 0x003), /* graphics accelleration: fill pixel */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1326_256x32_nhd_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1326_256x32_nhd_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1326_256x32_nhd_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a0, 0x052), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1326_256x32_nhd_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a0, 0x041), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
input:
|
||||
one tile (8 Bytes)
|
||||
output:
|
||||
Tile for ssd1326 (32 Bytes)
|
||||
*/
|
||||
|
||||
static uint8_t u8x8_ssd1326_8to32_dest_buf[32];
|
||||
|
||||
static uint8_t *u8x8_ssd1326_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
|
||||
{
|
||||
uint8_t v;
|
||||
uint8_t a,b;
|
||||
uint8_t i, j;
|
||||
uint8_t *dest;
|
||||
|
||||
for( j = 0; j < 4; j++ )
|
||||
{
|
||||
dest = u8x8_ssd1326_8to32_dest_buf;
|
||||
dest += j;
|
||||
a =*ptr;
|
||||
ptr++;
|
||||
b = *ptr;
|
||||
ptr++;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
v = 0;
|
||||
if ( a&1 ) v |= 0xf0;
|
||||
if ( b&1 ) v |= 0x0f;
|
||||
*dest = v;
|
||||
dest+=4;
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return u8x8_ssd1326_8to32_dest_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1326_256x32_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, y, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1326_256x32_nhd_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_er_256x32_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1326_256x32_nhd_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1326 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 4;
|
||||
|
||||
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
|
||||
y *= 8;
|
||||
y += u8x8->x_offset; /* x_offset is used as y offset for the ssd1326 */
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
|
||||
do
|
||||
{
|
||||
/* tile is empty, use the graphics acceleration command */
|
||||
/* are this really available on the ssd1326??? */
|
||||
u8x8_cad_SendCmd(u8x8, 0x024 ); // draw rectangle
|
||||
u8x8_cad_SendArg(u8x8, x );
|
||||
u8x8_cad_SendArg(u8x8, y );
|
||||
u8x8_cad_SendArg(u8x8, x+3 );
|
||||
u8x8_cad_SendArg(u8x8, y+7 );
|
||||
u8x8_cad_SendArg(u8x8, 0 ); // clear
|
||||
ptr += 8;
|
||||
x += 4;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
//x += 4;
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1326_256x32_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 15,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100, /**/
|
||||
/* sda_setup_time_ns = */ 100, /* ssd1326 */
|
||||
/* sck_pulse_width_ns = */ 100, /* ssd1326 */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 60, /* ssd1326 */
|
||||
/* tile_width = */ 32,
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
|
||||
/* flipmode_x_offset = */ 0, /* x_offset is used as y offset for the ssd1326 */
|
||||
/* pixel_width = */ 256,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1326_er_256x32(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1326_256x32_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1326_256x32_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,451 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1327.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_96x96_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_96x96_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
input:
|
||||
one tile (8 Bytes)
|
||||
output:
|
||||
Tile for ssd1327 (32 Bytes)
|
||||
*/
|
||||
|
||||
static uint8_t u8x8_ssd1327_8to32_dest_buf[32];
|
||||
|
||||
static uint8_t *u8x8_ssd1327_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
|
||||
{
|
||||
uint8_t v;
|
||||
uint8_t a,b;
|
||||
uint8_t i, j;
|
||||
uint8_t *dest;
|
||||
|
||||
for( j = 0; j < 4; j++ )
|
||||
{
|
||||
dest = u8x8_ssd1327_8to32_dest_buf;
|
||||
dest += j;
|
||||
a =*ptr;
|
||||
ptr++;
|
||||
b = *ptr;
|
||||
ptr++;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
v = 0;
|
||||
if ( a&1 ) v |= 0xf0;
|
||||
if ( b&1 ) v |= 0x0f;
|
||||
*dest = v;
|
||||
dest+=4;
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return u8x8_ssd1327_8to32_dest_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1327_96x96_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, y, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_96x96_display_info);
|
||||
break;
|
||||
*/
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_init_seq);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_powersave1_seq);
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1327 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 4;
|
||||
x+=u8x8->x_offset/2;
|
||||
|
||||
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
y *= 8;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address, moved out of the loop (issue 302) */
|
||||
u8x8_cad_SendArg(u8x8, y);
|
||||
u8x8_cad_SendArg(u8x8, y+7);
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
|
||||
u8x8_cad_SendArg(u8x8, x ); /* start */
|
||||
u8x8_cad_SendArg(u8x8, x+3 ); /* end */
|
||||
|
||||
|
||||
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1327_8to32(u8x8, ptr));
|
||||
ptr += 8;
|
||||
x += 4;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
//x += 4;
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=============================================*/
|
||||
/* Seeedstudio Grove OLED 96x96 */
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1327_96x96_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100, /**/
|
||||
/* sda_setup_time_ns = */ 100, /* */
|
||||
/* sck_pulse_width_ns = */ 100, /* */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 1, /* use 1 instead of 4, because the SSD1327 seems to be very slow */
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 60,
|
||||
/* tile_width = */ 12,
|
||||
/* tile_hight = */ 12,
|
||||
/* default_x_offset = */ 16,
|
||||
/* flipmode_x_offset = */ 16,
|
||||
/* pixel_width = */ 96,
|
||||
/* pixel_height = */ 96
|
||||
};
|
||||
|
||||
/* https://github.com/SeeedDocument/Grove_OLED_1.12/raw/master/resources/LY120-096096.pdf */
|
||||
/* http://www.seeedstudio.com/wiki/index.php?title=Twig_-_OLED_96x96 */
|
||||
/* values from u8glib */
|
||||
/*
|
||||
Re-map setting in Graphic Display Data RAM, command 0x0a0
|
||||
Bit 0: Column Address Re-map
|
||||
Bit 1: Nibble Re-map
|
||||
Bit 2: Horizontal/Vertical Address Increment
|
||||
Bit 3: Not used, must be 0
|
||||
|
||||
Bit 4: COM Re-map
|
||||
Bit 5: Not used, must be 0
|
||||
Bit 6: COM Split Odd Even
|
||||
Bit 7: Not used, must be 0
|
||||
*/
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_96x96_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_CA(0x0fd, 0x012), /* unlock display, usually not required because the display is unlocked after reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio: 0x03f * 1/64 duty */
|
||||
U8X8_CA(0x0a8, 0x05f), /* multiplex ratio: 0x05f * 1/64 duty */
|
||||
U8X8_CA(0x0a1, 0x000), /* display start line */
|
||||
//U8X8_CA(0x0a2, 0x04c), /* display offset, shift mapping ram counter */
|
||||
|
||||
U8X8_CA(0x0a2, 0x020), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a0, 0x051), /* remap configuration */
|
||||
|
||||
|
||||
U8X8_CA(0x0ab, 0x001), /* Enable internal VDD regulator (RESET) */
|
||||
//U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128 */
|
||||
U8X8_CA(0x081, 0x053), /* contrast, brightness, 0..128 */
|
||||
//U8X8_CA(0x0b1, 0x055), /* phase length */
|
||||
U8X8_CA(0x0b1, 0x051), /* phase length */
|
||||
//U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
|
||||
U8X8_CA(0x0b3, 0x001), /* set display clock divide ratio/oscillator frequency */
|
||||
|
||||
//? U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
|
||||
//? U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
|
||||
|
||||
U8X8_C(0x0b9), /* use linear lookup table */
|
||||
|
||||
//U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
|
||||
U8X8_CA(0x0bc, 0x008), /* pre-charge voltage level */
|
||||
//U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
|
||||
U8X8_CA(0x0be, 0x007), /* VCOMH voltage */
|
||||
U8X8_CA(0x0b6, 0x001), /* second precharge */
|
||||
U8X8_CA(0x0d5, 0x062), /* enable second precharge, internal vsl (bit0 = 0) */
|
||||
|
||||
|
||||
|
||||
U8X8_C(0x0a4), /* normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_seeed_96x96_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a2, 0x020), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a0, 0x051), /* remap configuration */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_seeed_96x96_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a2, 0x060), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a0, 0x042), /* remap configuration */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1327_seeed_96x96(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( u8x8_d_ssd1327_96x96_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_96x96_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_96x96_init_seq);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
|
||||
{
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_seeed_96x96_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_seeed_96x96_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*=============================================*/
|
||||
/* MIDAS MCOT128128C1V-YM 128x128 Module */
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1327_128x128_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 10,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100, /**/
|
||||
/* sda_setup_time_ns = */ 100, /* */
|
||||
/* sck_pulse_width_ns = */ 100, /* */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 1, /* use 1 instead of 4, because the SSD1327 seems to be very slow */
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 60,
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 16,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 128
|
||||
};
|
||||
|
||||
/* https://github.com/SeeedDocument/Grove_OLED_1.12/raw/master/resources/LY120-096096.pdf */
|
||||
/* http://www.seeedstudio.com/wiki/index.php?title=Twig_-_OLED_96x96 */
|
||||
/* values from u8glib */
|
||||
/*
|
||||
Re-map setting in Graphic Display Data RAM, command 0x0a0
|
||||
Bit 0: Column Address Re-map
|
||||
Bit 1: Nibble Re-map
|
||||
Bit 2: Horizontal/Vertical Address Increment
|
||||
Bit 3: Not used, must be 0
|
||||
|
||||
Bit 4: COM Re-map
|
||||
Bit 5: Not used, must be 0
|
||||
Bit 6: COM Split Odd Even
|
||||
Bit 7: Not used, must be 0
|
||||
*/
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_128x128_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_CA(0x0fd, 0x012), /* unlock display, usually not required because the display is unlocked after reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
//U8X8_CA(0x0a8, 0x03f), /* multiplex ratio: 0x03f * 1/64 duty */
|
||||
//U8X8_CA(0x0a8, 0x05f), /* multiplex ratio: 0x05f * 1/64 duty */
|
||||
U8X8_CA(0x0a8, 0x07f), /* multiplex ratio: 0x05f * 1/128duty */
|
||||
U8X8_CA(0x0a1, 0x000), /* display start line */
|
||||
//U8X8_CA(0x0a2, 0x04c), /* display offset, shift mapping ram counter */
|
||||
|
||||
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a0, 0x051), /* remap configuration */
|
||||
|
||||
|
||||
U8X8_CA(0x0ab, 0x001), /* Enable internal VDD regulator (RESET) */
|
||||
//U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128 */
|
||||
U8X8_CA(0x081, 0x053), /* contrast, brightness, 0..128 */
|
||||
//U8X8_CA(0x0b1, 0x055), /* phase length */
|
||||
U8X8_CA(0x0b1, 0x051), /* phase length */
|
||||
//U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
|
||||
U8X8_CA(0x0b3, 0x001), /* set display clock divide ratio/oscillator frequency */
|
||||
|
||||
//? U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
|
||||
//? U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
|
||||
|
||||
U8X8_C(0x0b9), /* use linear lookup table */
|
||||
|
||||
//U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
|
||||
U8X8_CA(0x0bc, 0x008), /* pre-charge voltage level */
|
||||
//U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
|
||||
U8X8_CA(0x0be, 0x007), /* VCOMH voltage */
|
||||
U8X8_CA(0x0b6, 0x001), /* second precharge */
|
||||
U8X8_CA(0x0d5, 0x062), /* enable second precharge, internal vsl (bit0 = 0) */
|
||||
|
||||
|
||||
|
||||
U8X8_C(0x0a4), /* normal display mode */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_128x128_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a0, 0x051), /* remap configuration */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1327_128x128_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a0, 0x042), /* remap configuration */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1327_midas_128x128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call the 96x96 procedure at the moment */
|
||||
if ( u8x8_d_ssd1327_96x96_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1327_128x128_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_init_seq);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
|
||||
{
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1327_128x128_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1329.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1329_128x96_noname_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_CA(0x0b3, 0x091), /* set display clock divide ratio/oscillator frequency (set clock as 135 frames/sec) */
|
||||
U8X8_CA(0x0a8, 0x05f), /* multiplex ratio: 0x03f * 1/64 duty - changed by CREESOO, acc. to datasheet, 100317*/
|
||||
U8X8_CA(0x0a2, 0x000), /* display offset, shift mapping ram counter */
|
||||
U8X8_CA(0x0a1, 0x000), /* display start line */
|
||||
U8X8_CA(0x0ad, 0x002), /* master configuration: disable embedded DC-DC, enable internal VCOMH */
|
||||
U8X8_CA(0x0a0, 0x052), /* remap configuration, horizontal address increment (bit 2 = 0), enable nibble remap (upper nibble is left, bit 1 = 1) */
|
||||
U8X8_C(0x086), /* full current range (0x084, 0x085, 0x086) */
|
||||
#ifdef removed
|
||||
U8X8_C(0x0b8), /* set gray scale table */
|
||||
U8X8_A(1), /* */
|
||||
U8X8_A(5), /* */
|
||||
U8X8_A(10), /* */
|
||||
U8X8_A(14), /* */
|
||||
U8X8_A(19), /* */
|
||||
U8X8_A(23), /* */
|
||||
U8X8_A(28), /* */
|
||||
U8X8_A(32), /* */
|
||||
U8X8_A(37), /* */
|
||||
U8X8_A(41), /* */
|
||||
U8X8_A(46), /* */
|
||||
U8X8_A(50), /* */
|
||||
U8X8_A(55), /* */
|
||||
U8X8_A(59), /* */
|
||||
U8X8_A(63), /* */
|
||||
#endif
|
||||
|
||||
U8X8_C(0x0b7), /* set default gray scale table */
|
||||
|
||||
U8X8_CA(0x081, 0x070), /* contrast, brightness, 0..128 */
|
||||
U8X8_CA(0x0b2, 0x051), /* frame frequency (row period) */
|
||||
U8X8_CA(0x0b1, 0x055), /* phase length */
|
||||
U8X8_CA(0x0bc, 0x010), /* pre-charge voltage level */
|
||||
U8X8_CA(0x0b4, 0x002), /* set pre-charge compensation level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_CA(0x0b0, 0x028), /* enable pre-charge compensation (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_CA(0x0be, 0x01c), /* VCOMH voltage */
|
||||
U8X8_CA(0x0bf, 0x002|0x00d), /* VSL voltage level (not documented in the SDD1325 datasheet, but used in the NHD init seq.) */
|
||||
U8X8_C(0x0a4), /* normal display mode */
|
||||
|
||||
U8X8_CA(0x023, 0x003), /* graphics accelleration: fill pixel */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1329_128x96_nhd_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1329_128x96_nhd_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1329_128x96_nhd_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a0, 0x052), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1329_128x96_nhd_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x0a0, 0x041), /* remap */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
input:
|
||||
one tile (8 Bytes)
|
||||
output:
|
||||
Tile for ssd1329 (32 Bytes)
|
||||
*/
|
||||
|
||||
static uint8_t u8x8_ssd1329_8to32_dest_buf[32];
|
||||
|
||||
static uint8_t *u8x8_ssd1329_8to32(U8X8_UNUSED u8x8_t *u8x8, uint8_t *ptr)
|
||||
{
|
||||
uint8_t v;
|
||||
uint8_t a,b;
|
||||
uint8_t i, j;
|
||||
uint8_t *dest;
|
||||
|
||||
for( j = 0; j < 4; j++ )
|
||||
{
|
||||
dest = u8x8_ssd1329_8to32_dest_buf;
|
||||
dest += j;
|
||||
a =*ptr;
|
||||
ptr++;
|
||||
b = *ptr;
|
||||
ptr++;
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
v = 0;
|
||||
if ( a&1 ) v |= 0xf0;
|
||||
if ( b&1 ) v |= 0x0f;
|
||||
*dest = v;
|
||||
dest+=4;
|
||||
a >>= 1;
|
||||
b >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
return u8x8_ssd1329_8to32_dest_buf;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1329_128x96_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, y, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1329_128x96_nhd_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_noname_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1329_128x96_nhd_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int ); /* ssd1329 has range from 0 to 255 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 4;
|
||||
|
||||
y = (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
|
||||
y *= 8;
|
||||
y += u8x8->x_offset; /* x_offset is used as y offset for the ssd1329 */
|
||||
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
|
||||
do
|
||||
{
|
||||
if ( ptr[0] | ptr[1] | ptr[2] | ptr[3] | ptr[4] | ptr[5] | ptr[6] | ptr[7] )
|
||||
{
|
||||
/* draw the tile if pattern is not zero for all bytes */
|
||||
u8x8_cad_SendCmd(u8x8, 0x015 ); /* set column address */
|
||||
u8x8_cad_SendArg(u8x8, x ); /* start */
|
||||
u8x8_cad_SendArg(u8x8, x+3 ); /* end */
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x075 ); /* set row address */
|
||||
u8x8_cad_SendArg(u8x8, y);
|
||||
u8x8_cad_SendArg(u8x8, y+7);
|
||||
|
||||
|
||||
u8x8_cad_SendData(u8x8, 32, u8x8_ssd1329_8to32(u8x8, ptr));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* tile is empty, use the graphics acceleration command */
|
||||
/* are this really available on the SSD1329??? */
|
||||
u8x8_cad_SendCmd(u8x8, 0x024 ); // draw rectangle
|
||||
u8x8_cad_SendArg(u8x8, x );
|
||||
u8x8_cad_SendArg(u8x8, y );
|
||||
u8x8_cad_SendArg(u8x8, x+3 );
|
||||
u8x8_cad_SendArg(u8x8, y+7 );
|
||||
u8x8_cad_SendArg(u8x8, 0 ); // clear
|
||||
}
|
||||
ptr += 8;
|
||||
x += 4;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
//x += 4;
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1329_128x96_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 15,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100, /**/
|
||||
/* sda_setup_time_ns = */ 100, /* ssd1329 */
|
||||
/* sck_pulse_width_ns = */ 100, /* ssd1329 */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 60, /* ssd1329 */
|
||||
/* tile_width = */ 16,
|
||||
/* tile_hight = */ 12,
|
||||
/* default_x_offset = */ 0, /* x_offset is used as y offset for the ssd1329 */
|
||||
/* flipmode_x_offset = */ 0, /* x_offset is used as y offset for the ssd1329 */
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 96
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1329_128x96_noname(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1329_128x96_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1329_128x96_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1606_172x72.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
SSD1606: 128x180x2
|
||||
two-bit, four graylevels
|
||||
command
|
||||
0x22: assign actions
|
||||
0x20: execute actions
|
||||
|
||||
action for command 0x022 are (more or less guessed)
|
||||
bit 7: Enable Clock
|
||||
bit 6: Enable Charge Pump
|
||||
bit 5: Load Temparture Value (???)
|
||||
bit 4: Load LUT (???)
|
||||
bit 3: Initial Display (???)
|
||||
bit 2: Pattern Display --> Requires about 945ms with the LUT from below
|
||||
bit 1: Disable Charge Pump
|
||||
bit 0: Disable Clock
|
||||
|
||||
Disable Charge Pump and Clock require about 267ms
|
||||
Enable Charge Pump and Clock require about 10ms
|
||||
|
||||
Notes:
|
||||
- Introduced a refresh display message, which copies RAM to display
|
||||
- Charge pump and clock are only enabled for the transfer RAM to display
|
||||
- U8x8 will not really work because of the two buffers in the SSD1606, however U8g2 should be ok.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
#define L(a,b,c,d) (((a)<<6)|((b)<<4)|((c)<<2)|(d))
|
||||
|
||||
|
||||
/* GDE021A1, 2.1" EPD */
|
||||
static const uint8_t u8x8_d_ssd1606_172x72_gde021a1_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: Disable */
|
||||
U8X8_CA(0x11, 0x03), /* Define data entry mode, x&y inc, x first */
|
||||
U8X8_CAA(0x44, 0, 31), /* RAM x start & end, each byte has 4 pixel, 32*4=128 */
|
||||
U8X8_CAA(0x45, 0, 179), /* RAM y start & end, 179 MAX */
|
||||
|
||||
U8X8_CA(0x4e, 0), /* set x pos, 0..31 */
|
||||
U8X8_CA(0x4f, 0), /* set y pos, 0...179 */
|
||||
|
||||
U8X8_CA(0xf0, 0x1f), /* set booster feedback to internal */
|
||||
U8X8_CA(0x22, 0xc0), /* display update seq. option: enable clk, enable CP, .... todo: this is never activated */
|
||||
|
||||
U8X8_C(0x32), /* write LUT register*/
|
||||
|
||||
#ifdef ORIGINAL_LUT
|
||||
|
||||
/* wavefrom part of the LUT: absolute LUT... this will always force the destination color */
|
||||
U8X8_A4(0x00,0x00,0x00,0x55), /* step 0 */
|
||||
U8X8_A4(0x00,0x00,0x55,0x55), /* step 1 */
|
||||
U8X8_A4(0x00,0x55,0x55,0x55),
|
||||
U8X8_A4(0xAA,0xAA,0xAA,0xAA),
|
||||
U8X8_A4(0x15,0x15,0x15,0x15),
|
||||
U8X8_A4(0x05,0x05,0x05,0x05),
|
||||
U8X8_A4(0x01,0x01,0x01,0x01),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00), /* step 19 */
|
||||
|
||||
/* timing part of the LUT */
|
||||
U8X8_A8(0x22,0xFB,0x22,0x1B,0x00,0x00,0x00,0x00),
|
||||
U8X8_A(0x00),U8X8_A(0x00),
|
||||
|
||||
#else
|
||||
|
||||
/* the following LUT will not change anything if the old and the new values are the same */
|
||||
/* 03 02 01 00 13 12 11 10 23 22 21 20 33 32 31 30 original */
|
||||
U8X8_A4(L(0, 0, 0, 0), L(0, 0, 0, 0), L(0, 0, 0, 0), L(0, 1, 1, 1)), // 0x00,0x00,0x00,0x55, step 0
|
||||
U8X8_A4(L(0, 0, 0, 0), L(0, 0, 0, 0), L(1, 0, 1, 1), L(0, 1, 1, 1)), // 0x00,0x00,0x55,0x55, step 1
|
||||
U8X8_A4(L(0, 0, 0, 0), L(1, 1, 0, 1), L(1, 0, 1, 1), L(0, 1, 1, 1)), // 0x00,0x55,0x55,0x55, step 2
|
||||
U8X8_A4(L(2, 2, 2, 0), L(2, 2, 0, 2), L(2, 0, 2, 2), L(0, 2, 2, 2)), // 0xAA,0xAA,0xAA,0xAA, step 3
|
||||
U8X8_A4(L(0, 1, 1, 0), L(0, 1, 0, 1), L(0, 0, 1, 1), L(0, 1, 1, 1)), // 0x15,0x15,0x15,0x15, step 4
|
||||
U8X8_A4(L(0, 0, 1, 0), L(0, 0, 0, 1), L(0, 0, 1, 1), L(0, 0, 1, 1)), // 0x05,0x05,0x05,0x05, step 5
|
||||
U8X8_A4(L(0, 0, 0, 0), L(0, 0, 0, 1), L(0, 0, 0, 1), L(0, 0, 0, 1)), // 0x01,0x01,0x01,0x01, step 6
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00),
|
||||
U8X8_A4(0x00,0x00,0x00,0x00), /* step 19 */
|
||||
|
||||
/* timing part of the LUT */
|
||||
U8X8_A8(0x22,0xFB,0x22,0x1B,0x00,0x00,0x00,0x00),
|
||||
U8X8_A(0x00),U8X8_A(0x00),
|
||||
|
||||
#endif
|
||||
|
||||
U8X8_CA(0x2c, 0xa0), /* write vcom value*/
|
||||
U8X8_CA(0x3c, 0x63), /* select boarder waveform */
|
||||
U8X8_CA(0x22, 0xc4), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
|
||||
/* 0x0c4 is mentioned in chapter 9.2 of the GDE021A1 data sheet */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1606_to_display_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
|
||||
//U8X8_CA(0x22, 0xc0), /* display update seq. option: Enable clock and charge pump */
|
||||
//U8X8_C(0x20), /* execute sequence */
|
||||
//U8X8_DLY(10),
|
||||
/* strange, splitting 0x0c0 does not work reliable */
|
||||
|
||||
U8X8_CA(0x22, 0xc4), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(250), /* the sequence above requires about 970ms */
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(230),
|
||||
|
||||
U8X8_CA(0x22, 0x03), /* disable clock and charge pump */
|
||||
U8X8_DLY(200), /* this requres about 270ms */
|
||||
U8X8_DLY(90),
|
||||
|
||||
//U8X8_CA(0x10, 0x01), /* deep sleep mode */
|
||||
//U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(50),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1606_172x72_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1606_172x72_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1606_172x72_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1606_172x72_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static uint8_t *u8x8_convert_tile_for_ssd1606(uint8_t *t)
|
||||
{
|
||||
uint8_t i;
|
||||
uint16_t r;
|
||||
static uint8_t buf[16];
|
||||
uint8_t *pbuf = buf;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
r = u8x8_upscale_byte(~(*t++));
|
||||
*pbuf++ = (r>>8) & 255;
|
||||
*pbuf++ = r & 255;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void u8x8_d_ssd1606_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
|
||||
static void u8x8_d_ssd1606_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c, page;
|
||||
uint8_t *ptr;
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
page = u8x8->display_info->tile_height;
|
||||
page --;
|
||||
page -= (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
page *= 2;
|
||||
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x00f ); /* scan start */
|
||||
u8x8_cad_SendArg(u8x8, 0);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x011 ); /* cursor increment mode */
|
||||
u8x8_cad_SendArg(u8x8, 3);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x045 ); /* window start column */
|
||||
u8x8_cad_SendArg(u8x8, 0);
|
||||
u8x8_cad_SendArg(u8x8, 179); /* end of display */
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x044 ); /* window end page */
|
||||
u8x8_cad_SendArg(u8x8, page);
|
||||
u8x8_cad_SendArg(u8x8, page+1);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x04f ); /* window column */
|
||||
u8x8_cad_SendArg(u8x8, x);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x04e ); /* window row */
|
||||
u8x8_cad_SendArg(u8x8, page);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x024 );
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 16, u8x8_convert_tile_for_ssd1606(ptr));
|
||||
ptr += 8;
|
||||
x += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t u8x8_d_ssd1606_172x72_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1606_172x72_display_info);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_gde021a1_init_seq);
|
||||
|
||||
/* special code for the SSD1606... */
|
||||
/* ensure that the initial buffer is clear and all eInk is set to white */
|
||||
/* this is done here, because the LUT will be of that kind, that it uses the previous color */
|
||||
/* make everything black */
|
||||
u8x8_FillDisplay(u8x8);
|
||||
/* write content to the display */
|
||||
u8x8_RefreshDisplay(u8x8);
|
||||
/* now make everything clear */
|
||||
u8x8_FillDisplay(u8x8);
|
||||
/* write content to the display */
|
||||
u8x8_RefreshDisplay(u8x8);
|
||||
/* now make everything clear */
|
||||
u8x8_ClearDisplay(u8x8);
|
||||
/* write content to the display */
|
||||
u8x8_RefreshDisplay(u8x8);
|
||||
|
||||
u8x8_ClearDisplay(u8x8);
|
||||
/* write content to the display */
|
||||
u8x8_RefreshDisplay(u8x8);
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
/*
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_powersave1_seq);
|
||||
*/
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
/*
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_172x72_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
*/
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
/*
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
*/
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_d_ssd1606_draw_tile(u8x8, arg_int, arg_ptr);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_REFRESH:
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1606_to_display_seq);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1606_172x72_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 120,
|
||||
/* pre_chip_disable_wait_ns = */ 60,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100,
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1606: */
|
||||
/* sck_pulse_width_ns = */ 100, /* SSD1606: 100ns */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150,
|
||||
/* tile_width = */ 22, /* 22*8 = 176 */
|
||||
/* tile_hight = */ 9, /* 9*8 = 72 */
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 172,
|
||||
/* pixel_height = */ 72
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_ssd1606_172x72(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1606_172x72_display_info);
|
||||
return 1;
|
||||
}
|
||||
return u8x8_d_ssd1606_172x72_generic(u8x8, msg, arg_int, arg_ptr);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
|
||||
u8x8_d_ssd1607_200x200.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
SSD1607: 200x300x1
|
||||
|
||||
command
|
||||
0x22: assign actions
|
||||
0x20: execute actions
|
||||
|
||||
action for command 0x022 are (more or less guessed)
|
||||
bit 7: Enable Clock
|
||||
bit 6: Enable Charge Pump
|
||||
bit 5: Load Temparture Value (???)
|
||||
bit 4: Load LUT (???)
|
||||
bit 3: Initial Display (???)
|
||||
bit 2: Pattern Display --> Requires about 945ms with the LUT from below
|
||||
bit 1: Disable Charge Pump
|
||||
bit 0: Disable Clock
|
||||
|
||||
Disable Charge Pump and Clock require about 267ms
|
||||
Enable Charge Pump and Clock require about 10ms
|
||||
|
||||
Notes:
|
||||
- Introduced a refresh display message, which copies RAM to display
|
||||
- Charge pump and clock are only enabled for the transfer RAM to display
|
||||
- U8x8 will not really work because of the two buffers in the SSD1606, however U8g2 should be ok.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
/*=================================================*/
|
||||
|
||||
static const u8x8_display_info_t u8x8_ssd1607_200x200_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* values from SSD1606 */
|
||||
/* post_chip_enable_wait_ns = */ 120,
|
||||
/* pre_chip_disable_wait_ns = */ 60,
|
||||
/* reset_pulse_width_ms = */ 100,
|
||||
/* post_reset_wait_ms = */ 100,
|
||||
/* sda_setup_time_ns = */ 50, /* SSD1606: */
|
||||
/* sck_pulse_width_ns = */ 100, /* SSD1606: 100ns */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 2, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40,
|
||||
/* write_pulse_width_ns = */ 150,
|
||||
/* tile_width = */ 25, /* 25*8 = 200 */
|
||||
/* tile_hight = */ 25,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 200,
|
||||
/* pixel_height = */ 200
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1607_200x200_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_CA(0x22, 0xc0), /* enable clock and charge pump */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(200), /* according to my measures it may take up to 150ms */
|
||||
U8X8_DLY(100), /* but it might take longer */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1607_200x200_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
/* disable clock and charge pump only, deep sleep is not entered, because we will loose RAM content */
|
||||
U8X8_CA(0x22, 0x02), /* only disable charge pump, HW reset seems to be required if the clock is disabled */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(20),
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1607_200x200_exec_1000dly_seq[] = {
|
||||
// assumes, that the start transfer has happend
|
||||
U8X8_CA(0x22, 0x04), /* display update seq. option: pattern display */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
static void u8x8_d_ssd1607_200x200_first_init(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8_ClearDisplay(u8x8);
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x032); // program update sequence
|
||||
u8x8_cad_SendMultipleArg(u8x8, 8, 0x055); // all black
|
||||
u8x8_cad_SendMultipleArg(u8x8, 12, 0x0aa); // all white
|
||||
u8x8_cad_SendMultipleArg(u8x8, 10, 0x022); // 830ms
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_exec_1000dly_seq);
|
||||
|
||||
}
|
||||
|
||||
static uint8_t *u8x8_convert_tile_for_ssd1607(uint8_t *t)
|
||||
{
|
||||
uint8_t i;
|
||||
static uint8_t buf[8];
|
||||
uint8_t *pbuf = buf;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
*pbuf++ = ~(*t++);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
static void u8x8_d_ssd1607_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr) U8X8_NOINLINE;
|
||||
static void u8x8_d_ssd1607_draw_tile(u8x8_t *u8x8, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint16_t x;
|
||||
uint8_t c, page;
|
||||
uint8_t *ptr;
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
page = u8x8->display_info->tile_height;
|
||||
page --;
|
||||
page -= (((u8x8_tile_t *)arg_ptr)->y_pos);
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x045 ); /* window start column */
|
||||
u8x8_cad_SendArg(u8x8, 0);
|
||||
u8x8_cad_SendArg(u8x8, 0);
|
||||
u8x8_cad_SendArg(u8x8, 199); /* end of display */
|
||||
u8x8_cad_SendArg(u8x8, 0);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x044 ); /* window end page */
|
||||
u8x8_cad_SendArg(u8x8, page);
|
||||
u8x8_cad_SendArg(u8x8, page);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x04f ); /* window column */
|
||||
u8x8_cad_SendArg(u8x8, x&255);
|
||||
u8x8_cad_SendArg(u8x8, x>>8);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x04e ); /* window row */
|
||||
u8x8_cad_SendArg(u8x8, page);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x024 );
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 8, u8x8_convert_tile_for_ssd1607(ptr));
|
||||
ptr += 8;
|
||||
x += 8;
|
||||
c--;
|
||||
} while( c > 0 );
|
||||
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*=================================================*/
|
||||
|
||||
|
||||
#define L(a,b,c,d) (((a)<<6)|((b)<<4)|((c)<<2)|(d))
|
||||
|
||||
|
||||
/* https://github.com/embeddedadventures/SSD1607/blob/master/SSD1607.cpp */
|
||||
static const uint8_t u8x8_d_ssd1607_200x200_init_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
//U8X8_CA(0x10, 0x00), /* Deep Sleep mode Control: Disable */
|
||||
U8X8_C(0x01),
|
||||
U8X8_A(199),U8X8_A(0),U8X8_A(0),
|
||||
|
||||
|
||||
U8X8_CA(0x03, 0x00), /* Gate Driving voltage: 15V (lowest value)*/
|
||||
U8X8_CA(0x04, 0x0a), /* Source Driving voltage: 15V (mid value and POR)*/
|
||||
|
||||
U8X8_CA(0x0f, 0x00), /* scan start ? */
|
||||
|
||||
U8X8_CA(0xf0, 0x1f), /* set booster feedback to internal */
|
||||
|
||||
U8X8_CA(0x2c, 0xa8), /* write vcom value*/
|
||||
U8X8_CA(0x3a, 0x1a), /* dummy lines */
|
||||
U8X8_CA(0x3b, 0x08), /* gate time */
|
||||
U8X8_CA(0x3c, 0x33), /* select boarder waveform */
|
||||
|
||||
U8X8_CA(0x11, 0x03), /* cursor increment mode */
|
||||
U8X8_CAA(0x44, 0, 24), /* RAM x start & end, each byte has 8 pixel, 25*4=200 */
|
||||
U8X8_CAAAA(0x45, 0, 0, 299&255, 299>>8), /* RAM y start & end, 0..299 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_ssd1607_to_display_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x32), /* write LUT register*/
|
||||
|
||||
|
||||
/* according to the command table, the lut has 240 bits (=30 bytes * 8 bits) */
|
||||
|
||||
/* Waveform part of the LUT (20 bytes) */
|
||||
/* bit 7/6: 1 - 1 transition */
|
||||
/* bit 5/4: 1 - 0 transition */
|
||||
/* bit 3/2: 0 - 1 transition */
|
||||
/* bit 1/0: 0 - 0 transition */
|
||||
/* 00 – VSS */
|
||||
/* 01 – VSH */
|
||||
/* 10 – VSL */
|
||||
/* 11 – NA */
|
||||
|
||||
/* original values */
|
||||
/*
|
||||
U8X8_A(0x02),
|
||||
U8X8_A(0x02),
|
||||
U8X8_A(0x01),
|
||||
U8X8_A(0x11),
|
||||
U8X8_A(0x12),
|
||||
U8X8_A(0x12),
|
||||
U8X8_A(0x22),
|
||||
U8X8_A(0x22),
|
||||
U8X8_A(0x66),
|
||||
U8X8_A(0x69),
|
||||
U8X8_A(0x69),
|
||||
U8X8_A(0x59),
|
||||
U8X8_A(0x58),
|
||||
U8X8_A(0x99),
|
||||
U8X8_A(0x99),
|
||||
U8X8_A(0x88),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
*/
|
||||
|
||||
/* original values, L-macro */
|
||||
U8X8_A(L(0,0,0,2)), // 0x02
|
||||
U8X8_A(L(0,0,0,2)), // 0x02
|
||||
U8X8_A(L(0,0,0,1)), // 0x01
|
||||
U8X8_A(L(0,1,0,1)), // 0x11
|
||||
U8X8_A(L(0,1,0,2)), // 0x12
|
||||
U8X8_A(L(0,1,0,2)), // 0x12
|
||||
U8X8_A(L(0,2,0,2)), // 0x22
|
||||
U8X8_A(L(0,2,0,2)), // 0x22
|
||||
U8X8_A(L(1,2,1,2)), // 0x66
|
||||
U8X8_A(L(1,2,2,1)), // 0x69
|
||||
U8X8_A(L(1,2,2,1)), // 0x69
|
||||
U8X8_A(L(1,1,2,1)), // 0x59
|
||||
U8X8_A(L(1,1,2,0)), // 0x58
|
||||
U8X8_A(L(2,1,2,1)), // 0x99
|
||||
U8X8_A(L(2,1,2,1)), // 0x99
|
||||
U8X8_A(L(2,0,2,0)), // 0x88
|
||||
U8X8_A(L(0,0,0,0)), // 0x00
|
||||
U8X8_A(L(0,0,0,0)), // 0x00
|
||||
U8X8_A(L(0,0,0,0)), // 0x00
|
||||
U8X8_A(L(0,0,0,0)), // 0x00
|
||||
|
||||
|
||||
/* orginal values without 0-0 and 1-1 transition */
|
||||
/*
|
||||
U8X8_A(L(3,0,0,3)), // 0x02
|
||||
U8X8_A(L(3,0,0,3)), // 0x02
|
||||
U8X8_A(L(3,0,0,3)), // 0x01
|
||||
U8X8_A(L(3,1,0,3)), // 0x11
|
||||
U8X8_A(L(3,1,0,3)), // 0x12
|
||||
U8X8_A(L(3,1,0,3)), // 0x12
|
||||
U8X8_A(L(3,2,0,3)), // 0x22
|
||||
U8X8_A(L(3,2,0,3)), // 0x22
|
||||
U8X8_A(L(3,2,1,3)), // 0x66
|
||||
U8X8_A(L(3,2,2,3)), // 0x69
|
||||
U8X8_A(L(3,2,2,3)), // 0x69
|
||||
U8X8_A(L(3,1,2,3)), // 0x59
|
||||
U8X8_A(L(3,1,2,3)), // 0x58
|
||||
U8X8_A(L(3,1,2,3)), // 0x99
|
||||
U8X8_A(L(3,1,2,3)), // 0x99
|
||||
U8X8_A(L(3,0,2,3)), // 0x88
|
||||
U8X8_A(L(3,0,0,3)), // 0x00
|
||||
U8X8_A(L(3,0,0,3)), // 0x00
|
||||
U8X8_A(L(3,0,0,3)), // 0x00
|
||||
U8X8_A(L(3,0,0,3)), // 0x00
|
||||
*/
|
||||
|
||||
|
||||
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
|
||||
U8X8_A(0xF8),
|
||||
U8X8_A(0xB4),
|
||||
U8X8_A(0x13),
|
||||
U8X8_A(0x51),
|
||||
U8X8_A(0x35),
|
||||
U8X8_A(0x51),
|
||||
U8X8_A(0x51),
|
||||
U8X8_A(0x19),
|
||||
U8X8_A(0x01),
|
||||
U8X8_A(0x00),
|
||||
|
||||
|
||||
U8X8_CA(0x22, 0x04), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
U8X8_DLY(250), /* the sequence above requires about 1200ms for the 200x200 display*/
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1607_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1607_200x200_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_init_seq);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
|
||||
u8x8_d_ssd1607_200x200_first_init(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_d_ssd1607_draw_tile(u8x8, arg_int, arg_ptr);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_REFRESH:
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_to_display_seq);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*=================================================*/
|
||||
/* there is no improvement possible... so i consider the v2 version as obsolete */
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_ssd1607_v2_to_display_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
/*
|
||||
0xaa, 0x09, 0x09, 0x19, 0x19,
|
||||
0x11, 0x11, 0x11, 0x11, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0x75, 0x77, 0x77, 0x77, 0x07,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00
|
||||
measured 1240 ms with IL3830 196x128
|
||||
|
||||
|
||||
0x02, 0x02, 0x01, 0x11, 0x12,
|
||||
0x12, 0x12, 0x22, 0x22, 0x66,
|
||||
0x69, 0x59, 0x58, 0x99, 0x99,
|
||||
0x88, 0x00, 0x00, 0x00, 0x00,
|
||||
|
||||
0xf8, 0xb4, 0x13, 0x51, 0x35,
|
||||
0x51, 0x51, 0xe9, 0x04, 0x00
|
||||
|
||||
*/
|
||||
|
||||
U8X8_C(0x32), /* write LUT register*/
|
||||
|
||||
/* https://github.com/olikraus/u8g2/issues/347 */
|
||||
U8X8_A(0x02),
|
||||
U8X8_A(0x02),
|
||||
U8X8_A(0x01),
|
||||
U8X8_A(0x11),
|
||||
U8X8_A(0x12),
|
||||
U8X8_A(0x12),
|
||||
U8X8_A(0x22),
|
||||
U8X8_A(0x22),
|
||||
U8X8_A(0x66),
|
||||
U8X8_A(0x69),
|
||||
U8X8_A(0x69),
|
||||
U8X8_A(0x59),
|
||||
U8X8_A(0x58),
|
||||
U8X8_A(0x99),
|
||||
U8X8_A(0x99),
|
||||
|
||||
U8X8_A(0x88),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
U8X8_A(0x00),
|
||||
|
||||
/* Timing part of the LUT, 20 Phases with 4 bit each: 10 bytes */
|
||||
U8X8_A(0xF8),
|
||||
U8X8_A(0xB4),
|
||||
U8X8_A(0x13),
|
||||
U8X8_A(0x51),
|
||||
U8X8_A(0x35),
|
||||
|
||||
U8X8_A(0x51),
|
||||
U8X8_A(0x51),
|
||||
U8X8_A(0xe9),
|
||||
U8X8_A(0x04),
|
||||
U8X8_A(0x00),
|
||||
|
||||
U8X8_CA(0x22, 0x04), /* display update seq. option: clk -> CP -> LUT -> initial display -> pattern display */
|
||||
U8X8_C(0x20), /* execute sequence */
|
||||
|
||||
U8X8_DLY(250), /* delay for 1500ms. The current sequence takes 1300ms */
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
|
||||
U8X8_DLY(250),
|
||||
U8X8_DLY(250),
|
||||
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_ssd1607_v2_200x200(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_ssd1607_200x200_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_init_seq);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
|
||||
u8x8_d_ssd1607_200x200_first_init(u8x8);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_200x200_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_d_ssd1607_draw_tile(u8x8, arg_int, arg_ptr);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_REFRESH:
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_ssd1607_v2_to_display_seq);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,668 @@
|
||||
/*
|
||||
|
||||
u8x8_d_st75256.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2017, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
0x030 ext 00
|
||||
0x031 ext 01
|
||||
0x038 ext 10
|
||||
0x039 ext 11
|
||||
|
||||
cad 011
|
||||
|
||||
|
||||
code examples:
|
||||
http://www.it610.com/article/2601023.htm
|
||||
|
||||
normal mode:
|
||||
0x00c bit format
|
||||
U8X8_CA( 0xbc, 0x00 ), data scan dir
|
||||
U8X8_A( 0xa6 ),
|
||||
y: 0 offset
|
||||
|
||||
flip mode:
|
||||
0x008 bit format
|
||||
U8X8_CA( 0xbc, 0x03 ), data scan dir
|
||||
U8X8_A( 0xa6 ),
|
||||
y: 5 offset
|
||||
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
/* not a real power down for the st75256... just a display off */
|
||||
static const uint8_t u8x8_d_st75256_256x128_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x94 ), /* sleep out */
|
||||
U8X8_DLY(10),
|
||||
U8X8_C( 0xaf ), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st75256_256x128_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0xae ), /* display off */
|
||||
U8X8_C( 0x95 ), /* sleep in */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st75256_jlx256128_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0xbc, 0x00 ), /* data scan dir */
|
||||
U8X8_A( 0xa6 ), /* ??? */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x00c ), /* data format LSB top */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st75256_jlx256128_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0xbc, 0x03 ), /* data scan dir */
|
||||
U8X8_A( 0xa6 ), /* ??? */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x008 ), /* data format MSB top */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
|
||||
static uint8_t u8x8_d_st75256_256x128_generic(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st75256_256x128_display_info);
|
||||
break;
|
||||
*/
|
||||
/* handled by the calling function
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_init_seq);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave1_seq);
|
||||
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x030 );
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 ); /* there are 9 bit for the volume control */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int & 0x1f)<<1 ); /* lower 6 bit */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int>>5)); /* upper 3 bit */
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x030 ); /* select command set */
|
||||
u8x8_cad_SendCmd(u8x8, 0x075 ); /* row */
|
||||
u8x8_cad_SendArg(u8x8, u8x8->x_offset + (((u8x8_tile_t *)arg_ptr)->y_pos)); /* x offset is used as y offset */
|
||||
u8x8_cad_SendArg(u8x8, 0x04f);
|
||||
//u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
u8x8_cad_SendCmd(u8x8, 0x015 ); /* col */
|
||||
u8x8_cad_SendArg(u8x8, x);
|
||||
u8x8_cad_SendArg(u8x8, 255);
|
||||
u8x8_cad_SendCmd(u8x8, 0x05c );
|
||||
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
/* SendData can not handle more than 255 bytes, treat c > 31 correctly */
|
||||
if ( c > 31 )
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, 248, ptr); /* 31*8=248 */
|
||||
ptr+=248;
|
||||
c -= 31;
|
||||
}
|
||||
|
||||
u8x8_cad_SendData(u8x8, c*8, ptr);
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*=============================================*/
|
||||
/* JLX256128 */
|
||||
|
||||
static const u8x8_display_info_t u8x8_st75256_256x128_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 5,
|
||||
/* post_reset_wait_ms = */ 5, /**/
|
||||
/* sda_setup_time_ns = */ 20, /* */
|
||||
/* sck_pulse_width_ns = */ 40, /* */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
|
||||
/* data_setup_time_ns = */ 15,
|
||||
/* write_pulse_width_ns = */ 70,
|
||||
/* tile_width = */ 32,
|
||||
/* tile_hight = */ 16,
|
||||
/* default_x_offset = */ 0, /* must be 0, because this is checked also for normal mode */
|
||||
/* flipmode_x_offset = */ 5, /* used as y offset */
|
||||
/* pixel_width = */ 256,
|
||||
/* pixel_height = */ 128
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_st75256_256x128_init_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_DLY(20),
|
||||
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x094 ), /* sleep out */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x0ae ), /* display off */
|
||||
|
||||
U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_CA( 0x0d7, 0x09f ), /* disable auto read */
|
||||
|
||||
//U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_C( 0x032 ), /* analog circuit set */
|
||||
U8X8_A( 0x000 ), /* code example: OSC Frequency adjustment */
|
||||
U8X8_A( 0x001 ), /* Frequency on booster capacitors 1 = 6KHz? */
|
||||
U8X8_A( 0x000 ), /* Bias: 1: 1/13, 2: 1/12, 3: 1/11, 4:1/10, 5:1/9 */
|
||||
|
||||
//U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_C( 0x020 ), /* gray levels */
|
||||
U8X8_A( 0x01 ),
|
||||
U8X8_A( 0x03 ),
|
||||
U8X8_A( 0x05 ),
|
||||
U8X8_A( 0x07 ),
|
||||
U8X8_A( 0x09),
|
||||
U8X8_A( 0x0b ),
|
||||
U8X8_A( 0x0d ),
|
||||
U8X8_A( 0x10 ),
|
||||
U8X8_A( 0x11 ),
|
||||
U8X8_A( 0x13 ),
|
||||
U8X8_A( 0x15 ),
|
||||
U8X8_A( 0x17 ),
|
||||
U8X8_A( 0x19 ),
|
||||
U8X8_A( 0x1b ),
|
||||
U8X8_A( 0x1d ),
|
||||
U8X8_A( 0x1f ),
|
||||
|
||||
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CAA(0x75, 0, 0x4f), /* row range */
|
||||
U8X8_CAA(0x15, 0, 255), /* col range */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0xbc, 0x00 ), /* data scan dir */
|
||||
U8X8_A( 0xa6 ), /* ??? */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x00c ), /* data format LSB top */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0xca ), /* display control, 3 args follow */
|
||||
U8X8_A( 0x00 ), /* 0x00: no clock division, 0x04: devide clock */
|
||||
U8X8_A( 0x7f ), /* 1/160 duty value from the DS example code */
|
||||
U8X8_A( 0x20 ), /* nline off */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0x0f0, 0x010 ), /* monochrome mode = 0x010*/
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CAA( 0x81, 0x36, 0x05 ), /* Volume control */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0x020, 0x00b ), /* Power control: Regulator, follower & booster on */
|
||||
U8X8_DLY(100),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_st75256_jlx256128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( u8x8_d_st75256_256x128_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
//u8x8_SetI2CAddress(u8x8, 0x078); /* lowest I2C adr of the ST75256 */
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st75256_256x128_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_init_seq);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
|
||||
{
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx256128_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx256128_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*=============================================*/
|
||||
/* JLX25664 */
|
||||
|
||||
static const u8x8_display_info_t u8x8_st75256_256x64_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 5,
|
||||
/* post_reset_wait_ms = */ 5, /**/
|
||||
/* sda_setup_time_ns = */ 20, /* */
|
||||
/* sck_pulse_width_ns = */ 40, /* */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
|
||||
/* data_setup_time_ns = */ 15,
|
||||
/* write_pulse_width_ns = */ 70,
|
||||
/* tile_width = */ 32,
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0, /* must be 0, because this is checked also for normal mode */
|
||||
/* flipmode_x_offset = */ 13, /* used as y offset */
|
||||
/* pixel_width = */ 256,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_st75256_256x64_init_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_DLY(20),
|
||||
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x094 ), /* sleep out */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x0ae ), /* display off */
|
||||
|
||||
U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_CA( 0x0d7, 0x09f ), /* disable auto read */
|
||||
|
||||
//U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_C( 0x032 ), /* analog circuit set */
|
||||
U8X8_A( 0x000 ), /* code example: OSC Frequency adjustment */
|
||||
U8X8_A( 0x001 ), /* Frequency on booster capacitors 1 = 6KHz? */
|
||||
U8X8_A( 0x005 ), /* Bias: 1: 1/13, 2: 1/12, 3: 1/11, 4:1/10, 5:1/9 */
|
||||
|
||||
//U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_C( 0x020 ), /* gray levels */
|
||||
U8X8_A( 0x01 ),
|
||||
U8X8_A( 0x03 ),
|
||||
U8X8_A( 0x05 ),
|
||||
U8X8_A( 0x07 ),
|
||||
U8X8_A( 0x09),
|
||||
U8X8_A( 0x0b ),
|
||||
U8X8_A( 0x0d ),
|
||||
U8X8_A( 0x10 ),
|
||||
U8X8_A( 0x11 ),
|
||||
U8X8_A( 0x13 ),
|
||||
U8X8_A( 0x15 ),
|
||||
U8X8_A( 0x17 ),
|
||||
U8X8_A( 0x19 ),
|
||||
U8X8_A( 0x1b ),
|
||||
U8X8_A( 0x1d ),
|
||||
U8X8_A( 0x1f ),
|
||||
|
||||
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CAA(0x75, 0, 0x1f), /* row range */
|
||||
U8X8_CAA(0x15, 0, 255), /* col range */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0xbc, 0x00 ), /* data scan dir */
|
||||
U8X8_A( 0xa6 ), /* ??? */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x00c ), /* data format LSB top */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0xca ), /* display control, 3 args follow */
|
||||
U8X8_A( 0x00 ), /* 0x00: no clock division, 0x04: devide clock */
|
||||
U8X8_A( 0x3f ), /* 64 duty value from the DS example code */
|
||||
U8X8_A( 0x20 ), /* nline off */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0x0f0, 0x010 ), /* monochrome mode = 0x010*/
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CAA( 0x81, 012, 0x02 ), /* Volume control */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0x020, 0x00b ), /* Power control: Regulator, follower & booster on */
|
||||
U8X8_DLY(100),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_st75256_jlx25664(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
if ( u8x8_d_st75256_256x128_generic(u8x8, msg, arg_int, arg_ptr) != 0 )
|
||||
return 1;
|
||||
if ( msg == U8X8_MSG_DISPLAY_SETUP_MEMORY )
|
||||
{
|
||||
//u8x8_SetI2CAddress(u8x8, 0x078); /* lowest I2C adr of the ST75256 */
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st75256_256x64_display_info);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_INIT )
|
||||
{
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x64_init_seq);
|
||||
return 1;
|
||||
}
|
||||
else if ( msg == U8X8_MSG_DISPLAY_SET_FLIP_MODE )
|
||||
{
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx256128_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx256128_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*=============================================*/
|
||||
/* JLX172104 LCD */
|
||||
|
||||
static const u8x8_display_info_t u8x8_st75256_172x104_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 20,
|
||||
/* pre_chip_disable_wait_ns = */ 20,
|
||||
/* reset_pulse_width_ms = */ 5,
|
||||
/* post_reset_wait_ms = */ 5, /**/
|
||||
/* sda_setup_time_ns = */ 20, /* */
|
||||
/* sck_pulse_width_ns = */ 40, /* */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4, /* 400KHz */
|
||||
/* data_setup_time_ns = */ 15,
|
||||
/* write_pulse_width_ns = */ 70,
|
||||
/* tile_width = */ 22, /* 22=176 */
|
||||
/* tile_hight = */ 13,
|
||||
/* default_x_offset = */ 84, /* */
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 172,
|
||||
/* pixel_height = */ 104
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st75256_jlx172104_init_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_DLY(20),
|
||||
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x094 ), /* sleep out */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x0ae ), /* display off */
|
||||
|
||||
U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_CA( 0x0d7, 0x09f ), /* disable auto read */
|
||||
|
||||
//U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_C( 0x032 ), /* analog circuit set */
|
||||
U8X8_A( 0x000 ), /* code example: OSC Frequency adjustment */
|
||||
U8X8_A( 0x001 ), /* Frequency on booster capacitors 1 = 6KHz? */
|
||||
U8X8_A( 0x003 ), /* Bias: 1: 1/13, 2: 1/12, 3: 1/11, 4:1/10, 5:1/9 */
|
||||
|
||||
//U8X8_C( 0x031 ), /* select 01 commands */
|
||||
U8X8_C( 0x020 ), /* gray levels */
|
||||
U8X8_A( 0x01 ),
|
||||
U8X8_A( 0x03 ),
|
||||
U8X8_A( 0x05 ),
|
||||
U8X8_A( 0x07 ),
|
||||
U8X8_A( 0x09),
|
||||
U8X8_A( 0x0b ),
|
||||
U8X8_A( 0x0d ),
|
||||
U8X8_A( 0x10 ),
|
||||
U8X8_A( 0x11 ),
|
||||
U8X8_A( 0x13 ),
|
||||
U8X8_A( 0x15 ),
|
||||
U8X8_A( 0x17 ),
|
||||
U8X8_A( 0x19 ),
|
||||
U8X8_A( 0x1b ),
|
||||
U8X8_A( 0x1d ),
|
||||
U8X8_A( 0x1f ),
|
||||
|
||||
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CAA(0x75, 0, 0x4f), /* row range */
|
||||
U8X8_CAA(0x15, 0, 255), /* col range */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0xbc, 0x02 ), /* data scan dir */
|
||||
U8X8_A( 0xa6 ), /* ??? */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x00c ), /* data format LSB top */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0xca ), /* display control, 3 args follow */
|
||||
U8X8_A( 0x00 ), /* 0x00: no clock division, 0x04: devide clock */
|
||||
U8X8_A( 0x9f ), /* 1/160 duty value from the DS example code */
|
||||
U8X8_A( 0x20 ), /* nline off */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0x0f0, 0x010 ), /* monochrome mode = 0x010*/
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CAA( 0x81, 0x08, 0x04 ), /* Volume control */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0x020, 0x00b ), /* Power control: Regulator, follower & booster on */
|
||||
U8X8_DLY(100),
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st75256_jlx172104_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0xbc, 0x02 ), /* data scan dir */
|
||||
U8X8_A( 0xa6 ), /* ??? */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x00c ), /* data format LSB top */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st75256_jlx172104_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_CA( 0xbc, 0x01 ), /* data scan dir */
|
||||
U8X8_A( 0xa6 ), /* ??? */
|
||||
|
||||
//U8X8_C( 0x030 ), /* select 00 commands */
|
||||
U8X8_C( 0x008 ), /* data format MSB top */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
uint8_t u8x8_d_st75256_jlx172104(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x030 ); /* select command set */
|
||||
u8x8_cad_SendCmd(u8x8, 0x075 ); /* row */
|
||||
if ( u8x8->x_offset == 0 ) /* 0 means flip mode 1, then adjust y value */
|
||||
u8x8_cad_SendArg(u8x8, 8+(((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
else
|
||||
u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
u8x8_cad_SendArg(u8x8, 0x04f);
|
||||
//u8x8_cad_SendArg(u8x8, (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
u8x8_cad_SendCmd(u8x8, 0x015 ); /* col */
|
||||
u8x8_cad_SendArg(u8x8, x+u8x8->x_offset);
|
||||
u8x8_cad_SendArg(u8x8, 255);
|
||||
u8x8_cad_SendCmd(u8x8, 0x05c );
|
||||
|
||||
|
||||
/* this procedure assumes, that the overall width is 172 */
|
||||
do
|
||||
{
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
c *= 8;
|
||||
|
||||
if ( c + x > 172u )
|
||||
{
|
||||
c = 172u;
|
||||
c -= x;
|
||||
}
|
||||
|
||||
u8x8_cad_SendData(u8x8, c, ptr);
|
||||
x += c;
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
return 1;
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
//u8x8_SetI2CAddress(u8x8, 0x078); /* lowest I2C adr of the ST75256 */
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st75256_172x104_display_info);
|
||||
return 1;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx172104_init_seq);
|
||||
return 1;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_256x128_powersave1_seq);
|
||||
|
||||
return 1;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx172104_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st75256_jlx172104_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
return 1;
|
||||
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
u8x8_cad_SendCmd(u8x8, 0x030 );
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 ); /* there are 9 bit for the volume control */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int & 0x1f)<<1 ); /* lower 6 bit */
|
||||
u8x8_cad_SendArg(u8x8, (arg_int>>5)); /* upper 3 bit */
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
return 1;
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,960 @@
|
||||
/*
|
||||
|
||||
u8x8_d_st7565.c
|
||||
also includes support for nt7534
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_st7565_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a4), /* all pixel off, issue 142 */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7565_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7565_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7565_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7565_zflip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7565_zflip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7565_128x64_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* st7565 datasheet, table 26, tcsh */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* st7565 datasheet, table 26, tcss */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* st7565 datasheet, table 26, tsds */
|
||||
/* sck_pulse_width_ns = */ 120, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* st7565 datasheet, table 24, tds8 */
|
||||
/* write_pulse_width_ns = */ 80, /* st7565 datasheet, table 24, tcclw */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 4,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_common(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
c *= 8;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
/*
|
||||
The following if condition checks the hardware limits of the st7565
|
||||
controller: It is not allowed to write beyond the display limits.
|
||||
This is in fact an issue within flip mode.
|
||||
*/
|
||||
if ( c + x > 132u )
|
||||
{
|
||||
c = 132u;
|
||||
c -= x;
|
||||
}
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
/* handled in the calling procedure
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_128x64_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_uc1701_dogs102_init_seq);
|
||||
break;
|
||||
*/
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_powersave1_seq);
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7565 has range from 0 to 63 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
/* DOGM128 */
|
||||
|
||||
static const uint8_t u8x8_d_st7565_dogm128_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
// U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a2), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on (regulator, booster and follower) */
|
||||
U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x */
|
||||
U8X8_C(0x027), /* set V0 voltage resistor ratio to max */
|
||||
U8X8_CA(0x081, 0x018), /* set contrast, contrast value, EA default: 0x016 */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_ea_dogm128(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_128x64_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_dogm128_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
/* Displaytech 64128n */
|
||||
|
||||
static const uint8_t u8x8_d_st7565_64128n_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
#ifdef NOT_WORKING
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
// U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a2), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on */
|
||||
//U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x */
|
||||
//U8X8_C(0x027), /* set V0 voltage resistor ratio to max */
|
||||
|
||||
U8X8_C(0x010), /* Set V0 voltage resistor ratio. Setting for controlling brightness of Displaytech 64128N */
|
||||
|
||||
|
||||
U8X8_CA(0x081, 0x01e), /* set contrast, contrast value */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
#else
|
||||
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0A2), /* 0x0a2: LCD bias 1/9 (according to Displaytech 64128N datasheet) */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
//U8X8_C(0x0A0), /* Normal ADC Select (according to Displaytech 64128N datasheet) */
|
||||
//U8X8_C(0x0c8), /* common output mode: set scan direction normal operation/SHL Select, 0x0c0 --> SHL = 0, normal, 0x0c8 --> SHL = 1 */
|
||||
|
||||
U8X8_C(0x040), /* Display start line for Displaytech 64128N */
|
||||
U8X8_C(0x028 | 0x04), /* power control: turn on voltage converter */
|
||||
U8X8_C(0x028 | 0x06), /* power control: turn on voltage regulator */
|
||||
U8X8_C(0x028 | 0x07), /* power control: turn on voltage follower */
|
||||
U8X8_C(0x010), /* Set V0 voltage resistor ratio. Setting for controlling brightness of Displaytech 64128N */
|
||||
/* 19 Jul 17: Not sure if this is true, cmd 0x1? is used to set the column */
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x081), /* set contrast */
|
||||
U8X8_C(0x01e), /* Contrast value. Setting for controlling brightness of Displaytech 64128N */
|
||||
//U8X8_C(0x0af), /* display on */
|
||||
//U8X8_C(0x0a5), /* display all points, ST7565 */
|
||||
//U8X8_C(0x0a4), /* normal display */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7565_64128n_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* st7565 datasheet, table 26, tcsh */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* st7565 datasheet, table 26, tcss */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* st7565 datasheet, table 26, tsds */
|
||||
/* sck_pulse_width_ns = */ 120, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* st7565 datasheet, table 24, tds8 */
|
||||
/* write_pulse_width_ns = */ 80, /* st7565 datasheet, table 24, tcclw */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 4,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_64128n(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_64128n_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_64128n_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
/* ZOLEN 128x64 */
|
||||
|
||||
static const uint8_t u8x8_d_st7565_zolen_128x64_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c8), /* common output mode */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
// U8X8_C(0x0c0), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a2), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on (regulator, booster and follower) */
|
||||
U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x */
|
||||
U8X8_C(0x027), /* set V0 voltage resistor ratio to max */
|
||||
U8X8_CA(0x081, 0x007), /* set contrast, contrast value, EA default: 0x016 */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_zolen_128x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_128x64_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_zolen_128x64_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_zflip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_zflip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*================================================*/
|
||||
/* NHD-C12832 */
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7565_128x32_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* st7565 datasheet, table 26, tcsh */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* st7565 datasheet, table 26, tcss */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* st7565 datasheet, table 26, tsds */
|
||||
/* sck_pulse_width_ns = */ 120, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* st7565 datasheet, table 24, tds8 */
|
||||
/* write_pulse_width_ns = */ 80, /* st7565 datasheet, table 24, tcclw */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 4,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_st7565_nhd_c12832_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
//U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a2), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on */
|
||||
U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x */
|
||||
U8X8_C(0x023), /* set V0 voltage resistor ratio to large*/
|
||||
U8X8_CA(0x081, 0x00a), /* set contrast, contrast value NHD C12832 */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_nhd_c12832(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_128x32_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_nhd_c12832_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
/* NHD-C12864 */
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7565_nhd_c12864_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* st7565 datasheet, table 26, tcsh */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* st7565 datasheet, table 26, tcss */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* st7565 datasheet, table 26, tsds */
|
||||
/* sck_pulse_width_ns = */ 120, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* st7565 datasheet, table 24, tds8 */
|
||||
/* write_pulse_width_ns = */ 80, /* st7565 datasheet, table 24, tcclw */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 4,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_st7565_nhd_c12864_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
//U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a2), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on */
|
||||
U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x */
|
||||
U8X8_C(0x023), /* set V0 voltage resistor ratio to large*/
|
||||
U8X8_CA(0x081, 180), /* set contrast, contrast value NHD C12864, see issue 186, increased contrast to 180 (issue 219) */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_nhd_c12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_nhd_c12864_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_nhd_c12864_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*================================================*/
|
||||
/* LM6059 (Adafruit)... probably this is a ST7567 display */
|
||||
|
||||
static const uint8_t u8x8_d_st7565_lm6059_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x060), /* set display start line to ... */
|
||||
|
||||
U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
U8X8_C(0x0c8), /* common output mode */
|
||||
//U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
// U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a3), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on (regulator, booster and follower) */
|
||||
U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x (ST7567 feature) */
|
||||
U8X8_C(0x027), /* set V0 voltage resistor ratio to max */
|
||||
U8X8_CA(0x081, 0x018), /* set contrast, contrast value, EA default: 0x016 */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7565_lm6059_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* st7565 datasheet, table 26, tcsh */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* st7565 datasheet, table 26, tcss */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* st7565 datasheet, table 26, tsds */
|
||||
/* sck_pulse_width_ns = */ 120, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* st7565 datasheet, table 24, tds8 */
|
||||
/* write_pulse_width_ns = */ 80, /* st7565 datasheet, table 24, tcclw */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 1, /* not sure... */
|
||||
/* flipmode_x_offset = */ 3,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_lm6059(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_lm6059_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_lm6059_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*================================================*/
|
||||
/* ERC12864-1 (buydisplay.com) */
|
||||
|
||||
static const uint8_t u8x8_d_st7565_erc12864_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to ... */
|
||||
|
||||
U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
U8X8_C(0x0c8), /* common output mode */
|
||||
//U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
// U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
// U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a3), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on (regulator, booster and follower) */
|
||||
U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x (ST7567 feature)*/
|
||||
U8X8_C(0x027), /* set V0 voltage resistor ratio to max */
|
||||
U8X8_CA(0x081, 0x018), /* set contrast, contrast value, EA default: 0x016 */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7565_erc12864_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* st7565 datasheet, table 26, tcsh */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* st7565 datasheet, table 26, tcss */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* st7565 datasheet, table 26, tsds */
|
||||
/* sck_pulse_width_ns = */ 120, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* st7565 datasheet, table 24, tds8 */
|
||||
/* write_pulse_width_ns = */ 80, /* st7565 datasheet, table 24, tcclw */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 4,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_erc12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_erc12864_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_erc12864_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*================================================*/
|
||||
/* NT7534, TG12864R */
|
||||
/* The NT7534 has an extended command set for the ST7565, however this is not used. */
|
||||
/* The TG12864R display is also shifted in lines, like the LM6059/Adafruit display */
|
||||
/* However contrast seems to be different */
|
||||
|
||||
static const uint8_t u8x8_d_nt7534_tg12864r_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x060), /* set display start line to ... */
|
||||
|
||||
U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
U8X8_C(0x0c8), /* common output mode */
|
||||
// Flipmode
|
||||
//U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c0), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a3), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on (regulator, booster and follower) */
|
||||
//U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x (ST7567 feature)*/
|
||||
U8X8_C(0x027), /* set V0 voltage resistor ratio to max */
|
||||
U8X8_CA(0x081, 0x009), /* set contrast, contrast value, EA default: 0x016 */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_nt7534_tg12864r(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
/* reuse the LM6059 data structure... this display seems to have similar shifts and offsets */
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_lm6059_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
|
||||
//u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_lm6059_init_seq);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_nt7534_tg12864r_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*================================================*/
|
||||
/* EA DOGM132 */
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7565_dogm132_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* st7565 datasheet, table 26, tcsh */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* st7565 datasheet, table 26, tcss */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* st7565 datasheet, table 26, tsds */
|
||||
/* sck_pulse_width_ns = */ 120, /* half of cycle time (100ns according to datasheet), AVR: below 70: 8 MHz, >= 70 --> 4MHz clock */
|
||||
/* sck_clock_hz = */ 4000000UL, /* since Arduino 1.6.0, the SPI bus speed in Hz. Should be 1000000000/sck_pulse_width_ns */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* st7565 datasheet, table 24, tds8 */
|
||||
/* write_pulse_width_ns = */ 80, /* st7565 datasheet, table 24, tcclw */
|
||||
/* tile_width = */ 17, /* width of 16*8=136 pixel */
|
||||
/* tile_hight = */ 4,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 132,
|
||||
/* pixel_height = */ 32
|
||||
};
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_st7565_dogm132_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
//U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a2), /* LCD bias 1/9 */
|
||||
U8X8_C(0x02f), /* all power control circuits on */
|
||||
U8X8_CA(0x0f8, 0x000), /* set booster ratio to 4x */
|
||||
U8X8_C(0x023), /* set V0 voltage resistor ratio to large*/
|
||||
U8X8_CA(0x081, 0x01f), /* set contrast, contrast value EA DOGM132 */
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
uint8_t u8x8_d_st7565_ea_dogm132(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
/* call common procedure first and handle messages there */
|
||||
if ( u8x8_d_st7565_common(u8x8, msg, arg_int, arg_ptr) == 0 )
|
||||
{
|
||||
/* msg not handled, then try here */
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7565_dogm132_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_dogm132_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7565_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return 0; /* msg unknown */
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
|
||||
u8x8_d_st7567.c
|
||||
|
||||
Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/)
|
||||
|
||||
Copyright (c) 2016, olikraus@gmail.com
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or other
|
||||
materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
*/
|
||||
#include "u8x8.h"
|
||||
|
||||
|
||||
|
||||
|
||||
static const uint8_t u8x8_d_st7567_132x64_powersave0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a4), /* all pixel off, issue 142 */
|
||||
U8X8_C(0x0af), /* display on */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7567_132x64_powersave1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7567_132x64_flip0_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a1), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c0), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7567_132x64_flip1_seq[] = {
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
U8X8_C(0x0a0), /* segment remap a0/a1*/
|
||||
U8X8_C(0x0c8), /* c0: scan dir normal, c8: reverse */
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
|
||||
/*=====================================================*/
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7567_132x64_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* */
|
||||
/* sck_pulse_width_ns = */ 120, /* */
|
||||
/* sck_clock_hz = */ 4000000UL, /* */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* */
|
||||
/* write_pulse_width_ns = */ 80, /* */
|
||||
/* tile_width = */ 17, /* width of 17*8=136 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 0,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 132,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_d_st7567_132x64_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
//U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a3), /* LCD bias 1/7 */
|
||||
/* power on sequence from paxinstruments */
|
||||
U8X8_C(0x028|4), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
U8X8_C(0x028|6), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
U8X8_C(0x028|7), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
|
||||
U8X8_C(0x026), /* v0 voltage resistor ratio */
|
||||
U8X8_CA(0x081, 0x027), /* set contrast, contrast value*/
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
/* pax instruments 132x64 display */
|
||||
uint8_t u8x8_d_st7567_pi_132x64(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_132x64_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
c *= 8;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
/*
|
||||
The following if condition checks the hardware limits of the st7567
|
||||
controller: It is not allowed to write beyond the display limits.
|
||||
This is in fact an issue within flip mode.
|
||||
*/
|
||||
if ( c + x > 132u )
|
||||
{
|
||||
c = 132u;
|
||||
c -= x;
|
||||
}
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*=====================================================*/
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static const u8x8_display_info_t u8x8_st7567_jlx12864_display_info =
|
||||
{
|
||||
/* chip_enable_level = */ 0,
|
||||
/* chip_disable_level = */ 1,
|
||||
|
||||
/* post_chip_enable_wait_ns = */ 150, /* */
|
||||
/* pre_chip_disable_wait_ns = */ 50, /* */
|
||||
/* reset_pulse_width_ms = */ 1,
|
||||
/* post_reset_wait_ms = */ 1,
|
||||
/* sda_setup_time_ns = */ 50, /* */
|
||||
/* sck_pulse_width_ns = */ 120, /* */
|
||||
/* sck_clock_hz = */ 4000000UL, /* */
|
||||
/* spi_mode = */ 0, /* active high, rising edge */
|
||||
/* i2c_bus_clock_100kHz = */ 4,
|
||||
/* data_setup_time_ns = */ 40, /* */
|
||||
/* write_pulse_width_ns = */ 80, /* */
|
||||
/* tile_width = */ 16, /* width of 16*8=128 pixel */
|
||||
/* tile_hight = */ 8,
|
||||
/* default_x_offset = */ 4,
|
||||
/* flipmode_x_offset = */ 0,
|
||||
/* pixel_width = */ 128,
|
||||
/* pixel_height = */ 64
|
||||
};
|
||||
|
||||
static const uint8_t u8x8_st7567_jlx12864_init_seq[] = {
|
||||
|
||||
U8X8_START_TRANSFER(), /* enable chip, delay is part of the transfer start */
|
||||
|
||||
U8X8_C(0x0e2), /* soft reset */
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x040), /* set display start line to 0 */
|
||||
|
||||
U8X8_C(0x0a1), /* ADC set to reverse */
|
||||
U8X8_C(0x0c0), /* common output mode */
|
||||
// Flipmode
|
||||
//U8X8_C(0x0a0), /* ADC set to reverse */
|
||||
//U8X8_C(0x0c8), /* common output mode */
|
||||
|
||||
U8X8_C(0x0a6), /* display normal, bit val 0: LCD pixel off. */
|
||||
U8X8_C(0x0a3), /* LCD bias 1/7 */
|
||||
/* power on sequence from paxinstruments */
|
||||
U8X8_C(0x028|4), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
U8X8_C(0x028|6), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
U8X8_C(0x028|7), /* all power control circuits on */
|
||||
U8X8_DLY(50),
|
||||
|
||||
U8X8_C(0x023), /* v0 voltage resistor ratio */
|
||||
U8X8_CA(0x081, 42>>2), /* set contrast, contrast value*/
|
||||
|
||||
U8X8_C(0x0ae), /* display off */
|
||||
U8X8_C(0x0a5), /* enter powersafe: all pixel on, issue 142 */
|
||||
|
||||
U8X8_END_TRANSFER(), /* disable chip */
|
||||
U8X8_END() /* end of sequence */
|
||||
};
|
||||
|
||||
/* JLX12864 display */
|
||||
uint8_t u8x8_d_st7567_jlx12864(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t x, c;
|
||||
uint8_t *ptr;
|
||||
switch(msg)
|
||||
{
|
||||
case U8X8_MSG_DISPLAY_SETUP_MEMORY:
|
||||
u8x8_d_helper_display_setup_memory(u8x8, &u8x8_st7567_jlx12864_display_info);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_INIT:
|
||||
u8x8_d_helper_display_init(u8x8);
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_st7567_jlx12864_init_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_POWER_SAVE:
|
||||
if ( arg_int == 0 )
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave0_seq);
|
||||
else
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_powersave1_seq);
|
||||
break;
|
||||
case U8X8_MSG_DISPLAY_SET_FLIP_MODE:
|
||||
if ( arg_int == 0 )
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip0_seq);
|
||||
u8x8->x_offset = u8x8->display_info->default_x_offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
u8x8_cad_SendSequence(u8x8, u8x8_d_st7567_132x64_flip1_seq);
|
||||
u8x8->x_offset = u8x8->display_info->flipmode_x_offset;
|
||||
}
|
||||
break;
|
||||
#ifdef U8X8_WITH_SET_CONTRAST
|
||||
case U8X8_MSG_DISPLAY_SET_CONTRAST:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
u8x8_cad_SendCmd(u8x8, 0x081 );
|
||||
u8x8_cad_SendArg(u8x8, arg_int >> 2 ); /* st7567 has range from 0 to 63 */
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
#endif
|
||||
case U8X8_MSG_DISPLAY_DRAW_TILE:
|
||||
u8x8_cad_StartTransfer(u8x8);
|
||||
|
||||
x = ((u8x8_tile_t *)arg_ptr)->x_pos;
|
||||
x *= 8;
|
||||
x += u8x8->x_offset;
|
||||
u8x8_cad_SendCmd(u8x8, 0x010 | (x>>4) );
|
||||
u8x8_cad_SendCmd(u8x8, 0x000 | ((x&15)));
|
||||
u8x8_cad_SendCmd(u8x8, 0x0b0 | (((u8x8_tile_t *)arg_ptr)->y_pos));
|
||||
|
||||
c = ((u8x8_tile_t *)arg_ptr)->cnt;
|
||||
c *= 8;
|
||||
ptr = ((u8x8_tile_t *)arg_ptr)->tile_ptr;
|
||||
/*
|
||||
The following if condition checks the hardware limits of the st7567
|
||||
controller: It is not allowed to write beyond the display limits.
|
||||
This is in fact an issue within flip mode.
|
||||
*/
|
||||
if ( c + x > 132u )
|
||||
{
|
||||
c = 132u;
|
||||
c -= x;
|
||||
}
|
||||
do
|
||||
{
|
||||
u8x8_cad_SendData(u8x8, c, ptr); /* note: SendData can not handle more than 255 bytes */
|
||||
arg_int--;
|
||||
} while( arg_int > 0 );
|
||||
|
||||
u8x8_cad_EndTransfer(u8x8);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user