This commit is contained in:
olikraus 2017-05-28 16:57:56 +02:00
parent b2ce464c4c
commit 9a1a015737
6 changed files with 219 additions and 39 deletions

View File

@ -1,6 +1,8 @@
Wiring
Q: Why does my xxx_SW_I2C() device not work with my other I2C devices?
A: SW_I2C emulates I2C with digitalWrite(), which will have a conflict with other
I2C devices at the same pins. There are two options: (A) use xxx_HW_I2C() or
@ -20,7 +22,23 @@ Q: For HW SPI no pin numbers are required in the constructor. But which are
the pin numbers for wiring?
A: This depends on your board. For some official boards, this is listed here:
https://www.arduino.cc/en/Reference/SPI
You need to connect MOSI (data) and SCK (clock) pins.
You need to connect MOSI (data) and SCK (clock) pins of your board with the
corresponding pins with your display.
All U8g2 software emulated SPI constructors look like this:
U8G2_..._4W_SW_SPI u8g2(U8G2_R0, clock, data, cs, dc, reset);
All U8g2 hardware SPI constructors look like this:
U8G2_..._4W_SW_SPI u8g2(U8G2_R0, cs, dc, reset);
Q: For HW I2C no pin numbers are required in the constructor. But which are
the pin numbers for wiring?
A: See same question for SPI. For some boards, the pins are listed here:
https://www.arduino.cc/en/Reference/Wire
All U8g2 software emulated I2C constructors look like this:
U8G2_..._SW_I2C u8g2(U8G2_R0, clock, data, reset);
All U8g2 hardware I2C constructors look like this:
U8G2_..._HW_I2C u8g2(U8G2_R0, reset);
Note: The HW_I2C allows to more arguments for hardware pin number remapping.
However, this is only supported on the ESP8266.
Q: The pin names on my display do not fit to the pin names of U8g2.
A: Yes, each datasheet/product/controller has different names. There

View File

@ -134,12 +134,19 @@ uint32_t get_wakeup_count(void)
/*============================================*/
/* 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)

View File

@ -16,6 +16,8 @@
*/
#include <stdint.h>
#include <stddef.h>
#include "stm32l031xx.h"
#include "delay.h"
#include "u8g2.h"
@ -38,6 +40,15 @@
/* 50ms*20*18 = 18 second */
#define MENU_IDLE_SYSTICK_TIMEOUT (20*18)
/* max alarm duration */
/* time in systicks (50ms) */
/* 50ms*20 = 1 second */
/* 50ms*20*10 = 10 second */
/* 50ms*20*18 = 18 second */
/* 50ms*20*120 = 120 seconds */
#define ALARM_MAX_SYSTICK_TIME (20*30)
/* wakeup period: The uC will wake up after the specified number of seconds */
/* the value is one less the intended number of seconds: */
/* 0: wakeup every 1 second */
@ -90,12 +101,87 @@ volatile unsigned long Tamper3Count = 0;
volatile unsigned long MenuIdleTimer = 0;
volatile unsigned long PWR_CSR_Backup;
volatile unsigned long ResetReason = RESET_REASON_POR;
volatile unsigned long AlarmSeqPos = 0;
volatile unsigned long AlarmSeqDly = 0;
const uint8_t *AlarmSeqPtr = NULL;
const uint8_t *AlarmSeqStart = NULL;
volatile unsigned long AlarmSeqTime = 0;
volatile unsigned long RTCUpdateCount = 0; // decremented in SysTick IRQ if not 0
//rtc_t rtc;
u8g2_t u8g2;
/*=======================================================================*/
#define AOff(dly) (0<<5)|((dly)&0x01f)
#define ABeep(dly) (1<<5)|((dly)&0x01f)
#define ARepeat() (0xfe)
#define AEnd() (0xff)
/*=======================================================================*/
const uint8_t ASeqTrippleBeep[] =
{ ABeep(1),AOff(2), ABeep(1),AOff(2),ABeep(1),AOff(22), ARepeat() };
/*=======================================================================*/
void set_alarm_sequence(const uint8_t *alarm_sequence)
{
GPIOA->BSRR = GPIO_BSRR_BR_6; /* atomic clr PA6 */
AlarmSeqDly = 0;
AlarmSeqPtr = alarm_sequence;
AlarmSeqStart = alarm_sequence;
AlarmSeqTime = 0;
}
void ExecuteAlarmSequenceStep(void)
{
if ( AlarmSeqPtr == NULL )
return;
//AlarmSeqTime++;
//if ( AlarmSeqTime > ALARM_MAX_SYSTICK_TIME )
//{
// set_alarm_sequence(NULL);
// gui_data.is_alarm = 0; // disable alarm
// return;
//}
if ( AlarmSeqDly > 0 )
{
AlarmSeqDly--;
return ;
}
switch( (*AlarmSeqPtr)>>5 )
{
case 0:
GPIOA->BSRR = GPIO_BSRR_BR_6; /* atomic clr PA6 */
AlarmSeqDly = ((*AlarmSeqPtr) & 0x01f);
break;
case 1:
GPIOA->BSRR = GPIO_BSRR_BS_6; /* atomic set PA13 */
AlarmSeqDly = ((*AlarmSeqPtr) & 0x01f);
break;
default:
if ( *AlarmSeqPtr == 0x0fe )
AlarmSeqPtr = AlarmSeqStart;
return;
}
AlarmSeqPtr++;
}
void SetAlarmSequence(const uint8_t *alarm_sequence)
{
__disable_irq();
set_alarm_sequence(alarm_sequence);
__enable_irq();
}
/*=======================================================================*/
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
@ -161,8 +247,11 @@ void __attribute__ ((interrupt, used)) SysTick_Handler(void)
RTC->ISR &= ~RTC_ISR_TAMP2F; /* clear tamper flag, allow new tamper event */
}
MenuIdleTimer++;
ExecuteAlarmSequenceStep();
MenuIdleTimer++;
if ( RTCUpdateCount > 0 )
RTCUpdateCount--;
}
void __attribute__ ((interrupt, used)) RTC_IRQHandler(void)
@ -244,6 +333,14 @@ void startUp(void)
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD2; /* no pullup/pulldown for PA2 */
GPIOA->PUPDR |= GPIO_PUPDR_PUPD2_0; /* pullup for PA2 */
/* buzzer output */
GPIOA->MODER &= ~GPIO_MODER_MODE6; /* clear mode for PA6 */
GPIOA->MODER |= GPIO_MODER_MODE6_0; /* Output mode for PA6 */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_6; /* Push/Pull for PA6 */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED6; /* low speed for PA6 */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD6; /* no pullup/pulldown for PA6 */
GPIOA->BSRR = GPIO_BSRR_BR_6; /* atomic clr PA6 */
}
@ -453,7 +550,10 @@ void startRTCWakeUp(void)
RTC_TAMPCR_TAMP3NOERASE | RTC_TAMPCR_TAMP3IE | RTC_TAMPCR_TAMP3E |
RTC_TAMPCR_TAMP2NOERASE | RTC_TAMPCR_TAMP2IE | RTC_TAMPCR_TAMP2E |
RTC_TAMPCR_TAMPPRCH_0 | RTC_TAMPCR_TAMPFLT_1 | RTC_TAMPCR_TAMPFREQ;
// RTC_TAMPCR_TAMPPUDIS
/* wake up IRQ is connected to line 20 */
EXTI->RTSR |= EXTI_RTSR_RT20; /* rising edge for wake up line */
EXTI->IMR |= EXTI_IMR_IM20; /* interrupt enable */
@ -528,6 +628,9 @@ void enterStandByMode(void)
u8g2_SetPowerSave(&u8g2, 1);
SetAlarmSequence(NULL);
GPIOA->MODER &= ~GPIO_MODER_MODE6; /* clear mode for PA6 --> input */
PWR->CR |= PWR_CR_PDDS; /* Power Down Deepsleep */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; /* set the cortex M0+ deep sleep flag */
__DSB(); /* finish memory access */
@ -760,6 +863,13 @@ int main()
delay_micro_seconds(3000000);
do_reset();
}
/*set a alarm time for testing */
gui_alarm_list[0].enable = 1;
gui_alarm_list[0].m = 1;
gui_alarm_list[0].wd[5] = 1;
gui_Recalculate();
}
else
{
@ -807,14 +917,40 @@ int main()
/* get current voltage level of the battery */
adc = readADC(5);
/* start user loop */
for(;;)
{
if ( gui_menu.me_list == melist_display_time )
if ( RTCUpdateCount == 0 )
{
readRTC();
gui_SignalTimeChange();
if ( gui_menu.me_list == melist_display_time )
{
readRTC();
gui_SignalTimeChange();
}
else
{
//readRTC();
//gui_Recalculate();
}
RTCUpdateCount = 10; // update every 10 systicks (half second)
}
for(;;)
{
i = key_get();
if ( i == KEY_NONE )
break;
if ( i == KEY_SELECT )
gui_Select();
if ( i == KEY_NEXT )
gui_Next();
}
u8g2_ClearBuffer(&u8g2);
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic set PA13 */
gui_Draw();
@ -827,37 +963,44 @@ int main()
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic clr PA13 */
u8g2_SendBuffer(&u8g2);
for(;;)
if ( MenuIdleTimer > MENU_IDLE_SYSTICK_TIMEOUT )
{
i = key_get();
if ( i == KEY_NONE )
break;
if ( i == KEY_SELECT )
gui_Select();
if ( i == KEY_NEXT )
gui_Next();
if ( gui_data.is_equal == 0 ) // idea is, that the alarm does not go off during the alarm to avoid another alarm in the same minute
{
if ( gui_menu.me_list != melist_display_time )
{
/* jump back to the display menu and redraw the time. not sure if this is required */
menu_SetMEList(&gui_menu, melist_display_time, 0);
readRTC();
gui_SignalTimeChange();
u8g2_ClearBuffer(&u8g2);
gui_Draw();
u8g2_SetFont(&u8g2, MENU_NORMAL_FONT);
u8g2_DrawStr(&u8g2, 0, 8, u8x8_u16toa((adc*330UL)>>12, 3));
drawBatSymbol(adc);
u8g2_SendBuffer(&u8g2);
}
/* stop everything except RTC */
enterStandByMode();
}
else
{
/* read and recalculate so that the gui_data.is_equal is updated */
readRTC();
gui_Recalculate();
}
}
if ( MenuIdleTimer > MENU_IDLE_SYSTICK_TIMEOUT && gui_data.is_equal == 0 )
{
if ( gui_menu.me_list != melist_display_time )
{
/* jump back to the display menu and redraw the time. not sure if this is required */
menu_SetMEList(&gui_menu, melist_display_time, 0);
readRTC();
gui_SignalTimeChange();
u8g2_ClearBuffer(&u8g2);
gui_Draw();
u8g2_SetFont(&u8g2, MENU_NORMAL_FONT);
u8g2_DrawStr(&u8g2, 0, 8, u8x8_u16toa((adc*330UL)>>12, 3));
drawBatSymbol(adc);
u8g2_SendBuffer(&u8g2);
}
/* stop everything except RTC */
enterStandByMode();
}
__DSB(); /* finish memory access */
__WFI(); /* enter sleep */
__NOP();
}
}

View File

@ -340,7 +340,7 @@ int main()
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->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
SysTick->VAL = 0;

View File

@ -59,7 +59,7 @@ struct _gui_alarm_struct
/* alarm information */
uint8_t snooze_count; /* input, 1 bit*/
uint8_t enable; /* input, 1 bit */
volatile uint8_t enable; /* input, 1 bit */
uint8_t skip_wd; /* input 0 = no skip, 1 = Monday, ... 3 bits*/
uint8_t h; /* input 5 bits */
uint8_t m; /* input 6 bits */
@ -68,6 +68,7 @@ struct _gui_alarm_struct
typedef struct _gui_alarm_struct gui_alarm_t;
/* guimenu.c */
extern const me_t melist_setup_time[];

View File

@ -310,7 +310,6 @@ void gui_StoreData(void)
/* recalculate all internal data */
/* additionally the active alarm menu might be set by this function */
void gui_Recalculate(void)
{
int i;
@ -326,6 +325,7 @@ void gui_Recalculate(void)
}
/* minute and/or hour has changed */
/* additionally the active alarm menu might be set by this function */
void gui_SignalTimeChange(void)
{
/* recalculate dependent values */
@ -388,7 +388,18 @@ void gui_Next(void)
if ( gui_menu.me_list == melist_active_alarm_menu )
{
disable_alarm();
gui_alarm_list[gui_data.active_alarm_idx].snooze_count = 1;
if ( gui_alarm_list[gui_data.active_alarm_idx].snooze_count != 0 )
{
int i;
/* this is already the snooze alarm, so clear all and behave like the normal alarm off */
for( i = 0; i < GUI_ALARM_CNT; i++ )
gui_alarm_list[i].snooze_count = 0;
}
else
{
/* enable snooze */
gui_alarm_list[gui_data.active_alarm_idx].snooze_count = 1;
}
gui_data.is_alarm = 0;
gui_Recalculate();
menu_SetMEList(&gui_menu, melist_display_time, 0);
@ -404,9 +415,9 @@ void gui_Select(void)
if ( gui_menu.me_list == melist_active_alarm_menu )
{
int i;
disable_alarm();
for( i = 0; i < GUI_ALARM_CNT; i++ )
gui_alarm_list[i].snooze_count = 0;
disable_alarm();
gui_data.is_alarm = 0;
gui_Recalculate();
menu_SetMEList(&gui_menu, melist_display_time, 0);