Commit abdf9648 authored by Matthieu Cattin's avatar Matthieu Cattin

Merge remote-tracking branch 'ohwr/orson_sw_mcattin_rebased' into mcattin_sw_dev

Conflicts:
	sw/common/gfx/gfx.c
	sw/common/gfx/gfx.h
parents 9e86ba51 71e51349
static const uint8_t battery_data[] = {
0x8d,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x8d,
0x00};
static const struct rle_bitmap battery = { 15, 12, battery_data };
static const uint8_t battery_charging_data[] = {
0x8d,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x05,
0x81,
0x03,
0x82,
0x04,
0x84,
0x01,
0x82,
0x00,
0x86,
0x03,
0x82,
0x00,
0x86,
0x03,
0x82,
0x04,
0x84,
0x01,
0x82,
0x05,
0x81,
0x03,
0x82,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x8d,
0x00};
static const struct rle_bitmap battery_charging = { 15, 12, battery_charging_data };
#include <bitmaps.h>
static const uint8_t example_icon_data[] = {
0x2e,
0x81,
0x05,
0x81,
0x04,
0x81,
0x05,
0x82,
0x16,
0x80,
0x0d,
0x80,
0x0d,
0x80,
0x08,
0x80,
0x09,
0x80,
0x02,
0x80,
0x08,
0x81,
0x02,
0x81,
0x06,
0x81,
0x04,
0x83,
0x01,
0x82,
0x08,
0x83,
0x14};
const struct rle_bitmap example_icon = { 15, 15, example_icon_data };
static const uint8_t gps_receiving_data[] = {
0x06,
0x83,
0x0e,
0x80,
0x0a,
0x81,
0x01,
0x80,
0x04,
0x82,
0x03,
0x80,
0x01,
0x80,
0x02,
0x81,
0x06,
0x80,
0x00,
0x80,
0x01,
0x81,
0x03,
0x81,
0x01,
0x80,
0x00,
0x80,
0x01,
0x82,
0x00,
0x83,
0x03,
0x80,
0x01,
0x82,
0x02,
0x80,
0x07,
0x83,
0x01,
0x80,
0x01,
0x80,
0x05,
0x83,
0x03,
0x80,
0x06,
0x84,
0x00,
0x81,
0x07,
0x85,
0x0a,
0x81,
0x09,
0x84,
0x08,
0x86,
0x05};
const struct rle_bitmap gps_receiving = { 15, 15, gps_receiving_data };
static const uint8_t battery_data[] = {
0x8d,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x82,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x8d,
0x00};
const struct rle_bitmap battery = { 15, 12, battery_data };
static const uint8_t gps_disconnected_data[] = {
0x0a,
0x80,
0x0d,
0x80,
0x0b,
0x84,
0x03,
0x82,
0x04,
0x80,
0x04,
0x81,
0x06,
0x80,
0x03,
0x81,
0x03,
0x81,
0x06,
0x82,
0x00,
0x83,
0x06,
0x82,
0x02,
0x80,
0x07,
0x83,
0x01,
0x80,
0x01,
0x80,
0x05,
0x83,
0x03,
0x80,
0x06,
0x84,
0x00,
0x81,
0x07,
0x85,
0x0a,
0x81,
0x09,
0x84,
0x08,
0x86,
0x05};
const struct rle_bitmap gps_disconnected = { 15, 15, gps_disconnected_data };
static const uint8_t battery_charging_data[] = {
0x8d,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x80,
0x05,
0x81,
0x03,
0x82,
0x04,
0x84,
0x01,
0x82,
0x00,
0x86,
0x03,
0x82,
0x00,
0x86,
0x03,
0x82,
0x04,
0x84,
0x01,
0x82,
0x05,
0x81,
0x03,
0x82,
0x0b,
0x80,
0x00,
0x80,
0x0b,
0x80,
0x00,
0x8d,
0x00};
const struct rle_bitmap battery_charging = { 15, 12, battery_charging_data };
static const uint8_t gps_searching_data[] = {
0x0c,
0x80,
0x0c,
0x80,
0x13,
0x82,
0x03,
0x80,
0x05,
0x81,
0x04,
0x80,
0x05,
0x81,
0x03,
0x81,
0x06,
0x82,
0x00,
0x83,
0x06,
0x82,
0x02,
0x80,
0x07,
0x83,
0x01,
0x80,
0x01,
0x80,
0x05,
0x83,
0x03,
0x80,
0x06,
0x84,
0x00,
0x81,
0x07,
0x85,
0x0a,
0x81,
0x09,
0x84,
0x08,
0x86,
0x05};
const struct rle_bitmap gps_searching = { 15, 15, gps_searching_data };
#ifndef BITMAPS_H
#define BITMAPS_H
#include <stdint.h>
struct rle_bitmap
{
uint8_t w;
uint8_t h;
const uint8_t *data;
};
extern const struct rle_bitmap example_icon;
extern const struct rle_bitmap gps_receiving;
extern const struct rle_bitmap battery;
extern const struct rle_bitmap gps_disconnected;
extern const struct rle_bitmap battery_charging;
extern const struct rle_bitmap gps_searching;
#endif /* BITMAPS_H */
......@@ -3,6 +3,8 @@
import sys
import math
import numpy
import os
import os.path
from PIL import Image
def pixel_to_bit(pixel,threshold=128):
......@@ -13,17 +15,13 @@ def pixel_to_bit(pixel,threshold=128):
return 0
def convert(im, name):
name = name.split('.')[0]
f = open(name+".h",'w')
f = open("bitmaps.c",'a')
pix = im.load()
f.write("static const uint8_t %s_data[] = {\n"%name);
for y in range(0, im.size[1]):
for x in range(0, im.size[0]):
for x in range(0, im.size[0]):
if(x==0 and y==0):
prev = pix[0, 0][0]
l=0
......@@ -40,48 +38,72 @@ def convert(im, name):
prev=cur
if(prev):
f.write(" 0x%02x" % (l))
f.write(" 0x%02x" % (l))
else:
f.write(" 0x%02x" % (l | 0x80))
f.write(" 0x%02x" % (l | 0x80))
f.write("};\n");
f.write("static const struct rle_bitmap %s = { %d, %d, %s_data };\n" % (name, im.size[0], im.size[1], name));
f.close()
print "RLE encoded image written to: %s.h\n"%name
f.write("const struct rle_bitmap %s = { %d, %d, %s_data };\n\n" % (name, im.size[0], im.size[1], name));
f.close()
def use():
print "Use: bmp2array.py imagefile"
f = open("bitmaps.h",'a')
f.write("extern const struct rle_bitmap %s;\n" % name);
f.close()
#
# Main script begins here.
#
# First check for keyword arguments on the command line.
#
if len(sys.argv) > 2:
print "Too many arghuments."
use()
exit(-1)
# Clean the previous output
if os.path.isfile("bitmaps.c"):
os.remove("bitmaps.h")
if os.path.isfile("bitmaps.c"):
os.remove("bitmaps.c")
#
# Open the image file and get the basic information about it.
#
try:
im = Image.open(sys.argv[1])
except:
# Eventually this should give more useful information (e.g. file does not
# exist, or not an image file, or ...
print "Unable to open %s" % sys.argv[1]
exit(-1)
# Write headers
f = open("bitmaps.h", 'a')
f.write("""#ifndef BITMAPS_H
#define BITMAPS_H
width,height = im.size
print "\nfile : %s\nformat : %s\nmode : %s\npalette : %s\nsize : %dx%d\n" % (sys.argv[1], im.format, im.mode, im.palette, width, height)
#include <stdint.h>
struct rle_bitmap
{
uint8_t w;
uint8_t h;
const uint8_t *data;
};
""")
f.close()
f = open("bitmaps.c", 'a')
f.write("#include <bitmaps.h>\n\n")
f.close()
#
# Do it!
# Process .bmp files in the current directory
#
convert(im, sys.argv[1])
for file in os.listdir("."):
if file.endswith(".bmp"):
try:
print("Processing: " + file)
im = Image.open(file)
width,height = im.size
print("format : %s" % im.format)
print("mode : %s" % im.mode)
print("palette : %s" % im.palette)
print("size : %dx%d" % (width, height))
convert(im, file)
except:
# Eventually this should give more useful information (e.g. file does not
# exist, or not an image file, or ...
print("Unable to open " + file)
f = open("bitmaps.h", 'a')
f.write("\n#endif /* BITMAPS_H */\n")
f.close()
static const uint8_t gps_disconnected_data[] = {
0x0a,
0x80,
0x0d,
0x80,
0x0b,
0x84,
0x03,
0x82,
0x04,
0x80,
0x04,
0x81,
0x06,
0x80,
0x03,
0x81,
0x03,
0x81,
0x06,
0x82,
0x00,
0x83,
0x06,
0x82,
0x02,
0x80,
0x07,
0x83,
0x01,
0x80,
0x01,
0x80,
0x05,
0x83,
0x03,
0x80,
0x06,
0x84,
0x00,
0x81,
0x07,
0x85,
0x0a,
0x81,
0x09,
0x84,
0x08,
0x86,
0x05};
static const struct rle_bitmap gps_disconnected = { 15, 15, gps_disconnected_data };
static const uint8_t gps_receiving_data[] = {
0x06,
0x83,
0x0e,
0x80,
0x0a,
0x81,
0x01,
0x80,
0x04,
0x82,
0x03,
0x80,
0x01,
0x80,
0x02,
0x81,
0x06,
0x80,
0x00,
0x80,
0x01,
0x81,
0x03,
0x81,
0x01,
0x80,
0x00,
0x80,
0x01,
0x82,
0x00,
0x83,
0x03,
0x80,
0x01,
0x82,
0x02,
0x80,
0x07,
0x83,
0x01,
0x80,
0x01,
0x80,
0x05,
0x83,
0x03,
0x80,
0x06,
0x84,
0x00,
0x81,
0x07,
0x85,
0x0a,
0x81,
0x09,
0x84,
0x08,
0x86,
0x05};
static const struct rle_bitmap gps_receiving = { 15, 15, gps_receiving_data };
static const uint8_t gps_searching_data[] = {
0x0c,
0x80,
0x0c,
0x80,
0x13,
0x82,
0x03,
0x80,
0x05,
0x81,
0x04,
0x80,
0x05,
0x81,
0x03,
0x81,
0x06,
0x82,
0x00,
0x83,
0x06,
0x82,
0x02,
0x80,
0x07,
0x83,
0x01,
0x80,
0x01,
0x80,
0x05,
0x83,
0x03,
0x80,
0x06,
0x84,
0x00,
0x81,
0x07,
0x85,
0x0a,
0x81,
0x09,
0x84,
0x08,
0x86,
0x05};
static const struct rle_bitmap gps_searching = { 15, 15, gps_searching_data };
......@@ -142,9 +142,12 @@ INCLUDEPATHS += \
C_SRC += \
../common/Device/EnergyMicro/EFM32GG/Source/system_efm32gg.c \
../common/drivers/dmactrl.c \
../common/drivers/lcd.c \
../common/drivers/lcd_dma.c \
../common/emlib/src/em_assert.c \
../common/emlib/src/em_cmu.c \
../common/emlib/src/em_dma.c \
../common/emlib/src/em_emu.c \
../common/emlib/src/em_rmu.c \
../common/emlib/src/em_gpio.c \
......@@ -152,6 +155,7 @@ C_SRC += \
../common/emlib/src/em_int.c \
../common/emlib/src/em_system.c \
../common/emlib/src/em_rtc.c \
../common/emlib/src/em_timer.c \
../common/emlib/src/em_burtc.c \
../common/emlib/src/em_usart.c \
../common/gfx/graphics.c \
......@@ -166,7 +170,6 @@ C_SRC += \
../common/gfx/font_xm4x6.c \
../common/gfx/font_xm5x8.c \
../common/gfx/font_xm16x25b.c \
../common/udelay.c \
../common/delay.c \
../common/drivers/i2cdrv.c \
../common/drivers/light_sensor.c \
......
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Backlight control.
*/
#include "backlight.h"
#include <em_cmu.h>
#include <em_gpio.h>
#include <em_timer.h>
static int backlight_level;
void backlight_init(void)
{
CMU_ClockEnable(cmuClock_TIMER1, true);
// Configure backlight LED pins as outputs
GPIO_PinModeSet(gpioPortE, 11, gpioModePushPull, 0);
GPIO_PinModeSet(gpioPortE, 12, gpioModePushPull, 0);
// Select CC channel parameters
TIMER_InitCC_TypeDef timerCCInit =
{
.eventCtrl = timerEventEveryEdge,
.edge = timerEdgeBoth,
.prsSel = timerPRSSELCh1,
.cufoa = timerOutputActionNone,
.cofoa = timerOutputActionNone,
.cmoa = timerOutputActionToggle,
.mode = timerCCModePWM,
.filter = false,
.prsInput = false,
.coist = false,
.outInvert = false,
};
// Configure CC channel 1 & 2
TIMER_InitCC(TIMER1, 1, &timerCCInit);
TIMER_InitCC(TIMER1, 2, &timerCCInit);
// Route CC1 to location 1 (PE11) and enable pin
TIMER1->ROUTE |= (TIMER_ROUTE_CC1PEN | TIMER_ROUTE_LOCATION_LOC1);
// Route CC2 to location 1 (PE12) and enable pin
TIMER1->ROUTE |= (TIMER_ROUTE_CC2PEN | TIMER_ROUTE_LOCATION_LOC1);
// Select timer parameters
TIMER_Init_TypeDef timerInit =
{
.enable = true,
.debugRun = true,
.prescale = timerPrescale64,
.clkSel = timerClkSelHFPerClk,
.fallAction = timerInputActionNone,
.riseAction = timerInputActionNone,
.mode = timerModeUp,
.dmaClrAct = false,
.quadModeX4 = false,
.oneShot = false,
.sync = false,
};
// Set Top Value (determines PWM frequency)
// TODO the top value may need adjustments if HFPER changes
// TIMER_TopSet(TIMER1, CMU_ClockFreqGet(cmuClock_HFPER) / 100000));
TIMER_TopSet(TIMER1, 100);
backlight_set_level(0);
// Configure timer
TIMER_Init(TIMER1, &timerInit);
}
void backlight_set_level(int level)
{
const int BL_MAX_LEVEL = 100;
if(level <= 0) {
TIMER_Enable(TIMER1, false);
level = 0; // in case level is negative
} else {
// Reenable the timer, if it was turned off previously
if(backlight_level == 0)
TIMER_Enable(TIMER1, true);
if(level > BL_MAX_LEVEL)
level = BL_MAX_LEVEL;
TIMER_CompareBufSet(TIMER1, 1, level);
TIMER_CompareBufSet(TIMER1, 2, level);
}
backlight_level = level;
}
unsigned int backlight_get_level(void)
{
return backlight_level;
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Backlight control.
*/
#ifndef BACKLIGHT_H
#define BACKLIGHT_H
/**
* @brief Initialize backlight control.
*/
void backlight_init(void);
/**
* @brief Sets the backlight brightness.
* @param level is the brightness level to be set. Valid values are in the
* 0-100 range. 0 stands for completely turned off, 100 is full brightness.
*/
void backlight_set_level(int level);
/**
* @brief Returns the current level of backlight.
*/
unsigned int backlight_get_level(void);
#endif /* BACKLIGHT_H */
......@@ -25,6 +25,7 @@
*/
#include "buttons.h"
#include <em_gpio.h>
__attribute__((weak))
void GPIO_EVEN_IRQHandler(void)
......
......@@ -27,23 +27,21 @@
#ifndef BUTTONS_H
#define BUTTONS_H
#include "em_gpio.h"
// Top left button
#define BUT_TL_PORT gpioPortC
#define BUT_TL_PIN 7
#define BUT_TL_PORT gpioPortA
#define BUT_TL_PIN 8
// Top right button
#define BUT_TR_PORT gpioPortA
#define BUT_TR_PIN 0
#define BUT_TR_PORT gpioPortC
#define BUT_TR_PIN 6
// Bottom left button
#define BUT_BL_PORT gpioPortC
#define BUT_BL_PIN 6
#define BUT_BL_PORT gpioPortA
#define BUT_BL_PIN 0
// Bottom right button
#define BUT_BR_PORT gpioPortA
#define BUT_BR_PIN 8
#define BUT_BR_PORT gpioPortC
#define BUT_BR_PIN 7
/**
* @TODO desc
* @brief Iniailize button IOs & interrupts.
*/
void buttons_init(void);
......
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Buzzer control.
*/
#include "buzzer.h"
#include <em_cmu.h>
#include <em_gpio.h>
#include <em_timer.h>
#define BUZZER_PWM_FREQ 10000
void buzzer_init(void)
{
// Configure buzzer pin as push/pull output
GPIO_PinModeSet(gpioPortA, 9, gpioModePushPull, 0);
// Enable clock for TIMER2 module
CMU_ClockEnable(cmuClock_TIMER2, true);
// Select CC channel parameters
TIMER_InitCC_TypeDef timerCCInit =
{
.cufoa = timerOutputActionNone,
.cofoa = timerOutputActionToggle,
.cmoa = timerOutputActionNone,
.mode = timerCCModeCompare,
.filter = false,
.prsInput = false,
.coist = false,
.outInvert = false,
};
// Configure CC channel 1
TIMER_InitCC(TIMER2, 1, &timerCCInit);
// Route CC1 to location 0 (PA9) and enable pin
TIMER2->ROUTE |= (TIMER_ROUTE_CC1PEN | TIMER_ROUTE_LOCATION_LOC0);
// Select timer parameter
TIMER_Init_TypeDef timerInit =
{
.enable = false,
.debugRun = true,
.prescale = timerPrescale64,
.clkSel = timerClkSelHFPerClk,
.fallAction = timerInputActionNone,
.riseAction = timerInputActionNone,
.mode = timerModeUp,
.dmaClrAct = false,
.quadModeX4 = false,
.oneShot = false,
.sync = false,
};
// Configure timer
TIMER_Init(TIMER2, &timerInit);
buzzer_set_freq(5500);
}
void buzzer_enable(void)
{
TIMER_Enable(TIMER2, true);
}
void buzzer_disable(void)
{
TIMER_Enable(TIMER2, false);
}
void buzzer_set_freq(int frequency)
{
const int MIN_AUDIBLE = 6;
const int MAX_AUDIBLE = 5000;
// For timer, lower TOP values mean higher frequency
frequency = MAX_AUDIBLE + MIN_AUDIBLE - frequency;
if(frequency < MIN_AUDIBLE)
frequency = MIN_AUDIBLE;
else if(frequency > MAX_AUDIBLE)
frequency = MAX_AUDIBLE;
// TODO add a formula to convert frequency to TIMER top value
TIMER_TopSet(TIMER2, frequency);
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Buzzer control.
*/
#ifndef BUZZER_H
#define BUZZER_H
/**
* @brief Initialize buzzer.
*/
void buzzer_init(void);
/**
* @brief Turns on the buzzer.
*/
void buzzer_enable(void);
/**
* @brief Turns off the buzzer.
*/
void buzzer_disable(void);
/**
* @brief Sets the frequency of buzzer sound.
* @param frequency is the frequency to be set. Valid values are between 6
* and 5500. If the requested frequency is out of the valid range, it will
* be set to either the closest valid value (either the lowest one or the
* highest one).
*/
void buzzer_set_freq(int frequency);
#endif /* BUZZER_H */
/***************************************************************************//**
* @file
* @brief DMA control data block.
* @author Energy Micro AS
* @version 3.20.0
*******************************************************************************
* @section License
* <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
*******************************************************************************
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
* 4. The source and compiled code may only be used on Energy Micro "EFM32"
* microcontrollers and "EFR4" radios.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
* obligation to support this Software. Energy Micro AS is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Energy Micro AS will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
*****************************************************************************/
#include "em_device.h"
#include "dmactrl.h"
#if ( ( DMA_CHAN_COUNT > 4 ) && ( DMA_CHAN_COUNT <= 8 ) )
#define DMACTRL_CH_CNT 8
#define DMACTRL_ALIGNMENT 256
#elif ( ( DMA_CHAN_COUNT > 8 ) && ( DMA_CHAN_COUNT <= 16 ) )
#define DMACTRL_CH_CNT 16
#define DMACTRL_ALIGNMENT 512
#else
#error "Unsupported DMA channel count (dmactrl.c)."
#endif
/** DMA control block array, requires proper alignment. */
#if defined (__ICCARM__)
#pragma data_alignment=DMACTRL_ALIGNMENT
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT * 2];
#elif defined (__CC_ARM)
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT * 2] __attribute__ ((aligned(DMACTRL_ALIGNMENT)));
#elif defined (__GNUC__)
DMA_DESCRIPTOR_TypeDef dmaControlBlock[DMACTRL_CH_CNT * 2] __attribute__ ((aligned(DMACTRL_ALIGNMENT)));
#else
#error Undefined toolkit, need to define alignment
#endif
/**************************************************************************//**
* @file udelay.h
* @brief Microsecond delay routine.
* @version 3.20.5
/***************************************************************************//**
* @file
* @brief DMA control data block.
* @author Energy Micro AS
* @version 3.20.0
******************************************************************************
* @section License
* <b>(C) Copyright 2014 Silicon Labs, http://www.silabs.com</b>
* <b>(C) Copyright 2012 Energy Micro AS, http://www.energymicro.com</b>
*******************************************************************************
*
* This file is licensensed under the Silabs License Agreement. See the file
* "Silabs_License_Agreement.txt" for details. Before using this software for
* any purpose, you must agree to the terms of that agreement.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
******************************************************************************/
#ifndef __UDELAY_H
#define __UDELAY_H
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
* 4. The source and compiled code may only be used on Energy Micro "EFM32"
* microcontrollers and "EFR4" radios.
*
* DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
* obligation to support this Software. Energy Micro AS is providing the
* Software "AS IS", with no express or implied warranties of any kind,
* including, but not limited to, any implied warranties of merchantability
* or fitness for any particular purpose or warranties against infringement
* of any proprietary rights of a third party.
*
* Energy Micro AS will not be liable for any consequential, incidental, or
* special damages, or any other relief, or for any claim by any third party,
* arising from your use of this Software.
*
*****************************************************************************/
#include <stdint.h>
#ifndef __DMACTRL_H
#define __DMACTRL_H
/***************************************************************************//**
* @addtogroup Drivers
......@@ -25,7 +42,7 @@
******************************************************************************/
/***************************************************************************//**
* @addtogroup Udelay
* @addtogroup DmaCtrl
* @{
******************************************************************************/
......@@ -33,14 +50,13 @@
extern "C" {
#endif
void UDELAY_Calibrate(void);
void UDELAY_Delay(uint32_t usecs);
extern DMA_DESCRIPTOR_TypeDef dmaControlBlock[];
#ifdef __cplusplus
}
#endif
/** @} (end group Udelay) */
/** @} (end group DmaCtrl) */
/** @} (end group Drivers) */
#endif
#endif /* __DMACTRL_H */
This diff is collapsed.
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Bartosz Bielawski <bartosz.bielawski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -29,10 +30,21 @@
#include "em_gpio.h"
#ifdef FREERTOS
#include <FreeRTOS.h>
#include <semphr.h>
///> How long should we wait for the semaphore
#define LCD_SEM_TICKS 100
extern xSemaphoreHandle lcd_sem;
#endif /* FREERTOS */
// Dimensions
#define LCD_HEIGHT 128
#define LCD_WIDTH 128
// Enable 90* rotation
#define LCD_ROTATE_90
// Pinout
#define LCD_PORT_SCLK gpioPortC
#define LCD_PIN_SCLK 4
......@@ -54,9 +66,18 @@
// Peripherals
#define LCD_SPI_UNIT USART2
#define LCD_SPI_CLOCK cmuClock_USART2
#define LCD_SPI_LOCATION 0
#define LCD_SPI_LOCATION USART_ROUTE_LOCATION_LOC0
#define LCD_SPI_BAUDRATE 500000
#define LCD_POL_INV_FREQ 64
#define LCD_POL_INV_FREQ 60
// Additional bytes to control the LCD; stored in framebuffer, required for DMA transfers
#define LCD_CONTROL_BYTES 2
// Number of bytes to store one line
#define LCD_STRIDE (LCD_WIDTH / 8 + LCD_CONTROL_BYTES)
// Framebuffer size (in bytes)
#define LCD_BUF_SIZE (LCD_STRIDE * LCD_HEIGHT + LCD_CONTROL_BYTES)
/**
* @brief LCD initialization routine.
......@@ -91,21 +112,81 @@ void lcd_update(void);
* @param uint8_t y is the y coordinate of the pixel.
* @param uint8_t value turns off the pixel if 0, turns on otherwise.
*/
void lcd_set_pixel(uint8_t x, uint8_t y, uint8_t value);
static inline void lcd_set_pixel(uint8_t x, uint8_t y, uint8_t value)
{
extern uint8_t * const off_buffer;
// x %= LCD_WIDTH;
// y %= LCD_HEIGHT;
#if defined(LCD_ROTATE_90)
uint8_t mask = 0x80 >> (y & 0x07);
uint16_t offset = (x * LCD_STRIDE) + ((LCD_HEIGHT - 1 - y) >> 3);
#elif defined(LCD_ROTATE_270)
uint8_t mask = 1 << (y & 0x07);
uint16_t offset = ((LCD_WIDTH - x - 1) * LCD_STRIDE) + (y >> 3);
#else
uint8_t mask = 1 << (x & 0x07); // == 1 << (x % 8)
uint16_t offset = (y * LCD_STRIDE) + (x >> 3); // == y * LCD_STRIDE + x / 8
#endif
if(value)
off_buffer[offset] |= mask;
else
off_buffer[offset] &= ~mask;
}
/**
* @brief Toggles a single pixel.
* @param uint8_t x is the x coordinate of the pixel.
* @param uint8_t y is the y coordinate of the pixel.
*/
void lcd_toggle_pixel(uint8_t x, uint8_t y);
static inline void lcd_toggle_pixel(uint8_t x, uint8_t y)
{
extern uint8_t * const off_buffer;
// x %= LCD_WIDTH;
// y %= LCD_HEIGHT;
#if defined(LCD_ROTATE_90)
uint8_t mask = 0x80 >> (y & 0x07);
uint16_t offset = (x * LCD_STRIDE) + ((LCD_HEIGHT - 1 - y) >> 3);
#elif defined(LCD_ROTATE_270)
uint8_t mask = 1 << (y & 0x07);
uint16_t offset = ((LCD_WIDTH - x - 1) * LCD_STRIDE) + (y >> 3);
#else
uint8_t mask = 1 << (x & 0x07); // == 1 << (x % 8)
uint16_t offset = (y * LCD_STRIDE) + (x >> 3); // == y * LCD_STRIDE + x / 8
#endif
off_buffer[offset] ^= mask;
}
/**
* @brief Returns the state of a single pixel.
* @param uint8_t x is the x coordinate of the pixel.
* @param uint8_t y is the y coordinate of the pixel.
*/
uint8_t lcd_get_pixel(uint8_t x, uint8_t y);
static inline uint8_t lcd_get_pixel(uint8_t x, uint8_t y)
{
extern uint8_t * const off_buffer;
// x %= LCD_WIDTH;
// y %= LCD_HEIGHT;
#if defined(LCD_ROTATE_90)
uint8_t mask = 0x80 >> (y & 0x07);
uint16_t offset = (x * LCD_STRIDE) + ((LCD_HEIGHT - 1 - y) >> 3);
#elif defined(LCD_ROTATE_270)
uint8_t mask = 1 << (y & 0x07);
uint16_t offset = ((LCD_WIDTH - x - 1) * LCD_STRIDE) + (y >> 3);
#else
uint8_t mask = 1 << (x & 0x07); // == 1 << (x % 8)
uint16_t offset = (y * LCD_STRIDE) + (x >> 3); // == y * LCD_STRIDE + x / 8
#endif
return off_buffer[offset] & mask;
}
#endif /* LCD_H */
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Bartosz Bielawski <bartosz.bielawski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "em_device.h"
#include "em_dma.h"
#include "em_emu.h"
#include "em_ebi.h"
#include "em_cmu.h"
#include "em_usart.h"
#include "dmactrl.h"
#include "lcd.h"
#include "lcd_dma.h"
// The DMA channel to use
#define DMA_CHANNEL 0
// Number of DMA transfers
#define DMA_TRANSFERS 3
// Framebuffer to be drawn
extern uint8_t lcd_buffer[LCD_BUF_SIZE];
// Stores pointer to the function called after transfers are finished
DMA_CB_TypeDef dma_callback;
// Configuration structures for two halves of the screen
DMA_DESCRIPTOR_TypeDef dma_cfg_block[DMA_TRANSFERS];
// Flag to indicate DMA state
volatile bool dma_transfer_active = false;
// Called by DMA when transfer is complete
static void lcd_dma_tx_complete(unsigned int channel, bool primary, void *user)
{
(void) channel; // suppress warnings
(void) primary;
(void) user;
dma_transfer_active = false;
#ifdef FREERTOS
xSemaphoreGive(lcd_sem);
#endif /* FREERTOS */
}
void lcd_dma_init(void)
{
DMA_Init_TypeDef dma_init;
DMA_CfgChannel_TypeDef channel_config;
DMA_CfgDescrSGAlt_TypeDef descriptor_config;
CMU_ClockEnable(cmuClock_DMA, true);
dma_init.hprot = 0;
dma_init.controlBlock = dmaControlBlock;
DMA_Init(&dma_init);
// Setting callback function
dma_callback.cbFunc = lcd_dma_tx_complete;
dma_callback.userPtr = NULL;
// Setting up channel
channel_config.highPri = false; // No high priority
channel_config.enableInt = true; // Enable interrupt
channel_config.select = DMAREQ_USART2_TXBL;
channel_config.cb = &dma_callback; // Callback routine
DMA_CfgChannel(DMA_CHANNEL, &channel_config);
// Setting up channel descriptor
descriptor_config.dstInc = dmaDataIncNone;
descriptor_config.srcInc = dmaDataInc1;
descriptor_config.size = dmaDataSize1;
descriptor_config.arbRate = dmaArbitrate1;
descriptor_config.hprot = 0;
descriptor_config.peripheral = true;
descriptor_config.dst = (void *)&(LCD_SPI_UNIT->TXDATA);
// Lines 0-42
descriptor_config.src = &lcd_buffer[0];
descriptor_config.nMinus1 = LCD_STRIDE * 43 - 1;
DMA_CfgDescrScatterGather(dma_cfg_block, 0, &descriptor_config);
// Lines 43-85
descriptor_config.src = &lcd_buffer[LCD_STRIDE * 43];
descriptor_config.nMinus1 = LCD_STRIDE * 43 - 1;
DMA_CfgDescrScatterGather(dma_cfg_block, 1, &descriptor_config);
// Lines 86-128
descriptor_config.src = &lcd_buffer[LCD_STRIDE * 86];
descriptor_config.nMinus1 = LCD_STRIDE * 43 - 1;
DMA_CfgDescrScatterGather(dma_cfg_block, 2, &descriptor_config);
dma_transfer_active = false;
}
void lcd_dma_send_frame(void)
{
#ifdef FREERTOS
if(xSemaphoreTake(lcd_sem, LCD_SEM_TICKS) != pdTRUE)
return;
#else
while(dma_transfer_active);
#endif /* else FREERTOS */
dma_transfer_active = true;
DMA_ActivateScatterGather(DMA_CHANNEL, true, dma_cfg_block, DMA_TRANSFERS);
// semaphore is given back in the DMA transfer finished interrupt
}
bool lcd_dma_is_active(void)
{
return dma_transfer_active;
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Bartosz Bielawski <bartosz.bielawski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
// TODO author note
#ifndef LCD_DMA_H
#define LCD_DMA_H
/**
* Initialize DMA operation.
* Enables the clock and sets up descriptors and
* registers for dma frame buffer transfer.
*/
void lcd_dma_init(void);
/**
* TODO
*/
void lcd_dma_send_frame(void);
/**
* TODO
*/
bool lcd_dma_is_active(void);
#endif /* LCD_DMA_H */
/*
* Copyright (C) 2014 Julian Lewis
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -25,13 +26,10 @@
*/
#include "light_sensor.h"
#include <math.h>
#include <stdio.h>
#include "i2cdrv.h"
// Writes a register
uint8_t max44009_write_reg(uint8_t reg_add, uint8_t value)
static uint8_t max44009_write_reg(uint8_t reg_add, uint8_t value)
{
I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret;
......@@ -57,9 +55,8 @@ uint8_t max44009_write_reg(uint8_t reg_add, uint8_t value)
return 0;
}
// Reads a register
uint8_t max44009_read_reg(uint8_t reg_add, uint8_t* value)
static uint8_t max44009_read_reg(uint8_t reg_add, uint8_t *value, uint8_t length)
{
I2C_TransferSeq_TypeDef seq;
I2C_TransferReturn_TypeDef ret;
......@@ -73,7 +70,7 @@ uint8_t max44009_read_reg(uint8_t reg_add, uint8_t* value)
// Read value in buffer
seq.buf[1].data = value;
seq.buf[1].len = 1;
seq.buf[1].len = length;
// Initiate transfer
ret = I2CDRV_Transfer(&seq);
......@@ -85,73 +82,72 @@ uint8_t max44009_read_reg(uint8_t reg_add, uint8_t* value)
return 0;
}
uint8_t light_sensor_set_int(uint8_t enable)
/*uint8_t light_sensor_set_int(uint8_t enable)
{
return 0;
}
uint8_t light_sensor_get_isr(uint8_t* isr)
{
return 0;
}
uint8_t light_sensor_set_cfg(Light_Sensor_Conf_TypeDef *cfg)
{
return 0;
}*/
///> Converts 16-bit raw register value (registers 3 & 4) to millilux.
static uint32_t raw16_to_lux(uint16_t val)
{
uint8_t e = (val & 0xf000) >> 12; // exponent
uint8_t m = ((val & 0x0f00) >> 4) | (val & 0x0f); // mantissa
return (1 << e) * m * 45;
}
///> Converts 8-bit raw register value (register 3) to millilux.
static uint32_t raw8_to_lux(uint8_t val)
{
uint8_t e = (val >> 4); // exponent
uint8_t m = (val & 0x0f); // mantissa
uint8_t light_sensor_get_lux(double* lux)
return (1 << e) * m * 720;
}
uint8_t light_sensor_get_raw(uint16_t *val)
{
uint8_t err, high_b, low_b, m, e;
/* TODO
* For accurate reading, high and low registers have to
* be read during the same i2c transfer.
* => Apparently not possible with the current i2cdrvr!
*
* For now, only read high byte
*/
// Read Lux registers high byte
err = max44009_read_reg(MAX44009_REG_LUX_H, &high_b);
if(err)
{
return err;
}
uint8_t err;
// Read Lux registers
err = max44009_read_reg(MAX44009_REG_LUX_H, (uint8_t*)val, 2);
/*
// Read Lux register low byte
err = max44009_read_reg(MAX44009_REG_LUX_L, &low_b);
if(err)
{
return err;
}
*/
// Extract mantissa and exponent
m = high_b & 0xff;
//m = ((high_b & 0xff) << 4) + (low_b & 0xff);
e = ((high_b & 0xff00) >> 4);
return 0;
}
uint8_t light_sensor_get_lux(uint32_t *lux)
{
uint16_t raw;
uint8_t ret = light_sensor_get_raw(&raw);
if(ret != 0)
return ret; // error, no more processing
// Calculate Lux value
*lux = pow(2,(double) e) * m * 0.72;
//*lux = pow(2,(double) e) * m * 0.045;
*lux = raw16_to_lux(raw);
return 0;
}
uint8_t light_sensor_set_thres(double thres)
/*uint8_t light_sensor_set_thres(double thres)
{
return 0;
}
uint8_t light_sensor_set_thres_timer(uint8_t timer)
{
return 0;
}
}*/
/*
* Copyright (C) 2014 Julian Lewis
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -50,7 +51,7 @@
#define MAX44009_CFG_TIM 0x07 // Integration time
/** Ambient light sensor configuration structure. */
typedef struct
/*typedef struct
{
bool cont;
bool manual;
......@@ -61,10 +62,23 @@ typedef struct
uint8_t light_sensor_set_int(uint8_t enable);
uint8_t light_sensor_get_isr(uint8_t* isr);
uint8_t light_sensor_set_cfg(Light_Sensor_Conf_TypeDef *cfg);
uint8_t light_sensor_get_lux(double* lux);
uint8_t light_sensor_set_thres(double thres);
uint8_t light_sensor_set_thres_timer(uint8_t timer);
uint8_t light_sensor_set_cfg(Light_Sensor_Conf_TypeDef *cfg);*/
/**
* Returns raw reading from the light sensor.
* @param val is the place where the reading will be stored.
* @return 0 in case of success, error code otherwise.
*/
uint8_t light_sensor_get_raw(uint16_t* val);
/**
* Returns light level expressed in millilux.
* @param lux is the variable where the computed value will be stored.
* @return 0 in case of success, error code otherwise.
*/
uint8_t light_sensor_get_lux(uint32_t *lux);
/*uint8_t light_sensor_set_thres(double thres);
uint8_t light_sensor_set_thres_timer(uint8_t timer);*/
#endif /* LIGHT_SENSOR_H */
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Vibration motor control.
*/
#include "vibra.h"
#include <em_cmu.h>
#include <em_gpio.h>
#define VIBRA_PORT gpioPortA
#define VIBRA_PIN 3
void vibra_init(void)
{
GPIO_PinModeSet(VIBRA_PORT, VIBRA_PIN, gpioModePushPull, 0);
}
void vibra_enable(void)
{
GPIO_PinOutSet(VIBRA_PORT, VIBRA_PIN);
}
void vibra_disable(void)
{
GPIO_PinOutClear(VIBRA_PORT, VIBRA_PIN);
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -21,15 +22,26 @@
*/
/**
* Clock application.
* @brief Vibration motor control.
*/
#ifndef CLOCK_H
#define CLOCK_H
#ifndef VIBRA_H
#define VIBRA_H
#include "application.h"
/**
* @brief Initialize vibration motor.
*/
void vibra_init(void);
extern application clock;
/**
* @brief Turns on the vibration motor.
*/
void vibra_enable(void);
/**
* @brief Turns off the vibration motor.
*/
void vibra_disable(void);
#endif /* CLOCK_H */
#endif /* VIBRA_H */
......@@ -32,7 +32,7 @@
*/
enum event_type {
BUTTON_PRESSED,
SENSOR,
SENSOR_INT,
RTC_TICK
};
......@@ -46,6 +46,15 @@ enum button_name {
BUT_BR // bottom right
};
/**
* Sensor interrupts.
*/
enum sensor_type {
// LIGHT, // disabled for the time being
MAGNETOMETER,
ACCELEROMETER
};
/**
* Structure describing events received by applications.
*/
......@@ -56,6 +65,7 @@ struct event {
///> Data dependent on the event type
union {
enum button_name button;
enum sensor_type sensor;
} data;
};
......
/*
* Copyright (C) 2014 Julian Lewis
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -39,7 +40,7 @@ void *gfx_alloc(int count)
count /= 4; // align to 32 bits
if(count + gfx_pool_pos >= GFX_POOL_SIZE)
return NULL;
return NULL;
void *p = gfx_pool_mem + gfx_pool_pos;
gfx_pool_pos += count;
......@@ -235,25 +236,25 @@ void gfx_round_box(struct surface *surf, int x0, int y0, int x1, int y1,
void gfx_draw_bitmap(struct surface *surf, int x0, int y0, const struct rle_bitmap *b)
{
int x=0, y=0;
uint8_t *d = b->data;
while ( y != b->h)
{
int pix = (*d) & 0x80 ? 1: 0;
int rep = ( (*d) & 0x7f) + 1;
d++;
while(rep--)
{
if(pix)
gfx_set_pixel(surf, x0+x, y0+y, COLOR_BLACK);
x++;
if(x == b->w)
{
x=0;
y++;
}
}
}
int x = 0, y = 0;
const uint8_t *d = b->data;
while(y != b->h)
{
int pix = (*d) & 0x80 ? 1 : 0;
int rep = ((*d) & 0x7f) + 1;
d++;
while(rep--)
{
if(pix)
gfx_set_pixel(surf, x0 + x, y0 + y, COLOR_BLACK);
x++;
if(x == b->w)
{
x=0;
y++;
}
}
}
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -24,6 +25,7 @@
#define __GFX_H
#include "font.h"
#include "bitmaps.h"
#define MIN(a,b) ((a)<(b)?(a):(b))
#define MAX(a,b) ((a)>(b)?(a):(b))
......@@ -44,23 +46,16 @@ struct surface
void *data;
};
struct rle_bitmap
static inline void gfx_set_pixel(struct surface *surf, int x, int y, int value)
{
uint8_t w;
uint8_t h;
uint8_t *data;
};
static inline void gfx_set_pixel(struct surface *surf, int x, int y, int value)
{
if(x < surf->clip.x0 || x > surf->clip.x1 ||
if(x < surf->clip.x0 || x > surf->clip.x1 ||
y < surf->clip.y0 || y > surf->clip.y1)
return;
x += surf->client_x;
y += surf->client_y;
uint8_t mask = 1 << (x & 0x07);
uint8_t mask = 1 << (x & 0x07);
uint8_t *p = surf->data + (y * surf->stride) + (x >> 3);
if(value == COLOR_BLACK)
......
/*
* Copyright (C) 2014 Julian Lewis
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
* @author Tomasz Wlostowski <tomasz.wlostowski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -65,11 +65,11 @@ void ui_add_widget(struct ui_widget *w) {
}
if(!(w->flags & WF_DOUBLE_BUFFER)) {
gfx_init_surface(&w->dc, &screen, w->pos.x0, w->pos.y0,
gfx_init_surface(&w->dc, &screen, w->pos.x0, w->pos.y0,
w->pos.x1 - w->pos.x0 + 1, w->pos.y1 - w->pos.y0 + 1);
}
else {
DBG("NonImpl\n");
// DBG("NonImpl\n");
}
w->flags |= WF_DIRTY;
......
This diff is collapsed.
......@@ -95,8 +95,8 @@ DEPFLAGS = -MMD -MP -MF $(@:.o=.d)
#
override CFLAGS += -D$(DEVICE) -Wall -Wextra -mcpu=cortex-m3 -mthumb \
-mfix-cortex-m3-ldrd -ffunction-sections \
-fdata-sections -fomit-frame-pointer -DGCC_ARMCM3 -DDEBUG_EFM \
$(DEPFLAGS)
-fdata-sections -fomit-frame-pointer -DGCC_ARMCM3 \
-DFREERTOS $(DEPFLAGS)
override ASMFLAGS += -x assembler-with-cpp -D$(DEVICE) -Wall -Wextra -mcpu=cortex-m3 -mthumb
......@@ -107,11 +107,12 @@ override LDFLAGS += -Xlinker -Map=$(LST_DIR)/$(PROJECTNAME).map -mcpu=cortex-m3
-mthumb -T../common/Device/EnergyMicro/EFM32GG/Source/GCC/efm32gg.ld \
-Wl,--gc-sections
LIBS = -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
LIBS = -Wl,--start-group -lgcc -lc -lnosys -Wl,--end-group
INCLUDEPATHS += \
-Isrc \
-IFreeRTOS/Source/include \
-I../bitmaps \
-I../common/CMSIS/Include \
-I../common/Device/EnergyMicro/EFM32GG/Include \
-I../common \
......@@ -123,21 +124,32 @@ INCLUDEPATHS += \
####################################################################
C_SRC += \
../bitmaps/bitmaps.c \
../common/Device/EnergyMicro/EFM32GG/Source/system_efm32gg.c \
../common/emlib/src/em_assert.c \
../common/emlib/src/em_burtc.c \
../common/emlib/src/em_cmu.c \
../common/emlib/src/em_dma.c \
../common/emlib/src/em_emu.c \
../common/emlib/src/em_gpio.c \
../common/emlib/src/em_i2c.c \
../common/emlib/src/em_int.c \
../common/emlib/src/em_rmu.c \
../common/emlib/src/em_rtc.c \
../common/emlib/src/em_system.c \
../common/emlib/src/em_timer.c \
../common/emlib/src/em_usart.c \
../common/emdrv/sleep/src/sleep.c \
../common/drivers/dmactrl.c \
../common/drivers/lcd.c \
../common/drivers/lcd_dma.c \
../common/drivers/backlight.c \
../common/drivers/buttons.c \
../common/drivers/buzzer.c \
../common/drivers/i2cdrv.c \
../common/drivers/light_sensor.c \
../common/drivers/rtc.c \
../common/drivers/vibra.c \
../common/gfx/font_helv11.c \
../common/gfx/font_helv17.c \
../common/gfx/font_helv17b.c \
......@@ -152,7 +164,6 @@ C_SRC += \
../common/gfx/graphics.c \
../common/gfx/gfx.c \
../common/gfx/ui.c \
../common/udelay.c \
FreeRTOS/Source/timers.c \
FreeRTOS/Source/tasks.c \
FreeRTOS/Source/queue.c \
......@@ -163,13 +174,16 @@ FreeRTOS/Source/portable/GCC/ARM_CM3/port.c \
src/apps/widgets/status_bar.c \
src/apps/application.c \
src/apps/clock.c \
src/apps/example_app.c \
src/apps/menu.c \
src/apps/menu_struct.c \
src/main.c \
src/blight_task.c \
src/irq_dispatcher.c \
src/low_power_tick_management.c
src/low_power_tick_management.c \
src/state.c
s_SRC +=
s_SRC +=
S_SRC += \
../common/Device/EnergyMicro/EFM32GG/Source/GCC/startup_efm32gg.S
......@@ -197,10 +211,10 @@ vpath %.S $(S_PATHS)
# Default build is debug build
all: debug
debug: CFLAGS += -DDEBUG -O0 -g
debug: CFLAGS += -DDEBUG -O0 -g -DDEBUG_EFM
debug: $(EXE_DIR)/$(PROJECTNAME).bin
release: CFLAGS += -DNDEBUG -O3
release: CFLAGS += -DNDEBUG -O3
release: $(EXE_DIR)/$(PROJECTNAME).bin
# Create objects from C SRC files
......
......@@ -21,15 +21,17 @@
*/
/**
* Menu application.
* List of applications.
*/
#ifndef MENU_H
#define MENU_H
#ifndef APP_LIST_H
#define APP_LIST_H
#include "application.h"
extern application menu;
extern application clock_app;
extern application example;
#endif /* MENU_H */
#endif /* APP_LIST_H */
......@@ -44,13 +44,11 @@ typedef struct {
///> Application name
const char* name;
// TODO const char* icon;
/**
* @brief Main application routine.
* @params Optional parameters, dependendent on application.
*/
void (*main)(void* params);
void (*main)(void* params);
} application;
/**
......
......@@ -25,45 +25,39 @@
* Clock application.
*/
#include "clock.h"
#include "application.h"
#include "widgets/status_bar.h"
#include <drivers/rtc.h>
#include <stdio.h>
#include <time.h>
static unsigned int hour, mins, secs, msecs;
static struct rtc_time rtc;
static struct tm cur_time;
static void digital_watch_redraw(struct ui_widget *w)
{
char buf[20];
sprintf(buf,"%02d:%02d", hour, mins);
char buf[32];
strftime(buf, sizeof(buf), "%H:%M", &cur_time);
/*sprintf(buf,"%02d:%02d", cur_time.tm_hour, cur_time.tm_min);*/
gfx_clear(&w->dc, 0);
gfx_text(&w->dc, &font_helv38b, 0, 0, buf, 1);
gfx_text(&w->dc, &font_helv38b, 4, 0, buf, 1);
sprintf(buf,"%02d.%01d", secs, msecs / 100);
gfx_text(&w->dc, &font_helv22b, 84, 14, buf, 1);
// sprintf must be used, so we can display msecs too
sprintf(buf, "%02d.%01d", cur_time.tm_sec, rtc.msecs / 100);
gfx_text(&w->dc, &font_helv22b, 88, 14, buf, 1);
strftime(buf, sizeof(buf), "%a %d %b %Y", &cur_time);
gfx_centered_text(&w->dc, &font_helv17, 40, buf, 1);
}
static void digital_watch_event(struct ui_widget *w, const struct event *evt)
{
// Hour has changed, it is time to redraw the clock
if(evt->type == RTC_TICK) {
msecs += 200;
if(1000 == msecs) {
++secs;
msecs = 0;
}
++secs;
if(60 == secs) {
++mins; secs = 0;
if(60 == mins) {
++hour; mins = 0;
if(24 == hour)
hour = 0; // TODO 12/24 hour format
}
}
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
w->flags |= WF_DIRTY;
}
......@@ -72,7 +66,7 @@ static void digital_watch_event(struct ui_widget *w, const struct event *evt)
struct ui_widget digital_watch = {
digital_watch_redraw,
digital_watch_event,
{ 0, 20, 127, 59 },
{ 0, 35, 127, 35 + 53 },
0,
WF_ACTIVE | WF_VISIBLE
};
......@@ -90,14 +84,8 @@ void clock_main(void* params) {
struct event evt;
// Restore clock
struct rtc_time time = rtc_get_time();
msecs = time.msecs;
secs = time.epoch;
mins = secs / 60;
hour = mins / 60;
secs %= 60;
mins %= 60;
hour %= 24;
rtc = rtc_get_time();
localtime_r((time_t*) &rtc.epoch, &cur_time);
// Initialize user interface
ui_clear();
......@@ -135,7 +123,7 @@ void clock_main(void* params) {
}
}
application clock = {
application clock_app = {
.name = "Clock",
.main = clock_main
};
......
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* Application template.
*/
#include "application.h"
#include "widgets/status_bar.h"
#include "drivers/backlight.h"
#include "drivers/buzzer.h"
#include "drivers/vibra.h"
#include <string.h> // for strcpy
static char message[32] = "hello world";
static void widget_redraw(struct ui_widget *w)
{
gfx_clear(&w->dc, 0);
gfx_text(&w->dc, &font_helv17b, 0, 0, message, 1);
}
static void widget_event(struct ui_widget *w, const struct event *evt)
{
// screen needs redrawing
w->flags |= WF_DIRTY;
switch(evt->type) {
case BUTTON_PRESSED:
switch(evt->data.button) {
case BUT_TR: // top right button
backlight_set_level(backlight_get_level() + 10);
sprintf(message, "top right (bl: %d)", backlight_get_level());
break;
case BUT_BR: // bottom right button
backlight_set_level(backlight_get_level() - 10);
sprintf(message, "bot right (bl: %d)", backlight_get_level());
break;
case BUT_BL: // bottom left button
strcpy(message, "bot left");
break;
case BUT_TL: // this should not happen, it is handled
break; // in the main loop
}
// short vibration
vibra_enable();
vTaskDelay(100);
vibra_disable();
break;
case RTC_TICK:
// tick-tock with a buzzer
buzzer_enable();
vTaskDelay(100);
buzzer_disable();
// ok, we do not need redrawing
w->flags &= ~WF_DIRTY;
break;
default: // suppress warnings
// ok, we do not need redrawing
w->flags &= ~WF_DIRTY;
break;
}
}
struct ui_widget widget = {
widget_redraw, // drawing function, called when widget is marked as dirty
widget_event, // event handler
{ 0, 20, 127, 59 }, // dimensions
0, // surface pointer; do not change
WF_ACTIVE | WF_VISIBLE // flags
};
struct ui_widget example_screen = { // main screen, contains all widgets
NULL,
NULL,
{ 0, 0, 127, 127 },
0,
WF_ACTIVE | WF_VISIBLE
};
void example_main(void* params) {
(void)(params); // suppress unused parameter warning
struct event evt;
// this is a good place for hardware initialization
// (configure interrupts, backlight settings, etc.)
// initialize user interface
ui_clear();
// initialize widgets before adding them
ui_init_widget(&example_screen);
ui_init_widget(&widget);
ui_add_widget(&widget);
// widget belongs to the main screen
ui_add_child(&example_screen, &widget);
ui_add_widget(&example_screen);
// if you want to have fullscreen just for you
// commenting the lines below will disable the status bar
ui_init_widget(&status_bar);
ui_add_widget(&status_bar);
// draw the screen for the first time
ui_update(NULL);
// event loop
while(1) {
// "0" in the line below, if you set it to a positive value then
// you may have a block of code that is executed when no event arrives
// for details, see below (else block)
if(xQueueReceive(appQueue, &evt, 0)) {
switch(evt.type) {
// decide which events are relevant and should be handled
// you may save some cycles if you list them here instead of
// lazily handling all of them
case BUTTON_PRESSED:
// current convention is to use the top left button to go back
if(evt.data.button == BUT_TL)
return; // go back to the main menu
// no break; fall through
case RTC_TICK: // there was no break, it handles BUTTON_PRESSED too
ui_update(&evt); // forward event to widgets
default: // suppress warnings
// ignore events that were not mentioned above
break;
}
}
else {
// that part is executed if timeout occurs
}
}
}
application example = {
.name = "Example", // this will be shown in menu
.main = example_main
};
......@@ -24,19 +24,19 @@
* Menu application.
*/
#include "menu.h"
#include "app_list.h"
#include "menu_struct.h"
#include "clock.h"
#include "widgets/status_bar.h"
static int selected_item = 0;
static int offset = 0;
static int menu_size = 0;
#define LINE_HEIGHT 17
#define LEFT_MARGIN 17
#define MENU_SCREEN_HEIGHT 107
#define MAX_ENTRIES (MENU_SCREEN_HEIGHT / LINE_HEIGHT)
#define LINE_HEIGHT 17
#define LEFT_MARGIN 17
#define MENU_SCREEN_HEIGHT 107
#define MENU_SCREEN_WIDTH 127
#define MAX_ENTRIES (MENU_SCREEN_HEIGHT / LINE_HEIGHT)
// store menu states to navigate between menus
static menu_list *menu_stack[8] = { &main_menu, NULL, };
......@@ -55,13 +55,16 @@ static void menu_screen_redraw(struct ui_widget *w)
// draw a white background for the selected entry
if(pos == selected_item) {
gfx_box(&w->dc, LEFT_MARGIN, i * LINE_HEIGHT,
127, (i + 1) * LINE_HEIGHT, 1);
MENU_SCREEN_WIDTH, (i + 1) * LINE_HEIGHT, 1);
}
// TODO draw icon
menu_entry *ent = &(*current_menu)->entries[pos];
// draw icon
if(ent->icon)
gfx_draw_bitmap(&w->dc, 0, i * LINE_HEIGHT, ent->icon);
// display label (either app or submenu)
menu_entry *ent = &(*current_menu)->entries[pos];
if(ent->type == APP) {
application *a = ent->data.app;
......@@ -84,7 +87,7 @@ static void menu_screen_event(struct ui_widget *w, const struct event *evt)
if(selected_item < menu_size - 1) {
++selected_item;
if(selected_item >= MAX_ENTRIES)
if(selected_item >= offset + MAX_ENTRIES)
offset = selected_item - MAX_ENTRIES + 1;
w->flags |= WF_DIRTY;
......@@ -105,7 +108,8 @@ static void menu_screen_event(struct ui_widget *w, const struct event *evt)
struct ui_widget menu_screen = {
menu_screen_redraw,
menu_screen_event,
{ 0, 20, 127, 20 + MENU_SCREEN_HEIGHT },
{ 0, STATUS_BAR_HEIGHT,
MENU_SCREEN_WIDTH, STATUS_BAR_HEIGHT + MENU_SCREEN_HEIGHT },
0,
WF_ACTIVE | WF_VISIBLE
};
......@@ -141,7 +145,7 @@ static void run(menu_entry *entry) {
static void go_back() {
if(current_menu == menu_stack) {
clock.main(NULL);
clock_app.main(NULL);
} else {
menu_size = 0;
selected_item = 0;
......@@ -160,7 +164,7 @@ void menu_main(void* params) {
menu_size = get_menu_size(*current_menu);
// run clock as the the initial application
clock.main(NULL);
clock_app.main(NULL);
menu_ui_init();
// Once it is deactivated - display the menu
......
......@@ -25,7 +25,7 @@
*/
#include "menu_struct.h"
#include "clock.h"
#include "app_list.h"
int get_menu_size(const menu_list *menu) {
int len = 0;
......@@ -40,34 +40,35 @@ int get_menu_size(const menu_list *menu) {
menu_list sub_menu = {
"Submenu",
{
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ END, { NULL } }
{ APP, &gps_receiving, { .app = &clock_app } },
{ APP, &battery, { .app = &clock_app } },
{ APP, &gps_disconnected, { .app = &clock_app } },
{ END, &gps_searching, { NULL } }
}
};
menu_list main_menu = {
"Main menu",
{
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ SUBMENU, { .submenu = &sub_menu } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ SUBMENU, { .submenu = &sub_menu } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ SUBMENU, { .submenu = &sub_menu } },
{ SUBMENU, { .submenu = &sub_menu } },
{ SUBMENU, { .submenu = &sub_menu } },
{ APP, { .app = &clock } },
{ APP, { .app = &clock } },
{ END, { NULL } }
{ APP, &example_icon, { .app = &example } },
{ APP, &gps_receiving, { .app = &clock_app } },
{ APP, &battery_charging, { .app = &clock_app } },
{ SUBMENU, NULL, { .submenu = &sub_menu } },
{ APP, &battery, { .app = &clock_app } },
{ APP, NULL, { .app = &clock_app } },
{ APP, &gps_disconnected, { .app = &clock_app } },
{ APP, NULL, { .app = &clock_app } },
{ SUBMENU, &battery_charging, { .submenu = &sub_menu } },
{ APP, NULL, { .app = &clock_app } },
{ APP, NULL, { .app = &clock_app } },
{ APP, NULL, { .app = &clock_app } },
{ APP, NULL, { .app = &clock_app } },
{ SUBMENU, NULL, { .submenu = &sub_menu } },
{ SUBMENU, NULL, { .submenu = &sub_menu } },
{ SUBMENU, NULL, { .submenu = &sub_menu } },
{ APP, NULL, { .app = &clock_app } },
{ APP, NULL, { .app = &clock_app } },
{ END, NULL, { NULL } }
}
};
......@@ -28,6 +28,7 @@
#define MENU_STRUCT_H
#include "application.h"
#include "bitmaps.h"
/**
* @brief Type of menu entry.
......@@ -45,6 +46,8 @@ enum entry_type {
typedef struct menu_entry_t {
enum entry_type type;
const struct rle_bitmap *icon;
union {
application *app;
struct menu_list_t *submenu;
......
......@@ -34,7 +34,7 @@ static void status_bar_event(struct ui_widget *w, const struct event *evt)
static void status_bar_redraw(struct ui_widget *w)
{
gfx_round_box(&w->dc, 30, -10, 127-30, 10, 9, COLOR_BLACK);
gfx_round_box(&w->dc, 30, -10, 127 - 30, 10, 9, COLOR_BLACK);
gfx_centered_text(&w->dc, &font_helv11, 0, "Home", 1);
}
......
......@@ -27,5 +27,8 @@
#include <gfx/ui.h>
///> Height of the status bar
#define STATUS_BAR_HEIGHT 20
struct ui_widget status_bar;
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Automatic backlight regulation.
*/
#include "blight_task.h"
#include <FreeRTOS.h>
#include <timers.h>
#include <inttypes.h>
#include <drivers/backlight.h>
#include <drivers/light_sensor.h>
///> Number of ticks between backlight adjustments
#define BLIGHT_TASK_PERIOD 3000
///> Entry that stores an appropriate backlight level value
///> depending on the light sensor readings.
static const struct {
uint16_t lux;
uint16_t level;
} blight_lut[] = {
{ 500, 100 },
{ 2000, 90 },
{ 4000, 80 },
{ 10000, 60 },
{ 20000, 30 },
{ 65535, 0 }
};
///> Number of pairs
const int blight_lut_size = sizeof(blight_lut) / sizeof(blight_lut[0]);
///> Current state
static bool auto_enabled = false;
///> Timer handle
static xTimerHandle timer_handle;
///> Currently used index in the lookup table
static int8_t cur_idx = -1;
static void auto_backlight_task(void *params)
{
(void) params;
uint32_t lux;
if(!light_sensor_get_lux(&lux)) {
// Look for the right value
uint8_t index;
for(index = 0; index < blight_lut_size; ++index) {
if(lux < blight_lut[index].lux)
break;
}
// Change the backlight level if it is different than the previous one
if(index != cur_idx) {
backlight_set_level(blight_lut[index].level);
cur_idx = index;
}
}
}
void auto_backlight_init(void)
{
timer_handle = xTimerCreate((signed char*) "auto_blight",
BLIGHT_TASK_PERIOD, pdTRUE,
(void*) 0, auto_backlight_task);
}
void auto_backlight_enable(bool enable)
{
if(enable == auto_enabled)
return;
if(enable) {
if(xTimerStart(timer_handle, 0) != pdPASS) {
// TODO kernel panic
}
// Select appropriate backlight level
auto_backlight_task(NULL);
} else {
xTimerStop(timer_handle, 0);
cur_idx = -1;
}
auto_enabled = enable;
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Automatic backlight regulation.
*/
#ifndef BLIGHT_TASK_H
#define BLIGHT_TASK_H
#include <stdbool.h>
/**
* Initializes the automatic backlight adjustment task.
*/
void auto_backlight_init(void);
/**
* Enables/disables automatic backlight adjustment.
* @param enable decides if the automatic regulation should be enabled.
* Note that you are still able to change the backlight level manually, but
* it will be overridden next time the automatic adjustment task is
* executed.
*/
void auto_backlight_enable(bool enable);
#endif /* BLIGHT_TASK_H */
......@@ -33,29 +33,68 @@
#include <em_gpio.h>
#include <em_burtc.h>
#include "state.h"
static portBASE_TYPE gpio_irq_dispatcher(uint32_t flags)
{
// We have not woken a task at the start of the ISR
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
portBASE_TYPE task_woken1 = pdFALSE;
portBASE_TYPE task_woken2 = pdFALSE;
// Fill the event data
struct event evt;
evt.type = BUTTON_PRESSED;
switch(flags)
{
case 0x01: evt.data.button = BUT_BL; break;
case 0x40: evt.data.button = BUT_TR; break;
case 0x80: evt.data.button = BUT_BR; break;
case 0x0100: evt.data.button = BUT_TL; break;
// Buttons
case (1 << 0): // PA0
evt.type = BUTTON_PRESSED;
evt.data.button = BUT_TR;
break;
case (1 << 6): // PC6
evt.type = BUTTON_PRESSED;
evt.data.button = BUT_BL;
break;
case (1 << 7): // PC7
evt.type = BUTTON_PRESSED;
evt.data.button = BUT_TL;
break;
case (1 << 8): // PA8
evt.type = BUTTON_PRESSED;
evt.data.button = BUT_BR;
break;
// Sensors
// There is a conflict with the bottom-left button interrupt
// case (1 << 6): // PA6
// evt.type = SENSOR_INT;
// evt.data.sensor = LIGHT;
// break;
case (1 << 10): // PA10
evt.type = SENSOR_INT;
evt.data.sensor = MAGNETOMETER;
break;
case (1 << 5): // PD5
evt.type = SENSOR_INT;
evt.data.sensor = ACCELEROMETER;
break;
// Unexpected event, do not send it
default: return xHigherPriorityTaskWoken;
default: return pdFALSE;
}
// Post the event to the back of the queue
xQueueSendToBackFromISR(appQueue, &evt, &xHigherPriorityTaskWoken);
xQueueSendToBackFromISR(appQueue, &evt, &task_woken1);
// Switch to active state if a button was pressed
if(evt.type == BUTTON_PRESSED)
reset_active_irq(&task_woken2);
return xHigherPriorityTaskWoken;
return task_woken1 || task_woken2;
}
void GPIO_EVEN_IRQHandler(void)
......
......@@ -29,11 +29,18 @@
#include <em_cmu.h>
#include <sleep.h>
#include <apps/menu.h>
#include <drivers/i2cdrv.h>
#include <drivers/backlight.h>
#include <drivers/buttons.h>
#include <drivers/buzzer.h>
#include <drivers/lcd.h>
#include <drivers/rtc.h>
#include <drivers/vibra.h>
#include <gfx/ui.h>
#include <apps/app_list.h>
#include "blight_task.h"
#include "state.h"
int main(void)
{
......@@ -44,13 +51,18 @@ int main(void)
CMU_ClockEnable(cmuClock_HFPER, true);
CMU_ClockEnable(cmuClock_GPIO, true);
I2C_Init_TypeDef i2cInit = I2C_INIT_DEFAULT;
I2CDRV_Init(&i2cInit);
backlight_init();
buttons_init();
buzzer_init();
vibra_init();
rtc_init();
lcd_init();
ui_init();
GPIO_PinModeSet(gpioPortE, 11, gpioModePushPull, 0);
GPIO_PinModeSet(gpioPortE, 12, gpioModePushPull, 0);
auto_backlight_init();
state_init();
// Initialize SLEEP driver, no callbacks are used
SLEEP_Init(NULL, NULL);
......
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Watch states handling.
*/
#include <FreeRTOS.h>
#include <timers.h>
#include <drivers/backlight.h>
#include "state.h"
#include "blight_task.h"
///> Number of ticks when the watch is considered active since active_reset()
#define ACTIVE_STATE_TICKS 10000
enum watch_state current_state = IDLE;
static xTimerHandle timer_handle;
static void state_handler(enum watch_state state);
static void stop_active(void *params);
void state_init(void)
{
timer_handle = xTimerCreate((signed char*) "active_state",
ACTIVE_STATE_TICKS, pdTRUE,
(void*) 0, stop_active);
reset_active();
}
enum watch_state get_state(void)
{
return current_state;
}
void reset_active(void)
{
xTimerReset(timer_handle, 0);
state_handler(ACTIVE);
}
void reset_active_irq(portBASE_TYPE *task_woken)
{
xTimerResetFromISR(timer_handle, task_woken);
state_handler(ACTIVE);
}
static void stop_active(void *params)
{
(void) params;
xTimerStop(timer_handle, 0);
state_handler(IDLE);
}
static void state_handler(enum watch_state state)
{
if(state == current_state)
return;
switch(state) {
case ACTIVE:
auto_backlight_enable(true);
break;
case IDLE:
auto_backlight_enable(false);
backlight_set_level(0);
// TODO switch frequency? goto sleep?
break;
}
current_state = state;
}
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/**
* @brief Watch states handling.
*/
#ifndef STATE_H
#define STATE_H
#include <FreeRTOS.h>
///> Possible states for the watch.
enum watch_state { ACTIVE, IDLE };
/**
* @brief Initializes the state handler.
*/
void state_init(void);
/**
* @brief Returns the current state of watch.
*/
enum watch_state get_state(void);
/**
* @brief Switches to the active state for a period of time.
*/
void reset_active(void);
/**
* @brief Switches to the active state for a period of time (version
* that can be called from interrupt service routines).
* @param task_woken will be set to true if a context switch should
* be performed (@see xTimerReset()).
*/
void reset_active_irq(portBASE_TYPE *task_woken);
#endif /* STATE_H */
......@@ -142,17 +142,21 @@ INCLUDEPATHS += \
C_SRC += \
../common/Device/EnergyMicro/EFM32GG/Source/system_efm32gg.c \
../common/drivers/dmactrl.c \
../common/drivers/lcd.c \
../common/drivers/lcd_dma.c \
../common/drivers/i2cdrv.c \
../common/drivers/max17047.c \
../common/emlib/src/em_assert.c \
../common/emlib/src/em_cmu.c \
../common/emlib/src/em_dma.c \
../common/emlib/src/em_emu.c \
../common/emlib/src/em_gpio.c \
../common/emlib/src/em_i2c.c \
../common/emlib/src/em_int.c \
../common/emlib/src/em_system.c \
../common/emlib/src/em_rtc.c \
../common/emlib/src/em_timer.c \
../common/emlib/src/em_usart.c \
../common/gfx/graphics.c \
../common/gfx/font_helv11.c \
......
......@@ -143,13 +143,17 @@ INCLUDEPATHS += \
C_SRC += \
../common/Device/EnergyMicro/EFM32GG/Source/system_efm32gg.c \
../common/drivers/lcd.c \
../common/drivers/dmactrl.c \
../common/drivers/lcd_dma.c \
../common/emlib/src/em_assert.c \
../common/emlib/src/em_cmu.c \
../common/emlib/src/em_dma.c \
../common/emlib/src/em_emu.c \
../common/emlib/src/em_gpio.c \
../common/emlib/src/em_i2c.c \
../common/emlib/src/em_int.c \
../common/emlib/src/em_system.c \
../common/emlib/src/em_timer.c \
../common/emlib/src/em_rtc.c \
../common/emlib/src/em_usart.c \
../common/gfx/graphics.c \
......@@ -158,7 +162,6 @@ C_SRC += \
../common/gfx/font_helv17b.c \
../common/gfx/font_xm4x5.c \
../common/gfx/font_xm4x6.c \
../common/udelay.c \
../common/delay.c \
../common/drivers/i2cdrv.c \
../common/drivers/light_sensor.c \
......
/*
* Copyright (C) 2014 Julian Lewis
* @author Maciej Suminski <maciej.suminski@cern.ch>
* @author Matthieu Cattin <matthieu.cattin@cern.ch>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
......@@ -51,7 +52,7 @@ int main(void)
double temp = 0;
double pressure = 0;
double altitude = 0;
double lux;
uint32_t lux;
/* Setup SysTick Timer for 1 msec interrupts */
if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1);
......@@ -76,7 +77,7 @@ int main(void)
{
err = light_sensor_get_lux(&lux);
sprintf(str, "light: %3.3f lux", lux);
sprintf(str, "light: %u lux", lux);
text(&font_helv11, 5, 10, str);
err = alti_get_temp_pressure(&temp, &pressure, true);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment