initial commit

This commit is contained in:
tkl
2016-07-23 07:59:54 +02:00
commit cb58a410f1
1378 changed files with 372066 additions and 0 deletions

View File

@@ -0,0 +1,280 @@
/*
* ascii_font.h
*
* Created on: Jan 15, 2016
* Author: tkl
*/
#ifndef ASCII_FONT_H_
#define ASCII_FONT_H_
#include "font.h"
static const unsigned char ascii_font[] = {
0x00, 0x00, 0x00, 0x00, 0x00,
0x3E, 0x5B, 0x4F, 0x5B, 0x3E,
0x3E, 0x6B, 0x4F, 0x6B, 0x3E,
0x1C, 0x3E, 0x7C, 0x3E, 0x1C,
0x18, 0x3C, 0x7E, 0x3C, 0x18,
0x1C, 0x57, 0x7D, 0x57, 0x1C,
0x1C, 0x5E, 0x7F, 0x5E, 0x1C,
0x00, 0x18, 0x3C, 0x18, 0x00,
0xFF, 0xE7, 0xC3, 0xE7, 0xFF,
0x00, 0x18, 0x24, 0x18, 0x00,
0xFF, 0xE7, 0xDB, 0xE7, 0xFF,
0x30, 0x48, 0x3A, 0x06, 0x0E,
0x26, 0x29, 0x79, 0x29, 0x26,
0x40, 0x7F, 0x05, 0x05, 0x07,
0x40, 0x7F, 0x05, 0x25, 0x3F,
0x5A, 0x3C, 0xE7, 0x3C, 0x5A,
0x7F, 0x3E, 0x1C, 0x1C, 0x08,
0x08, 0x1C, 0x1C, 0x3E, 0x7F,
0x14, 0x22, 0x7F, 0x22, 0x14,
0x5F, 0x5F, 0x00, 0x5F, 0x5F,
0x06, 0x09, 0x7F, 0x01, 0x7F,
0x00, 0x66, 0x89, 0x95, 0x6A,
0x60, 0x60, 0x60, 0x60, 0x60,
0x94, 0xA2, 0xFF, 0xA2, 0x94,
0x08, 0x04, 0x7E, 0x04, 0x08,
0x10, 0x20, 0x7E, 0x20, 0x10,
0x08, 0x08, 0x2A, 0x1C, 0x08,
0x08, 0x1C, 0x2A, 0x08, 0x08,
0x1E, 0x10, 0x10, 0x10, 0x10,
0x0C, 0x1E, 0x0C, 0x1E, 0x0C,
0x30, 0x38, 0x3E, 0x38, 0x30,
0x06, 0x0E, 0x3E, 0x0E, 0x06,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x5F, 0x00, 0x00,
0x00, 0x07, 0x00, 0x07, 0x00,
0x14, 0x7F, 0x14, 0x7F, 0x14,
0x24, 0x2A, 0x7F, 0x2A, 0x12,
0x23, 0x13, 0x08, 0x64, 0x62,
0x36, 0x49, 0x56, 0x20, 0x50,
0x00, 0x08, 0x07, 0x03, 0x00,
0x00, 0x1C, 0x22, 0x41, 0x00,
0x00, 0x41, 0x22, 0x1C, 0x00,
0x2A, 0x1C, 0x7F, 0x1C, 0x2A,
0x08, 0x08, 0x3E, 0x08, 0x08,
0x00, 0x80, 0x70, 0x30, 0x00,
0x08, 0x08, 0x08, 0x08, 0x08,
0x00, 0x00, 0x60, 0x60, 0x00,
0x20, 0x10, 0x08, 0x04, 0x02,
0x3E, 0x51, 0x49, 0x45, 0x3E,
0x00, 0x42, 0x7F, 0x40, 0x00,
0x72, 0x49, 0x49, 0x49, 0x46,
0x21, 0x41, 0x49, 0x4D, 0x33,
0x18, 0x14, 0x12, 0x7F, 0x10,
0x27, 0x45, 0x45, 0x45, 0x39,
0x3C, 0x4A, 0x49, 0x49, 0x31,
0x41, 0x21, 0x11, 0x09, 0x07,
0x36, 0x49, 0x49, 0x49, 0x36,
0x46, 0x49, 0x49, 0x29, 0x1E,
0x00, 0x00, 0x14, 0x00, 0x00,
0x00, 0x40, 0x34, 0x00, 0x00,
0x00, 0x08, 0x14, 0x22, 0x41,
0x14, 0x14, 0x14, 0x14, 0x14,
0x00, 0x41, 0x22, 0x14, 0x08,
0x02, 0x01, 0x59, 0x09, 0x06,
0x3E, 0x41, 0x5D, 0x59, 0x4E,
0x7C, 0x12, 0x11, 0x12, 0x7C,
0x7F, 0x49, 0x49, 0x49, 0x36,
0x3E, 0x41, 0x41, 0x41, 0x22,
0x7F, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x49, 0x49, 0x49, 0x41,
0x7F, 0x09, 0x09, 0x09, 0x01,
0x3E, 0x41, 0x41, 0x51, 0x73,
0x7F, 0x08, 0x08, 0x08, 0x7F,
0x00, 0x41, 0x7F, 0x41, 0x00,
0x20, 0x40, 0x41, 0x3F, 0x01,
0x7F, 0x08, 0x14, 0x22, 0x41,
0x7F, 0x40, 0x40, 0x40, 0x40,
0x7F, 0x02, 0x1C, 0x02, 0x7F,
0x7F, 0x04, 0x08, 0x10, 0x7F,
0x3E, 0x41, 0x41, 0x41, 0x3E,
0x7F, 0x09, 0x09, 0x09, 0x06,
0x3E, 0x41, 0x51, 0x21, 0x5E,
0x7F, 0x09, 0x19, 0x29, 0x46,
0x26, 0x49, 0x49, 0x49, 0x32,
0x03, 0x01, 0x7F, 0x01, 0x03,
0x3F, 0x40, 0x40, 0x40, 0x3F,
0x1F, 0x20, 0x40, 0x20, 0x1F,
0x3F, 0x40, 0x38, 0x40, 0x3F,
0x63, 0x14, 0x08, 0x14, 0x63,
0x03, 0x04, 0x78, 0x04, 0x03,
0x61, 0x59, 0x49, 0x4D, 0x43,
0x00, 0x7F, 0x41, 0x41, 0x41,
0x02, 0x04, 0x08, 0x10, 0x20,
0x00, 0x41, 0x41, 0x41, 0x7F,
0x04, 0x02, 0x01, 0x02, 0x04,
0x40, 0x40, 0x40, 0x40, 0x40,
0x00, 0x03, 0x07, 0x08, 0x00,
0x20, 0x54, 0x54, 0x78, 0x40,
0x7F, 0x28, 0x44, 0x44, 0x38,
0x38, 0x44, 0x44, 0x44, 0x28,
0x38, 0x44, 0x44, 0x28, 0x7F,
0x38, 0x54, 0x54, 0x54, 0x18,
0x00, 0x08, 0x7E, 0x09, 0x02,
0x18, 0xA4, 0xA4, 0x9C, 0x78,
0x7F, 0x08, 0x04, 0x04, 0x78,
0x00, 0x44, 0x7D, 0x40, 0x00,
0x20, 0x40, 0x40, 0x3D, 0x00,
0x7F, 0x10, 0x28, 0x44, 0x00,
0x00, 0x41, 0x7F, 0x40, 0x00,
0x7C, 0x04, 0x78, 0x04, 0x78,
0x7C, 0x08, 0x04, 0x04, 0x78,
0x38, 0x44, 0x44, 0x44, 0x38,
0xFC, 0x18, 0x24, 0x24, 0x18,
0x18, 0x24, 0x24, 0x18, 0xFC,
0x7C, 0x08, 0x04, 0x04, 0x08,
0x48, 0x54, 0x54, 0x54, 0x24,
0x04, 0x04, 0x3F, 0x44, 0x24,
0x3C, 0x40, 0x40, 0x20, 0x7C,
0x1C, 0x20, 0x40, 0x20, 0x1C,
0x3C, 0x40, 0x30, 0x40, 0x3C,
0x44, 0x28, 0x10, 0x28, 0x44,
0x4C, 0x90, 0x90, 0x90, 0x7C,
0x44, 0x64, 0x54, 0x4C, 0x44,
0x00, 0x08, 0x36, 0x41, 0x00,
0x00, 0x00, 0x77, 0x00, 0x00,
0x00, 0x41, 0x36, 0x08, 0x00,
0x02, 0x01, 0x02, 0x04, 0x02,
0x3C, 0x26, 0x23, 0x26, 0x3C,
0x1E, 0xA1, 0xA1, 0x61, 0x12,
0x3A, 0x40, 0x40, 0x20, 0x7A,
0x38, 0x54, 0x54, 0x55, 0x59,
0x21, 0x55, 0x55, 0x79, 0x41,
0x22, 0x54, 0x54, 0x78, 0x42, // a-umlaut
0x21, 0x55, 0x54, 0x78, 0x40,
0x20, 0x54, 0x55, 0x79, 0x40,
0x0C, 0x1E, 0x52, 0x72, 0x12,
0x39, 0x55, 0x55, 0x55, 0x59,
0x39, 0x54, 0x54, 0x54, 0x59,
0x39, 0x55, 0x54, 0x54, 0x58,
0x00, 0x00, 0x45, 0x7C, 0x41,
0x00, 0x02, 0x45, 0x7D, 0x42,
0x00, 0x01, 0x45, 0x7C, 0x40,
0x7D, 0x12, 0x11, 0x12, 0x7D, // A-umlaut
0xF0, 0x28, 0x25, 0x28, 0xF0,
0x7C, 0x54, 0x55, 0x45, 0x00,
0x20, 0x54, 0x54, 0x7C, 0x54,
0x7C, 0x0A, 0x09, 0x7F, 0x49,
0x32, 0x49, 0x49, 0x49, 0x32,
0x3A, 0x44, 0x44, 0x44, 0x3A, // o-umlaut
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x3D, 0x42, 0x42, 0x42, 0x3D, // O-umlaut
0x3D, 0x40, 0x40, 0x40, 0x3D,
0x3C, 0x24, 0xFF, 0x24, 0x24,
0x48, 0x7E, 0x49, 0x43, 0x66,
0x2B, 0x2F, 0xFC, 0x2F, 0x2B,
0xFF, 0x09, 0x29, 0xF6, 0x20,
0xC0, 0x88, 0x7E, 0x09, 0x03,
0x20, 0x54, 0x54, 0x79, 0x41,
0x00, 0x00, 0x44, 0x7D, 0x41,
0x30, 0x48, 0x48, 0x4A, 0x32,
0x38, 0x40, 0x40, 0x22, 0x7A,
0x00, 0x7A, 0x0A, 0x0A, 0x72,
0x7D, 0x0D, 0x19, 0x31, 0x7D,
0x26, 0x29, 0x29, 0x2F, 0x28,
0x26, 0x29, 0x29, 0x29, 0x26,
0x30, 0x48, 0x4D, 0x40, 0x20,
0x38, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x38,
0x2F, 0x10, 0xC8, 0xAC, 0xBA,
0x2F, 0x10, 0x28, 0x34, 0xFA,
0x00, 0x00, 0x7B, 0x00, 0x00,
0x08, 0x14, 0x2A, 0x14, 0x22,
0x22, 0x14, 0x2A, 0x14, 0x08,
0x55, 0x00, 0x55, 0x00, 0x55, // #176 (25% block) missing in old code
0xAA, 0x55, 0xAA, 0x55, 0xAA, // 50% block
0xFF, 0x55, 0xFF, 0x55, 0xFF, // 75% block
0x00, 0x00, 0x00, 0xFF, 0x00,
0x10, 0x10, 0x10, 0xFF, 0x00,
0x14, 0x14, 0x14, 0xFF, 0x00,
0x10, 0x10, 0xFF, 0x00, 0xFF,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x14, 0x14, 0x14, 0xFC, 0x00,
0x14, 0x14, 0xF7, 0x00, 0xFF,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x14, 0x14, 0xF4, 0x04, 0xFC,
0x14, 0x14, 0x17, 0x10, 0x1F,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0x1F, 0x00,
0x10, 0x10, 0x10, 0xF0, 0x00,
0x00, 0x00, 0x00, 0x1F, 0x10,
0x10, 0x10, 0x10, 0x1F, 0x10,
0x10, 0x10, 0x10, 0xF0, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0xFF, 0x10,
0x00, 0x00, 0x00, 0xFF, 0x14,
0x00, 0x00, 0xFF, 0x00, 0xFF,
0x00, 0x00, 0x1F, 0x10, 0x17,
0x00, 0x00, 0xFC, 0x04, 0xF4,
0x14, 0x14, 0x17, 0x10, 0x17,
0x14, 0x14, 0xF4, 0x04, 0xF4,
0x00, 0x00, 0xFF, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0xF7, 0x00, 0xF7,
0x14, 0x14, 0x14, 0x17, 0x14,
0x10, 0x10, 0x1F, 0x10, 0x1F,
0x14, 0x14, 0x14, 0xF4, 0x14,
0x10, 0x10, 0xF0, 0x10, 0xF0,
0x00, 0x00, 0x1F, 0x10, 0x1F,
0x00, 0x00, 0x00, 0x1F, 0x14,
0x00, 0x00, 0x00, 0xFC, 0x14,
0x00, 0x00, 0xF0, 0x10, 0xF0,
0x10, 0x10, 0xFF, 0x10, 0xFF,
0x14, 0x14, 0x14, 0xFF, 0x14,
0x10, 0x10, 0x10, 0x1F, 0x00,
0x00, 0x00, 0x00, 0xF0, 0x10,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x00, 0x00, 0xFF, 0xFF,
0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
0x38, 0x44, 0x44, 0x38, 0x44,
0xFC, 0x4A, 0x4A, 0x4A, 0x34, // sharp-s or beta
0x7E, 0x02, 0x02, 0x06, 0x06,
0x02, 0x7E, 0x02, 0x7E, 0x02,
0x63, 0x55, 0x49, 0x41, 0x63,
0x38, 0x44, 0x44, 0x3C, 0x04,
0x40, 0x7E, 0x20, 0x1E, 0x20,
0x06, 0x02, 0x7E, 0x02, 0x02,
0x99, 0xA5, 0xE7, 0xA5, 0x99,
0x1C, 0x2A, 0x49, 0x2A, 0x1C,
0x4C, 0x72, 0x01, 0x72, 0x4C,
0x30, 0x4A, 0x4D, 0x4D, 0x30,
0x30, 0x48, 0x78, 0x48, 0x30,
0xBC, 0x62, 0x5A, 0x46, 0x3D,
0x3E, 0x49, 0x49, 0x49, 0x00,
0x7E, 0x01, 0x01, 0x01, 0x7E,
0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
0x44, 0x44, 0x5F, 0x44, 0x44,
0x40, 0x51, 0x4A, 0x44, 0x40,
0x40, 0x44, 0x4A, 0x51, 0x40,
0x00, 0x00, 0xFF, 0x01, 0x03,
0xE0, 0x80, 0xFF, 0x00, 0x00,
0x08, 0x08, 0x6B, 0x6B, 0x08,
0x36, 0x12, 0x36, 0x24, 0x36,
0x06, 0x0F, 0x09, 0x0F, 0x06,
0x00, 0x00, 0x18, 0x18, 0x00,
0x00, 0x00, 0x10, 0x10, 0x00,
0x30, 0x40, 0xFF, 0x01, 0x01,
0x00, 0x1F, 0x01, 0x01, 0x1E,
0x00, 0x19, 0x1D, 0x17, 0x12,
0x00, 0x3C, 0x3C, 0x3C, 0x3C,
0x00, 0x00, 0x00, 0x00, 0x00 // #255 NBSP
};
const struct font font_ascii_7x5 = {
5,
7,
1,
256,
(unsigned char *)ascii_font
};
#endif /* ASCII_FONT_H_ */

View File

@@ -0,0 +1,35 @@
/*
* canvas.c
*
* Created on: Jan 15, 2016
* Author: tkl
*/
#include <stddef.h>
#include <string.h>
#include "font.h"
#include "bitmap.h"
int bitmap_print_text(const struct font *font, struct bitmap *bitmap, int x_pos,
int y_pos, char *text)
{
int i = 0, pos = 0;
/* align to page */
if(y_pos % 8 != 0)
y_pos -= y_pos % 8;
pos = y_pos / 8 * bitmap->x_size + x_pos;
while(text[i] != 0) {
while(((pos + font->char_size_x) % bitmap->x_size) < font->char_size_x)
pos++;
memcpy(&bitmap->buffer[pos], &font->font[text[i] * font->char_size_x],
font->char_size_x);
memset(&bitmap->buffer[pos + font->char_size_x], 0x00,
font->char_between);
i++;
pos += font->char_size_x + 1;
}
return 0;
}

View File

@@ -0,0 +1,20 @@
/*
* bitmap.h
*
* Created on: Jan 15, 2016
* Author: tkl
*/
#ifndef BITMAP_H_
#define BITMAP_H_
struct bitmap {
int x_size;
int y_size;
char *buffer;
};
int bitmap_print_text(const struct font *font, struct bitmap *bitmap, int x_pos,
int y_pos, char *text);
#endif /* BITMAP_H_ */

18
source/firmware/kernel/ctx.h Executable file
View File

@@ -0,0 +1,18 @@
/*
* ctx.h
*
* Created on: Feb 20, 2015
* Author: tkl
*/
#ifndef CTX_H_
#define CTX_H_
#ifdef ARCH_MSP430
#include "msp430_ctx.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_ctx.h"
#endif
#endif /* CTX_H_ */

View File

@@ -0,0 +1,36 @@
/*
* adc.c
*
* Created on: Dec 23, 2012
* Author: tkl
*/
#include <stddef.h>
#include "adc.h"
//------------------------------------------------------------------------------
int adc_open(const struct adc *device) {
if(NULL == device) {
return -1;
}
adc_fp_open open = device->fp->open;
return open(device->arch_dep_device);
}
//------------------------------------------------------------------------------
int adc_close(const struct adc *device) {
if(NULL == device) {
return -1;
}
adc_fp_close close = device->fp->close;
return close(device->arch_dep_device);
}
//------------------------------------------------------------------------------
uint16_t adc_read(const struct adc *device, int timeout) {
if(NULL == device) {
return -1;
}
adc_fp_read read = device->fp->read;
return read(device->arch_dep_device, timeout);
}

View File

@@ -0,0 +1,38 @@
/*
* adc.h
*
* Created on: Dec 23, 2012
* Author: tkl
*/
#ifndef ADC_H_
#define ADC_H_
#include <stdint.h>
//------------------------------------------------------------------------------
typedef int (*adc_fp_open)(const void *);
typedef int (*adc_fp_close)(const void *);
typedef uint16_t (*adc_fp_read)(const void *, int);
//------------------------------------------------------------------------------
//! \brief Contains the function pointer to access the adc driver.
struct adc_fp {
const adc_fp_open open; //!< Function pointer to the open function.
const adc_fp_close close; //!< Function pointer to the close function.
const adc_fp_read read; //!< Function pointer to the read function.
};
//------------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the adc driver.
struct adc {
const void *arch_dep_device; //!< Architecture depended adc device (i.e. msp430_adc_t).
const struct adc_fp *fp; //!< Function pointer for the adc driver access.
};
//------------------------------------------------------------------------------
int adc_open(const struct adc *device);
int adc_close(const struct adc *device);
uint16_t adc_read(const struct adc *device, int timeout);
#endif /* ADC_H_ */

View File

@@ -0,0 +1,25 @@
/*
* battery_monitor.c
*
* Created on: Dec 23, 2012
* Author: tkl
*/
#include "stddef.h"
#include "adc.h"
#include "battery_monitor.h"
//------------------------------------------------------------------------------
struct battery_monitor_voltage get_voltage(const struct battery_monitor *device)
{
struct battery_monitor_voltage ret;
ret.valid = false;
if(NULL == device) {
return ret;
}
adc_open(device->adc);
ret.raw = adc_read(device->adc, device->timeout);
adc_close(device->adc);
ret.voltage = ret.raw * device->factor / device->divider + device->offset;
ret.valid = true;
return ret;
}

View File

@@ -0,0 +1,34 @@
/*
* battery_monitor.h
*
* Created on: Dec 23, 2012
* Author: tkl
*/
#ifndef BATTERY_MONITOR_H_
#define BATTERY_MONITOR_H_
#include "stdbool.h"
//------------------------------------------------------------------------------
//! \brief battery monitor device.
struct battery_monitor {
const struct adc *adc; //!< Adc device for the battery monitor.
const unsigned short timeout; //!< Adc measurement timeout.
const int factor; //!< Factor to calculate voltage from adc result.
const int divider; //!< Divider to calculate voltage from adc result.
const int offset; //!< Offset to calculate voltage from adc result.
};
//------------------------------------------------------------------------------
//! \brief Value container for the battery monitor.
struct battery_monitor_voltage {
unsigned short voltage; //!< Calculated voltage.
unsigned short raw; //!< Raw value of the adc.
bool valid; //!< Indicates if result is valid.
};
//------------------------------------------------------------------------------
struct battery_monitor_voltage get_voltage(const struct battery_monitor * device);
#endif /* BATTERY_MONITOR_H_ */

View File

@@ -0,0 +1,147 @@
/*
* cc110x.c
*
* Created on: Jul 20, 2012
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#include "board.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "schedule.h"
#include "irq.h"
#include "sys_tick.h"
#include "cc110x.h"
static volatile bool tx_condition;
extern volatile struct thread_context *current_thread;
static void it_cb(const struct cc110x *cc110x, enum cc110x_it_type it_type);
int cc110x_open(const struct cc110x *cc110x)
{
if(NULL == cc110x)
return (-1);
tx_condition = false;
cc110x->fp->init(cc110x);
cc110x->fp->set_it_callback(cc110x->arch_dep_device, it_cb, cc110x);
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_PWD);
cc110x_write_pa_table(cc110x);
return (0);
}
int cc110x_close(const struct cc110x *cc110x)
{
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_PWD);
blocking_read_wakeup(cc110x);
return 0;
}
void cc110x_set_radio_mode(const struct cc110x *cc110x,
enum cc110x_radio_mode mode)
{
if(NULL == cc110x) {
return;
}
*(cc110x->radio_mode) = mode;
enum cc110x_strobe_cmd cmd = STROBE_SIDLE;
switch(mode) {
case CC110X_RADIO_MODE_NONE: return;
case CC110X_RADIO_MODE_IDLE: cmd = STROBE_SIDLE; break;
case CC110X_RADIO_MODE_RX: cmd = STROBE_SRX; break;
case CC110X_RADIO_MODE_TX: cmd = STROBE_STX; break;
case CC110X_RADIO_MODE_PWD: cmd = STROBE_SPWD; break;
}
cc110x->fp->strobe(cc110x->arch_dep_device, cmd);
}
enum cc110x_radio_mode cc110x_get_radio_mode(const struct cc110x *cc110x)
{
if(NULL == cc110x)
return (CC110X_RADIO_MODE_NONE);
return (*(cc110x->radio_mode));
}
void cc110x_write_pa_table(const struct cc110x *cc110x)
{
if(NULL == cc110x)
return;
cc110x->fp->write_pa_table(cc110x->arch_dep_device);
}
void cc110x_strobe(const struct cc110x *cc110x, enum cc110x_strobe_cmd cmd)
{
if(NULL == cc110x)
return;
cc110x->fp->strobe(cc110x->arch_dep_device, cmd);
}
int cc110x_write(const struct cc110x *cc110x, const char *buffer,
int size)
{
enum cc110x_radio_mode mode;
int ret;
if((NULL == cc110x) || (NULL == buffer))
return (-1);
mode = cc110x_get_radio_mode(cc110x);
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE);
cc110x_strobe(cc110x, STROBE_SFTX);
ret = cc110x->fp->write(cc110x->arch_dep_device, buffer, size);
tx_condition = true;
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_TX);
while(tx_condition);
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE);
cc110x_strobe(cc110x, STROBE_SFTX);
cc110x_set_radio_mode(cc110x, mode);
return (ret);
}
int cc110x_read(const struct cc110x *cc110x, char *buffer, int size)
{
int ret;
unsigned int irq;
if((NULL == cc110x) || (NULL == buffer))
return (-1);
if(0 == cc110x_get_rx_count(cc110x)) {
irq = disable_irq();
current_thread->status = THREAD_STATUS_BLOCKING;
current_thread->wakeup_blocking_source = (void*) cc110x;
restore_irq(irq);
schedule();
}
enum cc110x_radio_mode mode = cc110x_get_radio_mode(cc110x);
cc110x_set_radio_mode(cc110x, CC110X_RADIO_MODE_IDLE);
ret = cc110x_get_rx_count(cc110x);
ret = cc110x->fp->read(cc110x->arch_dep_device, buffer, ret);
cc110x_strobe(cc110x, STROBE_SFRX);
cc110x_set_radio_mode(cc110x, mode);
return (ret);
}
int cc110x_get_rx_count(const struct cc110x *cc110x)
{
if(NULL == cc110x)
return (-1);
return (cc110x->fp->get_rx_count(cc110x->arch_dep_device));
}
static void it_cb(const struct cc110x *cc110x,
enum cc110x_it_type it_type)
{
if(NULL == cc110x)
return;
switch(it_type) {
case IT_TYPE_NONE:
break;
case IT_TYPE_RX_COMPLETE:
blocking_read_wakeup(cc110x);
break;
case IT_TYPE_TX_COMPLETE:
tx_condition = false;
break;
}
}

View File

@@ -0,0 +1,88 @@
/*
* cc110x.h
*
* Created on: Jul 20, 2012
* Author: tkl
*/
#ifndef CC110X_H_
#define CC110X_H_
enum cc110x_radio_mode {
CC110X_RADIO_MODE_NONE = 0,
CC110X_RADIO_MODE_IDLE,
CC110X_RADIO_MODE_RX,
CC110X_RADIO_MODE_TX,
CC110X_RADIO_MODE_PWD
};
enum cc110x_strobe_cmd {
STROBE_SRES = 0,
STROBE_SFSTXON,
STROBE_SXOFF,
STROBE_SCAL,
STROBE_SRX,
STROBE_STX,
STROBE_SIDLE,
STROBE_SWOR,
STROBE_SPWD,
STROBE_SFRX,
STROBE_SFTX,
STROBE_SWORRST,
STROBE_SNOP
};
enum cc110x_it_type {
IT_TYPE_NONE = 0,
IT_TYPE_RX_COMPLETE,
IT_TYPE_TX_COMPLETE
};
typedef void (*cc110x_fp_init)(const void *);
typedef void (*cc110x_fp_write_pa_table)(const void *);
typedef void (*cc110x_fp_set_radio_mode)(const void *, enum cc110x_radio_mode);
typedef char (*cc110x_fp_strobe)(const void *, enum cc110x_strobe_cmd);
typedef int (*cc110x_fp_write)(const void *, const char *, int);
typedef int (*cc110x_fp_read)(const void *, char *, int);
typedef int (*cc110x_fp_set_it_cb)(const void *, const void *, const void *);
typedef int (*cc110x_fp_get_rx_count)(const void *);
//! \brief Contains the function pointer to access the cc110x driver.
struct cc110x_fp {
/*! Function pointer to the init function. */
const cc110x_fp_init init;
/*! Function pointer to the strobe function. */
const cc110x_fp_strobe strobe;
/*! Function pointer to the write function. */
const cc110x_fp_write write;
/*! Function pointer to the read function. */
const cc110x_fp_read read;
/*! Function pointer to the write_pa_table function. */
const cc110x_fp_write_pa_table write_pa_table;
/*! Function pointer to the set_it_callback function. */
const cc110x_fp_set_it_cb set_it_callback;
/*! Function pointer to the get_rx_count function. */
const cc110x_fp_get_rx_count get_rx_count;
};
//! \brief The cc110x driver object.
struct cc110x {
/*! Radio mode. */
enum cc110x_radio_mode *radio_mode;
/*! Architecture depended underlaying device (i.e. spi_t or NULL). */
const void *arch_dep_device;
/*! Function pointer for the cc110x driver access. */
const struct cc110x_fp *fp;
};
int cc110x_open(const struct cc110x *cc110x);
int cc110x_close(const struct cc110x *cc110x);
int cc110x_write(const struct cc110x *cc110x, const char *buffer, int size);
int cc110x_read(const struct cc110x *cc110x, char *buffer, int size);
int cc110x_get_rx_count(const struct cc110x *cc110x);
void cc110x_set_radio_mode(const struct cc110x *cc110x, enum cc110x_radio_mode mode);
enum cc110x_radio_mode cc110x_get_radio_mode(const struct cc110x *cc110x);
void cc110x_write_pa_table(const struct cc110x *cc110x);
void cc110x_strobe(const struct cc110x *cc110x, enum cc110x_strobe_cmd cmd);
#endif /* CC110X_H_ */

View File

@@ -0,0 +1,3 @@
SUB_FOLDER += firmware/kernel/driver
INCLUDES += firmware/kernel/driver
DOC_SRC += firmware/kernel/driver

View File

@@ -0,0 +1,126 @@
/*
* ds75.c
*
* Created on: Aug 1, 2012
* Author: tkl
*/
#include <stddef.h>
#include "ds75.h"
//-----------------------------------------------------------------------------
#define TEMPERATURE_REGISTER_ADDR 0x00
#define CONFIGURATION_REGISTER_ADDR 0x01
//-----------------------------------------------------------------------------
int ds75_open(const struct ds75 *device) {
if(NULL == device) {
return -1;
}
*device->config_value = 0x00;
return device->i2c->fp->open(device->i2c->arch_dep_device);
}
//-----------------------------------------------------------------------------
int ds75_close(const struct ds75 *device) {
if(NULL == device) {
return -1;
}
return device->i2c->fp->close(device->i2c->arch_dep_device);
}
//-----------------------------------------------------------------------------
int ds75_set_precision(const struct ds75 *device, enum ds75_precision precision)
{
if(NULL == device) {
return -1;
}
char cfg = *device->config_value | (precision << 5);
char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
device->i2c_slave_addr, buffer, sizeof(buffer));
if (ret >= 0) {
*device->config_value = cfg;
}
return ret;
}
//-----------------------------------------------------------------------------
enum ds75_precision ds_75_get_precision(const struct ds75 *device) {
if(NULL == device) {
return DS_75_PRECISION_INVALID;
}
char cfg = *device->config_value;
cfg >>= 5;
cfg &= 3;
return (enum ds75_precision) cfg;
}
//-----------------------------------------------------------------------------
int ds_75_shut_down(const struct ds75 *device) {
if(NULL == device) {
return -1;
}
char cfg = *device->config_value | (1 << 0);
char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
device->i2c_slave_addr, buffer, sizeof(buffer));
if (ret >= 0) {
*device->config_value = cfg;
}
return ret;
}
//-----------------------------------------------------------------------------
int ds_75_wakeup(const struct ds75 *device) {
if(NULL == device) {
return -1;
}
char cfg = *device->config_value & ~(1 << 0);
char buffer[] = {CONFIGURATION_REGISTER_ADDR, cfg};
int ret = device->i2c->fp->write(device->i2c->arch_dep_device,
device->i2c_slave_addr, buffer, sizeof(buffer));
if (ret >= 0) {
*device->config_value = cfg;
}
return ret;
}
//-----------------------------------------------------------------------------
struct ds75_temperature ds_75_get_temperature(const struct ds75 *device) {
struct ds75_temperature ret;
ret.temperature = 0xFFFF;
ret.raw[0] = 0xFF;
ret.raw[1] = 0xFF;
ret.valid = false;
if(NULL == device) {
return ret;
}
// set temperature register
char addr = TEMPERATURE_REGISTER_ADDR;
int res = device->i2c->fp->write(device->i2c->arch_dep_device, device->i2c_slave_addr, &addr, 1);
if(res < 0) {
return ret;
}
// read temperature register
res = device->i2c->fp->read(device->i2c->arch_dep_device, device->i2c_slave_addr, ret.raw, 2);
if(res < 0) {
return ret;
}
ret.valid = true;
ret.temperature = ret.raw[0];
if(ret.temperature & 0x0080) {
ret.temperature |= 0xFF00;
}
ret.temperature *= 10;
unsigned short s_low = (unsigned char)ret.raw[1];
s_low >>= 4;
s_low *= 625;
s_low += 500;
s_low /= 1000;
ret.temperature += s_low;
return ret;
}

View File

@@ -0,0 +1,49 @@
/*
* ds75.h
*
* Created on: Aug 1, 2012
* Author: tkl
*/
#ifndef DS75_H_
#define DS75_H_
#include <stdbool.h>
#include "i2c.h"
//-----------------------------------------------------------------------------
enum ds75_precision {
DS_75_PRECISION_9_BIT = 0,
DS_75_PRECISION_10_BIT,
DS_75_PRECISION_11_BIT,
DS_75_PRECISION_12_BIT,
DS_75_PRECISION_INVALID
};
//-----------------------------------------------------------------------------
//! \brief The ds75 driver object.
struct ds75 {
const struct i2c * i2c; //!< The i2c device the ds75 is connected to.
const char i2c_slave_addr; //!< The i2c slave address of the ds 75.
char *const config_value; //!< Config value.
};
//-----------------------------------------------------------------------------
//! \brief Data container for the ds 75 measurement result.
struct ds75_temperature {
short temperature; //!< Calculated temperature.
char raw[2]; //!< Raw i2c result.
bool valid; //!< Validity indicator.
};
//-----------------------------------------------------------------------------
int ds75_open(const struct ds75 *device);
int ds75_close(const struct ds75 *device);
int ds75_set_precision(const struct ds75 *device, enum ds75_precision precision);
enum ds75_precision ds_75_get_precision(const struct ds75 *device);
int ds_75_shut_down(const struct ds75 *device);
int ds_75_wakeup(const struct ds75 *device);
struct ds75_temperature ds_75_get_temperature(const struct ds75 *device);
#endif /* DS75_H_ */

View File

@@ -0,0 +1,61 @@
/*! \file gpio.c
* \author tkl
* \date Feb 13, 2012
* \brief Source file of the architecture independent gpio driver.
*/
#include <stddef.h>
#include "gpio.h"
int gpio_open(const struct gpio *device)
{
if(device == NULL)
return -1;
gpio_fp_open_t open = device->fp->open;
return open(device->arch_dep_device);
}
int gpio_close(const struct gpio *device)
{
if(device == NULL)
return -1;
gpio_fp_close_t close = device->fp->close;
return close(device->arch_dep_device);
}
char gpio_read(const struct gpio *device)
{
if(device == NULL)
return 0;
gpio_fp_read_t read = device->fp->read;
return read(device->arch_dep_device);
}
void gpio_write(const struct gpio *device, char byte)
{
if(device == NULL)
return;
gpio_fp_write_t write = device->fp->write;
write(device->arch_dep_device, byte);
}
void gpio_toggle(const struct gpio *device) {
if(device == NULL)
return;
gpio_fp_toggle_t toggle = device->fp->toggle;
toggle(device->arch_dep_device);
}
int gpio_set_exti_callback(const struct gpio *device, const void *callback,
const void *param)
{
if((device == NULL) || (callback == NULL))
return -1;
gpio_fp_set_cb_t set_cb = device->fp->set_cb;
return set_cb(device->arch_dep_device, callback, param);
}

View File

@@ -0,0 +1,78 @@
/*! \file gpio.h
* \author tkl
* \date Feb 13, 2012
* \brief Header file of the architecture independent gpio driver.
*/
#ifndef GPIO_H_
#define GPIO_H_
//! \brief Function pointer to the open function.
typedef int (*gpio_fp_open_t)(const void*);
//! \brief Function pointer to the close function.
typedef int (*gpio_fp_close_t)(const void*);
//! \brief Function pointer to the read function.
typedef char (*gpio_fp_read_t)(const void*);
//! \brief Function pointer to the write function.
typedef void (*gpio_fp_write_t)(const void*, char);
//! \brief Function pointer to the toggle function.
typedef void (*gpio_fp_toggle_t)(const void*);
//! \brief Function pointer to the set_callback function.
typedef int (*gpio_fp_set_cb_t)(const void*, const void*, const void*);
//! \brief Contains the function pointer to access the gpio driver.
struct gpio_fp {
const gpio_fp_open_t open; //!< Function pointer to the open function.
const gpio_fp_close_t close; //!< Function pointer to the close function.
const gpio_fp_read_t read; //!< Function pointer to the read function.
const gpio_fp_write_t write; //!< Function pointer to the write function.
const gpio_fp_toggle_t toggle; //!< Function pointer to the toggle function.
const gpio_fp_set_cb_t set_cb; //!< Function pointer to the set_callback function.
};
//! \brief Contains the architecture depended device and the access functions to the gpio driver.
struct gpio {
const void *arch_dep_device; //!< Architecture depended gpio device (i.e. stm32f10x_gpio_t).
const struct gpio_fp *fp; //!< Function pointer for the gpio driver access.
};
/*! \brief Open a gpio pin.
* \param device The gpio to open.
* \retval -1 in error case.
*/
int gpio_open(const struct gpio *device);
/*! \brief Close a gpio pin
* \param device The gpio to close.
* \retval -1 in error case.
*/
int gpio_close(const struct gpio *device);
/*! \brief read from a gpio pin
* \param device The gpio to read from
* \return Read out value.
*/
char gpio_read(const struct gpio *device);
/*! \brief write to a gpio pin
* \param device The gpio to write to.
* \param byte The value to write.
*/
void gpio_write(const struct gpio *device, char byte);
//! \brief toggle a gpio pin
//! \param device the gpio to toggle.
void gpio_toggle(const struct gpio *device);
//! \brief set the callback for a gpio pin external interrupt
//! \param device The gpio to set a callback for.
//! \param callback The function pointer to be called back.
//! \param param The parameter for the call back.
int gpio_set_exti_callback(const struct gpio *device, const void *callback,
const void *param);
#endif /* GPIO_H_ */

View File

@@ -0,0 +1,53 @@
//! \file i2c.c
//! \author tkl
//! \date Apr 26, 2012
//! \brief Source file of the architecture independent i2c driver.
#include <stddef.h>
#include "i2c.h"
int i2c_open(struct i2c *device)
{
if(device == NULL) {
return -1;
}
i2c_fp_open_t open = device->fp->open;
device->cnt_subscriber++;
return open(device->arch_dep_device);
}
int i2c_close(struct i2c *device)
{
int ret = -1;
if(device == NULL) {
return -1;
}
i2c_fp_close_t close = device->fp->close;
device->cnt_subscriber--;
if(device->cnt_subscriber == 0)
ret = close(device->arch_dep_device);
else
ret = 0; /* close only if all subscribers are gone. */
return ret;
}
//-----------------------------------------------------------------------------
int i2c_write(const struct i2c *device, char addr, const char *buffer,
unsigned int len)
{
if(device == NULL) {
return -1;
}
i2c_fp_write_t write = device->fp->write;
return write(device->arch_dep_device, addr, buffer, len);
}
//-----------------------------------------------------------------------------
int i2c_read(const struct i2c *device, char addr, char *buffer,
unsigned int len)
{
if(device == NULL) {
return -1;
}
i2c_fp_read_t read = device->fp->read;
return read(device->arch_dep_device, addr, buffer, len);
}

View File

@@ -0,0 +1,75 @@
//! \file spi.h
//! \author tkl
//! \date Apr 26, 2012
//! \brief Header file of the architecture independent i2c driver.
#ifndef I2C_H_
#define I2C_H_
//-----------------------------------------------------------------------------
//! \brief Function pointer to the open function.
typedef int (*i2c_fp_open_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the close function.
typedef int (*i2c_fp_close_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the write function.
typedef int (*i2c_fp_write_t)(const void *, char addr, const char *buffer,
unsigned int len);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the read function.
typedef int (*i2c_fp_read_t)(const void *, char addr, char *buffer,
unsigned int len);
//-----------------------------------------------------------------------------
//! \brief Contains the function pointer to access the i2c driver.
struct i2c_fp {
const i2c_fp_open_t open; //!< Function pointer to the open function.
const i2c_fp_close_t close; //!< Function pointer to the close function.
const i2c_fp_write_t write; //!< Function pointer to the write function.
const i2c_fp_read_t read; //!< Function pointer to the read function.
};
//-----------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the i2c driver.
struct i2c {
const void *arch_dep_device; //!< Architecture depended i2c device (i.e. stm32f10x_i2c_t).
const struct i2c_fp *fp; //!< Function pointer for the i2c driver access.
int cnt_subscriber; //!< Number of opened slaves
};
//-----------------------------------------------------------------------------
//! \brief Open i2c device.
//! \param device The device to open.
//! \retval -1 in error case.
int i2c_open(struct i2c *device);
//-----------------------------------------------------------------------------
//! \brief Close i2c device.
//! \param device The device to close.
//! \retval -1 in error case.
int i2c_close(struct i2c *device);
//-----------------------------------------------------------------------------
//! \brief Write to an i2c device.
//! \param device The device to write to.
//! \param addr The i2c address of the i2c sink.
//! \param buffer The buffer to write.
//! \param len The length of the buffer.
//! \retval -1 in error case, otherwise the number of written bytes.
int i2c_write(const struct i2c *device, char addr, const char *buffer,
unsigned int len);
//-----------------------------------------------------------------------------
//! \brief Read from an i2c device.
//! \param device The device to read from.
//! \param addr The i2c address of the i2c source
//! \param buffer The buffer to read to.
//! \param len The maximum length of the buffer.
//! \retval -1 in error case, otherwise the number of read bytes.
int i2c_read(const struct i2c *device, char addr, char *buffer,
unsigned int len);
#endif /* I2C_H_ */

View File

@@ -0,0 +1,218 @@
//! \file rtc.c
//! \author tkl
//! \date Jul 8, 2012
//! \brief Source file of the architecture independent rtc implementation.
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "rtc.h"
//-----------------------------------------------------------------------------
int rtc_open(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_open_t open = device->fp->open;
return (open(device->arch_dep_device));
}
//-----------------------------------------------------------------------------
int rtc_close(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_close_t close = device->fp->close;
return (close(device->arch_dep_device));
}
//-----------------------------------------------------------------------------
void rtc_set_time(const struct rtc *device, const struct loki_time *time) {
if(NULL == device) {
return;
}
rtc_fp_set_time_t set_time = device->fp->set_time;
set_time(device->arch_dep_device, time);
}
//-----------------------------------------------------------------------------
struct loki_time *rtc_get_time(const struct rtc *device, struct loki_time *time) {
if(NULL == device) {
return (NULL);
}
rtc_fp_get_time_t get_time = device->fp->get_time;
return (get_time(device->arch_dep_device, time));
}
#ifndef __isleap
//! Nonzero if YEAR is a leap year (every 4 years, except every 100th isn't, and every 400th is).
#define __isleap(year) \
((year) % 4 == 0 && ((year) % 100 != 0 || (year) % 400 == 0))
#endif
//! Seconds per hour.
#define SECS_PER_HOUR (long)(60 * 60)
//! Seconds per day.
#define SECS_PER_DAY (long)(SECS_PER_HOUR * 24)
//! Clocks per sec.
#define CLOCKS_PER_SEC 1000
static const uint8_t __mon_lengths[2][12] = {
{ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }, /* Normal years. */
{ 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 } /* Leap years. */
};
//-----------------------------------------------------------------------------
uint32_t time_to_tick(const struct loki_time *time) {
if(NULL == time) {
return (0);
}
uint32_t ret = 0;
uint32_t year = time->year - 1970;
ret = time->sec + time->min * 60 + time->hour * 3600;
uint32_t days_in_year = 0;
switch(time->mon) {
case 1:
days_in_year = time->day;
break;
case 2:
days_in_year = time->day + 31;
break;
case 3:
days_in_year = time->day + 31 + 28;
break;
case 4:
days_in_year = time->day + 31 + 28 + 31;
break;
case 5:
days_in_year = time->day + 31 + 28 + 31 + 30;
break;
case 6:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31;
break;
case 7:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30;
break;
case 8:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31;
break;
case 9:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31;
break;
case 10:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30;
break;
case 11:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31;
break;
case 12:
days_in_year = time->day + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30;
break;
}
if(days_in_year > 0) {
days_in_year--;
}
uint32_t leap_days = 0;
uint32_t y = time->year;
while(y >= 1970) {
leap_days += __isleap(y) ? 1 : 0;
y--;
}
if(__isleap(time->year)) {
if(days_in_year < 59) {
if(leap_days > 0) {
leap_days--;
}
}
}
ret += (days_in_year + leap_days) * 60 * 60 * 24;
ret += (year * 60 * 60 * 24 * 365);
return (ret);
}
//-----------------------------------------------------------------------------
struct loki_time tick_to_time(uint32_t tick) {
struct loki_time ret;
uint32_t days, rem;
uint32_t y;
char *ip;
days = tick / SECS_PER_DAY;
rem = tick % SECS_PER_DAY;
while (rem < 0) {
rem += SECS_PER_DAY;
--days;
}
while (rem >= SECS_PER_DAY) {
rem -= SECS_PER_DAY;
++days;
}
ret.hour = rem / SECS_PER_HOUR;
rem %= SECS_PER_HOUR;
ret.min = rem / 60;
ret.sec = rem % 60;
y = 1970;
while (days >= (rem = __isleap(y) ? 366 : 365)) {
++y;
days -= rem;
}
while (days < 0) {
--y;
days += __isleap(y) ? 366 : 365;
}
ret.year = y;
ip = (char *)__mon_lengths[__isleap(y)];
for (y = 0; days >= ip[y]; ++y)
days -= ip[y];
ret.mon = y + 1;
ret.day = days + 1;
return (ret);
}
//-----------------------------------------------------------------------------
int rtc_start_interval_event(const struct rtc *device, enum rtc_interval interval,
const void *callback, const void *argument) {
if(NULL == device) {
return (-1);
}
rtc_fp_start_interval_event start_interval = device->fp->start_interval;
return (start_interval(device->arch_dep_device, interval, callback, argument));
}
//-----------------------------------------------------------------------------
int rtc_stop_interval_event(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_stop_interval_event stop_interval = device->fp->stop_interval;
return (stop_interval(device->arch_dep_device));
}
//-----------------------------------------------------------------------------
int rtc_start_alarm_event(const struct rtc *device,
const struct loki_time *alarm_time, enum rtc_alarm_mask alarm_mask,
const void *callback, const void *argument)
{
if(NULL == device) {
return (-1);
}
rtc_fp_start_alarm_event start_alarm = device->fp->start_alarm;
return (start_alarm(device->arch_dep_device, alarm_time, alarm_mask,
callback, argument));
}
//-----------------------------------------------------------------------------
int rtc_stop_alarm_event(const struct rtc *device) {
if(NULL == device) {
return (-1);
}
rtc_fp_stop_alarm_event stop_alarm = device->fp->stop_alarm;
return (stop_alarm(device->arch_dep_device));
}

View File

@@ -0,0 +1,161 @@
//! \file rtc.h
//! \author tkl
//! \date Jul 8, 2012
//! \brief Header file of the architecture independent rtc implementation.
#ifndef RTC_H_
#define RTC_H_
#include <stdint.h>
//-----------------------------------------------------------------------------
//! \brief Loki time container.
struct loki_time {
uint32_t sec; //!< Seconds. [0-60]
uint32_t min; //!< Minutes. [0-59]
uint32_t hour; //!< Hours. [0-23]
uint32_t day; //!< Day. [1-31]
uint32_t mon; //!< Month. [0-11]
uint32_t year; //!< Year.
};
//-----------------------------------------------------------------------------
//! \brief Rtc interrupt interval.
enum rtc_interval {
RTC_INTERVAL_MINUTE = 0, //!< rtc interrupt every minute.
RTC_INTERVAL_HOUR, //!< rtc interrupt every hour.
RTC_INTERVAL_MIDNIGHT, //!< rtc interrupt every day at 00:00.
RTC_INTERVAL_NOON //!< rtc interrupt every day at 12:00.
};
//-----------------------------------------------------------------------------
//! \brief Rtc alarm mask.
enum rtc_alarm_mask {
RTC_ALARM_DISABLED = 0x00, //!< Alarm mask disabled.
RTC_ALARM_MINUTE = 0x01, //!< Alarm mask minute.
RTC_ALARM_HOUR = 0x02, //!< Alarm mask hour.
RTC_ALARM_DAY_OF_WEEK = 0x04, //!< Alarm mask day of week.
RTC_ALARM_DAY_OF_MONTH = 0x08 //!< Alarm mask day of month.
};
//-----------------------------------------------------------------------------
//! Callback for the open function of the arch depended rtc driver.
typedef int (*rtc_fp_open_t)(const void*);
//! Callback for the close function of the arch depended rtc driver.
typedef int (*rtc_fp_close_t)(const void*);
//! Callback for the time set function of the arch depended rtc driver.
typedef void (*rtc_fp_set_time_t)(const void*, const struct loki_time*);
//! Callback for the time get function of the arch depended rtc driver.
typedef struct loki_time *(*rtc_fp_get_time_t)(const void*, struct loki_time*);
//! Callback for the start interval event function.
typedef int (*rtc_fp_start_interval_event)
(const void *, enum rtc_interval, const void *, const void *);
//! Callback for the stop interval event.
typedef int (*rtc_fp_stop_interval_event)(const void *);
//! Callback for the start alarm event.
typedef int (*rtc_fp_start_alarm_event)
(const void *, const struct loki_time*, enum rtc_alarm_mask, const void *, const void *);
//! Callback for the stop alarm event.
typedef int (*rtc_fp_stop_alarm_event)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to access the rct driver.
struct rtc_fp {
const rtc_fp_open_t open; //!< Function pointer to the open function.
const rtc_fp_close_t close; //!< Function pointer to the close function.
const rtc_fp_set_time_t set_time; //!< Function pointer to the set_time function.
const rtc_fp_get_time_t get_time; //!< Function pointer to the get_time function.
const rtc_fp_start_interval_event start_interval; //!< Function pointer to the start_interval function.
const rtc_fp_stop_interval_event stop_interval; //!< Function pointer to the stop_interval function.
const rtc_fp_start_alarm_event start_alarm; //!< Function pointer to the start_alarm function.
const rtc_fp_stop_alarm_event stop_alarm; //!< Function pointer to the stop_alarm function.
};
//-----------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the rtc driver.
struct rtc {
const void *arch_dep_device; //!< Architecture depended rtc device (i.e. msp430_rtc_t).
const struct rtc_fp *fp; //!< Function pointer for the rtc driver access.
};
//-----------------------------------------------------------------------------
//! \brief Open a rtc device.
//! \param device The rtc device to open.
//! \retval -1 in error case.
int rtc_open(const struct rtc *device);
//-----------------------------------------------------------------------------
//! \brief Close a rtc device.
//! \param device The rtc device to close.
//! \retval -1 in error case.
int rtc_close(const struct rtc *device);
//-----------------------------------------------------------------------------
//! \brief Set rtc time.
//! \param device The rtc device.
//! \param time The time to set.
void rtc_set_time(const struct rtc *device, const struct loki_time *time);
//-----------------------------------------------------------------------------
//! \brief Get rtc time.
//! \param device The rtc device.
//! \param time The time to get.
//! \retval NULL in error case, otherwise points to time.
struct loki_time *rtc_get_time(const struct rtc *device,
struct loki_time *time);
//-----------------------------------------------------------------------------
//! \brief Converts a Unix timestamp to a loki_time.
//! \param tick The Unix timestamp.
//! \return the converted time.
struct loki_time tick_to_time(uint32_t tick);
//-----------------------------------------------------------------------------
//! \brief Converts a loki_time to aunix timestamp.
//! \param time The time to convert.
//! \return The converted unix timestamp.
uint32_t time_to_tick(const struct loki_time *time);
//-----------------------------------------------------------------------------
//! \brief Starts a rtc interval event.
//! On every occurance of interval the rtc event gets fired.
//! \param device The rtc device.
//! \param interval The interval of rtc event occurance.
//! \param callback The callback is executed in case of interval event.
//! \param argument The argument for the callback.
//! \retval -1 in error case.
int rtc_start_interval_event(const struct rtc *device, enum rtc_interval interval,
const void * callback, const void *argument);
//-----------------------------------------------------------------------------
//! \brief Stops a rtc interval event.
//! \param device The rtc device.
//! \retval -1 in error case.
int rtc_stop_interval_event(const struct rtc *device);
//-----------------------------------------------------------------------------
//! \brief Starts a rtc alarm event.
//! \param device The rtc device.
//! \param alarm_time The time to fire the alarm.
//! \param alarm_mask The mask to filter the alarm time.
//! \param callback The callback is executed in case of alarm.
//! \param argument The argument for the callback.
//! \retval -1 in error case.
int rtc_start_alarm_event(const struct rtc *device,
const struct loki_time *alarm_time, enum rtc_alarm_mask alarm_mask,
const void * callback, const void *argument);
//-----------------------------------------------------------------------------
//! \brief Stops a rtc alarm.
//! \param device The rtc device.
//! \retval -1 in error case.
int rtc_stop_alarm_event(const struct rtc *device);
#endif /* RTC_H_ */

View File

@@ -0,0 +1,51 @@
//! \file spi.c
//! \author tkl
//! \date Feb 11, 2012
//! \brief Source file of the architecture independent spi driver.
#include <stddef.h>
#include "spi.h"
//-----------------------------------------------------------------------------
int spi_open(const struct spi *device) {
if(device == NULL) {
return -1;
}
spi_fp_open_t open = device->fp->open;
return open(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
int spi_close(const struct spi *device) {
if(device == NULL) {
return -1;
}
spi_fp_close_t close = device->fp->close;
return close(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
void spi_assert_cs(const struct spi * device) {
if(device == NULL) {
return;
}
spi_fp_assert_cs_t assert_cs = device->fp->assert_cs;
assert_cs(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
void spi_deassert_cs(const struct spi * device) {
if(device == NULL) {
return;
}
spi_fp_deassert_cs_t deassert_cs = device->fp->deassert_cs;
deassert_cs(device->arch_dep_device);
}
//-----------------------------------------------------------------------------
char spi_rxtx_byte(const struct spi * device, char byte) {
if(device == NULL) {
return 0;
}
spi_fp_rxtx_byte_t rxtx_byte = device->fp->rxtx_byte;
return rxtx_byte(device->arch_dep_device, byte);
}

View File

@@ -0,0 +1,75 @@
//! \file spi.h
//! \author tkl
//! \date Feb 11, 2012
//! \brief Header file of the architecture independent spi driver.
#ifndef SPI_H_
#define SPI_H_
//-----------------------------------------------------------------------------
//! \brief Function pointer to the open function.
typedef int (*spi_fp_open_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the close function.
typedef int (*spi_fp_close_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the assert chip select function.
typedef void (*spi_fp_assert_cs_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the deassert chip select function.
typedef void (*spi_fp_deassert_cs_t)(const void *);
//-----------------------------------------------------------------------------
//! \brief Function pointer to the receive / transmit function.
typedef char (*spi_fp_rxtx_byte_t)(const void *, char);
//-----------------------------------------------------------------------------
//! \brief Contains the function pointer to access the spi driver.
struct spi_fp {
const spi_fp_open_t open; //!< Function pointer to the open function.
const spi_fp_close_t close; //!< Function pointer to the close function.
const spi_fp_assert_cs_t assert_cs; //!< Function pointer to the assert chip select function.
const spi_fp_deassert_cs_t deassert_cs; //!< Function pointer to the deassert chip select function.
const spi_fp_rxtx_byte_t rxtx_byte; //!< Function pointer to the receive / transmit function.
};
//-----------------------------------------------------------------------------
//! \brief Contains the architecture depended device and the access functions to the spi driver.
struct spi {
const void *arch_dep_device; //!< Architecture depended spi device (i.e. stm32f10x_spi_t).
const struct spi_fp *fp; //!< Function pointer for the spi driver access.
};
//-----------------------------------------------------------------------------
//! \brief Open spi device.
//! \param device The spi to open.
int spi_open(const struct spi *device);
//-----------------------------------------------------------------------------
//! \brief Close spi device.
//! \param device The spi to close.
//! \retval -1 in error case.
int spi_close(const struct spi *device);
//-----------------------------------------------------------------------------
//! \brief Assert the spi's chip select.
//! \param device The spi to assert.
//! \retval -1 in error case.
void spi_assert_cs(const struct spi * device);
//-----------------------------------------------------------------------------
//! \brief Deassert the spi'schip select.
//! \param device The spi to deassert.
//! \retval -1 in error case.
void spi_deassert_cs(const struct spi * device);
//-----------------------------------------------------------------------------
//! \brief rx/tx byte over spi.
//! \param device The spi to act on.
//! \param byte The data to transmit.
//! \return The received data
char spi_rxtx_byte(const struct spi * device, char byte);
#endif /* SPI_H_ */

View File

@@ -0,0 +1,139 @@
/*
* ssd1306.c
*
* Created on: Jan 13, 2016
* Author: tkl
*/
#include <string.h>
#include "i2c.h"
#include "font.h"
#include "bitmap.h"
#include "ssd1306.h"
#define MAX_COLUMN 128
#define MAX_ROW 64
#define PAGE_COUNT 8
#define HEAD_PAGE_COUNT 2
#define BODY_PAGE_COUNT PAGE_COUNT - HEAD_PAGE_COUNT
#define CMD_MODE 0x80
#define DATA_MODE 0x40
#define COLUMN_ADDR 0x21
#define PAGE_ADDR 0x22
#define DISPLAY_OFF 0xAE
static const char init_sequence[] = {
0x80, 0xAE, 0x80, 0x20, 0x80, 0x10, 0x80, 0xb0, 0x80, 0xc8, 0x80, 0x00,
0x80, 0x10, 0x80, 0x40, 0x80, 0x81, 0x80, 0x7f, 0x80, 0xa1, 0x80, 0xa6,
0x80, 0xa8, 0x80, 0x3f, 0x80, 0xa4, 0x80, 0xd3, 0x80, 0x00, 0x80, 0xd5,
0x80, 0xf0, 0x80, 0xd9, 0x80, 0x22, 0x80, 0xda, 0x80, 0x12, 0x80, 0xdb,
0x80, 0x20, 0x80, 0x8d, 0x80, 0x14, 0x80, 0xaf
};
static int set_column(const struct ssd1306 *dev, char column)
{
char buf[6];
buf[0] = CMD_MODE;
buf[1] = COLUMN_ADDR;
buf[2] = CMD_MODE;
buf[3] = column;
buf[4] = CMD_MODE;
buf[5] = MAX_COLUMN - 1;
return i2c_write(dev->dev, dev->i2c_addr, buf, 6);
}
static int set_page(const struct ssd1306 *dev, char page)
{
char buf[6];
buf[0] = CMD_MODE;
buf[1] = PAGE_ADDR;
buf[2] = CMD_MODE;
buf[3] = page;
buf[4] = CMD_MODE;
buf[5] = MAX_ROW / PAGE_COUNT - 1;
return i2c_write(dev->dev, dev->i2c_addr, buf, 6);
}
static int clear_head(const struct ssd1306 *dev)
{
int ret, i, j;
char buf[2];
ret = set_column(dev, 0);
ret |= set_page(dev, 0);
buf[0] = DATA_MODE;
buf[1] = 0x00;
for(i = 0; i < HEAD_PAGE_COUNT; i++)
for(j = 0; j < MAX_COLUMN; j++)
ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2);
return ret;
}
static int clear_body(const struct ssd1306 *dev)
{
int ret, i, j;
char buf[2];
ret = set_column(dev, 0);
ret |= set_page(dev, 2);
buf[0] = DATA_MODE;
buf[1] = 0x00;
for(i = 0; i < BODY_PAGE_COUNT; i++)
for(j = 0; j < MAX_COLUMN; j++)
ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2);
return ret;
}
static int clear(const struct ssd1306 *dev)
{
int ret;
ret = clear_head(dev);
ret |= clear_body(dev);
return ret;
}
int ssd1306_open(const struct ssd1306 *dev)
{
int ret;
ret = i2c_open((struct i2c *)dev->dev);
ret = i2c_write(dev->dev, dev->i2c_addr, init_sequence,
sizeof(init_sequence) / sizeof(init_sequence[0]));
ret |= clear(dev);
ret |= set_column(dev, 0);
ret |= set_page(dev, 0);
return ret;
}
int ssd1306_close(const struct ssd1306 *dev)
{
int ret;
char buf[2];
buf[0] = CMD_MODE;
buf[1] = DISPLAY_OFF;
ret = i2c_write(dev->dev, dev->i2c_addr, buf, 2);
ret |= i2c_close((struct i2c *)dev->dev);
return ret;
}
int ssd1306_write(const struct ssd1306 *dev, const struct bitmap *bitmap)
{
int ret, i, len = bitmap->x_size * bitmap->y_size / 8;
char buf[2] = {DATA_MODE, 0x00};
if(len != MAX_COLUMN * PAGE_COUNT)
return -1;
ret = set_column(dev, 0);
ret |= set_page(dev, 0);
for(i = 0; i < len; i++) {
buf[1] = bitmap->buffer[i];
ret |= i2c_write(dev->dev, dev->i2c_addr, buf, 2);
}
return ret;
}

View File

@@ -0,0 +1,22 @@
/*
* ssd1306.h
*
* Created on: Jan 13, 2016
* Author: tkl
*/
#ifndef SSD1306_H_
#define SSD1306_H_
struct ssd1306 {
const struct i2c *dev;
const char i2c_addr;
};
struct bitmap;
int ssd1306_open(const struct ssd1306 *dev);
int ssd1306_close(const struct ssd1306 *dev);
int ssd1306_write(const struct ssd1306 *dev, const struct bitmap *bitmap);
#endif /* SSD1306_H_ */

View File

@@ -0,0 +1,35 @@
//! \file timer.c
//! \author tkl
//! \date Jul 5, 2012
//! \brief Source file of the architecture independent timer implementation.
#include <stddef.h>
#include "timer.h"
int timer_open(const struct loki_timer *device)
{
if(device == NULL)
return -1;
timer_fp_open_t open = device->fp->open;
return open(device->arch_dep_device);
}
int timer_close(const struct loki_timer *device)
{
if(device == NULL)
return -1;
timer_fp_close_t close = device->fp->close;
return close(device->arch_dep_device);
}
int timer_set_it_callback(const struct loki_timer *device, const void *callback,
const void *param)
{
if((device == NULL) || (callback == NULL))
return -1;
timer_fp_set_cb_t set_cb = device->fp->set_cb;
return set_cb(device->arch_dep_device, callback, param);
}

View File

@@ -0,0 +1,43 @@
//! \file timer.h
//! \author tkl
//! \date Jul 4, 2012
//! \brief Header file of the architecture independent timer implementation.
#ifndef TIMER_H_
#define TIMER_H_
typedef int (*timer_fp_open_t)(const void*); //!< callback for the open function of the arch depended timer driver.
typedef int (*timer_fp_close_t)(const void*); //!< callback for the close function of the arch depended timer driver.
typedef int (*timer_fp_set_cb_t)(const void*, const void *, const void *); //!< callback for set_callback function of the arch depended timer driver.
//! \brief The access function pointer for the timer.
struct timer_fp {
const timer_fp_open_t open; //!< Function pointer to the open function.
const timer_fp_close_t close; //!< Function pointer to the close function.
const timer_fp_set_cb_t set_cb; //!< Function pointer to the set_callback function.
};
//! \brief Contains the architecture depended device informations.
struct loki_timer {
const void *arch_dep_device; //!< Architecture depended timer device (i.e. msp430_timer).
const struct timer_fp *fp; //!< Function pointer to the architectur depended timer driver access.
};
//! \brief Open a timer timer
//! \param device The timer device to open.
//! \retval -1 in error case.
int timer_open(const struct loki_timer *device);
//! \brief Close a timer timer
//! \param device The timer device to close.
//! \retval -1 in error case.
int timer_close(const struct loki_timer *device);
//! \brief Set the callback for a sys tick timer
//! \param device The timer device to set the callback for.
//! \param callback The function pointer to call back.
//! \param param The parameter for the call back.
//! \retval -1 in error case.
int timer_set_it_callback(const struct loki_timer *device, const void *callback,
const void *param);
#endif /* TIMER_H_ */

View File

@@ -0,0 +1,78 @@
//! \file uart.c
//! \author tkl
//! \date Jul 15, 2012
//! \brief Source file of the architecture independent uart implementation.
#include <stddef.h>
#include <stdbool.h>
#include "ringbuffer.h"
#include "irq.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "schedule.h"
#include "uart.h"
extern volatile struct thread_context *current_thread;
static const void *uart_it_callback(const void *param);
int uart_open(const struct uart *this)
{
if(NULL == this)
return (-1);
int ret = this->fp->set_cb(this, uart_it_callback, this);
ret |= this->fp->open(this->arch_dep_device);
return (ret);
}
int uart_close(const struct uart *this)
{
if(NULL == this)
return (-1);
blocking_read_wakeup((const void *)this);
return (this->fp->close(this->arch_dep_device));
}
int uart_read(const struct uart *this, char *buffer, int len)
{
int ret = -1;
unsigned int irq;
if(NULL == this)
return (-1);
irq = disable_irq();
if(ringbuffer_is_empty(this->buffer)) {
current_thread->status = THREAD_STATUS_BLOCKING;
current_thread->wakeup_blocking_source = (void*) this;
restore_irq(irq);
schedule();
}
ret = ringbuffer_read(this->buffer, buffer, len);
restore_irq(irq);
return ret;
}
int uart_write(const struct uart *this, const char *buffer, int len)
{
if(NULL == this)
return (-1);
return (this->fp->write(this->arch_dep_device, buffer, len));
}
static const void *uart_it_callback(const void *param)
{
if(NULL == param)
return (NULL);
char c = 0;
struct uart *uart = (struct uart *)param;
uart->fp->read((const void *)uart->arch_dep_device, &c, 1);
if(!ringbuffer_is_full(uart->buffer))
ringbuffer_write(uart->buffer, &c, 1);
blocking_read_wakeup(param);
return (param);
}

View File

@@ -0,0 +1,63 @@
//! \file uart.h
//! \author tkl
//! \date Jul 15, 2012
//! \brief Header file of the architecture independent uart implementation.
#ifndef UART_H_
#define UART_H_
//! Function pointer for the uart open function.
typedef int (*uart_fp_open_t)(const void*);
//! Function pointer for the uart close function.
typedef int (*uart_fp_close_t)(const void*);
//! Function pointer for the uart read function.
typedef int (*uart_fp_read_t)(const void*, char*, int);
//! Function pointer for the uart write function.
typedef int (*uart_fp_write_t)(const void*, const char*, int);
//! Function pointer for the uart set callback function.
typedef int (*uart_fp_set_cb_t)(const void*, const void *, const void*);
//! \brief Uart access.
struct uart_fp {
const uart_fp_open_t open; //!< Open.
const uart_fp_close_t close; //!< Close.
const uart_fp_read_t read; //!< Read.
const uart_fp_write_t write; //!< Write.
const uart_fp_set_cb_t set_cb; //!< Set callback.
};
//! \brief Uart driver object.
struct uart {
const void *arch_dep_device; //!< Architecture depended uart device.
const struct uart_fp *fp; //!< Uart access.
struct ringbuffer *buffer; //!< Intermediate buffer.
};
//! \brief Open an uart device.
//! \param this The uart device to open.
//! \retval -1 in error case.
int uart_open(const struct uart *this);
//! \brief Close an uart device.
//! \param this The uart device to close.
//! \retval -1 in error case.
int uart_close(const struct uart *this);
//! \brief Read from an uart device.
//! \param this The uart device to read from.
//! \param buffer The buffer to read to.
//! \param len The size of the buffer.
//! \retval -1 in error case, otherwise the number of read characters.
int uart_read(const struct uart *this, char *buffer, int len);
//! \brief Write to an uart device.
//! \param this The uart device to write to.
//! \param buffer The buffer to write.
//! \param len The number of characters to write.
//! \retval -1 in error case, otherwise the number of written characters.
int uart_write(const struct uart *this, const char *buffer, int len);
#endif /* UART_H_ */

View File

@@ -0,0 +1,19 @@
/*
* font.h
*
* Created on: Jan 15, 2016
* Author: tkl
*/
#ifndef FONT_H_
#define FONT_H_
struct font {
int char_size_x;
int char_size_y;
int char_between;
int char_count;
unsigned char *font;
};
#endif /* FONT_H_ */

View File

@@ -0,0 +1,17 @@
/*
* irq.h
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#ifndef IRQ_H_
#define IRQ_H_
#ifdef ARCH_MSP430
#include "msp430_irq.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_irq.h"
#endif
#endif /* IRQ_H_ */

View File

@@ -0,0 +1,15 @@
/*
* isr.h
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#ifndef ISR_H_
#define ISR_H_
#ifdef ARCH_MSP430
#include "msp430_isr.h"
#endif
#endif /* ISR_H_ */

View File

@@ -0,0 +1,5 @@
SUB_FOLDER += firmware/kernel
INCLUDES += firmware/kernel
DOC_SRC += firmware/kernel
include firmware/kernel/driver/driver.mk

View File

@@ -0,0 +1,18 @@
/*
* low_power.h
*
* Created on: Feb 17, 2015
* Author: tkl
*/
#ifndef LOW_POWER_H_
#define LOW_POWER_H_
#ifdef ARCH_MSP430
#include "msp430_low_power.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_low_power.h"
#endif
#endif /* LOW_POWER_H_ */

View File

@@ -0,0 +1,64 @@
/*
* queue.c
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "queue.h"
int queue_init(struct queue *head)
{
if(NULL == head)
return -1;
head->front = NULL;
head->rear = NULL;
return 0;
}
int queue_push(struct queue *head, struct queue_node *node)
{
if((NULL == head) || (NULL == node))
return -1;
if(head->front == NULL) {
head->front = node;
head->rear = node;
}
else {
head->rear->next = node;
head->rear = node;
}
return 1;
}
int queue_pop(struct queue *head, struct queue_node *node)
{
if(NULL == head)
return -1;
if(head->front == NULL)
return 0;
else {
memcpy(node, head->front, sizeof(struct queue_node));
head->front = node->next;
return 1;
}
return 0;
}
bool queue_is_empty(struct queue *head)
{
if(NULL == head)
return false;
if(head->front == NULL)
return true;
return false;
}

View File

@@ -0,0 +1,26 @@
/*
* queue.h
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#ifndef QUEUE_H_
#define QUEUE_H_
struct queue_node {
struct queue_node *next;
unsigned int data;
};
struct queue {
struct queue_node *front;
struct queue_node *rear;
};
int queue_init(struct queue *head);
int queue_push(struct queue *head, struct queue_node *node);
int queue_pop(struct queue *head, struct queue_node *node);
bool queue_is_empty(struct queue *head);
#endif /* QUEUE_H_ */

View File

@@ -0,0 +1,64 @@
/*
* ringbuffer.c
*
* Created on: Jul 24, 2012
* Author: tkl
*/
#include "irq.h"
#include "ringbuffer.h"
//-----------------------------------------------------------------------------
int ringbuffer_read(struct ringbuffer *this, char *buffer, int size) {
int i;
unsigned int irq;
for(i = 0; i < size; i++) {
if(this->used > 0) {
irq = disable_irq();
buffer[i] = *this->read;
this->read++;
this->used--;
if(this->read >= (this->buffer + this->size)) {
this->read = this->buffer;
}
restore_irq(irq);
}
else {
return i;
}
}
return 0;
}
//-----------------------------------------------------------------------------
int ringbuffer_write(struct ringbuffer *this, const char *buffer,
int size)
{
int i = 0;
unsigned int irq;
for(i = 0; i < size; i++) {
if(this->used < this->size) {
irq = disable_irq();
*this->write = buffer[i];
this->write++;
this->used++;
if(this->write >= (this->buffer + this->size)) {
this->write = this->buffer;
}
restore_irq(irq);
}
else {
return i;
}
}
return i;
}
//-----------------------------------------------------------------------------
int ringbuffer_is_full(const struct ringbuffer *this) {
return (this->used == this->size) ? 1 : 0;
}
//-----------------------------------------------------------------------------
int ringbuffer_is_empty(const struct ringbuffer *this) {
return (this->used == 0) ? 1 : 0;
}

View File

@@ -0,0 +1,49 @@
/*
* ringbuffer.h
*
* Created on: Jul 24, 2012
* Author: tkl
*/
#ifndef RINGBUFFER_H_
#define RINGBUFFER_H_
//-----------------------------------------------------------------------------
//! \brief A ring buffer object.
struct ringbuffer {
char *buffer; //!< The buffer.
char *read; //!< Read access.
char *write; //!< Write access.
int size; //!< Buffer size.
int used; //!< Buffer in use.
};
//-----------------------------------------------------------------------------
//! \brief Read out n characters from ring buffer.
//! \param this The ring buffer to read from.
//! \param buffer to read to.
//! \param size The maximum number of characters to read.
//! \retval -1 in error case, otherwise the number of read characters.
int ringbuffer_read(struct ringbuffer *this, char *buffer, int size);
//-----------------------------------------------------------------------------
//! \brief Write n characters to ring buffer.
//! \param this The ring buffer to write to.
//! \param buffer to write.
//! \param size The number of characters to write.
//! \retval -1 in error case, otherwise the number of written characters.
int ringbuffer_write(struct ringbuffer *this, const char *buffer, int size);
//-----------------------------------------------------------------------------
//! \brief Check if ring buffer is full.
//! \param this The ring buffer to check.
//! \retval -1 in error case, otherwise 1 (true) / 0 (false).
int ringbuffer_is_full(const struct ringbuffer *this);
//-----------------------------------------------------------------------------
//! \brief Check if ring buffer is empty.
//! \param this The ring buffer to check.
//! \retval -1 in error case, otherwise 1 (true) / 0 (false).
int ringbuffer_is_empty(const struct ringbuffer *this);
#endif /* RINGBUFFER_H_ */

View File

@@ -0,0 +1,37 @@
/*
* schedule.c
*
* Created on: Feb 20, 2015
* Author: tkl
*/
#include <stdbool.h>
#include "board.h"
#include "ctx.h"
#include "cpu.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "irq.h"
#include "schedule.h"
#include "low_power.h"
extern volatile struct thread_list threads;
volatile struct thread_context *current_thread;
static struct thread_context idle_task;
static stack_t idle_stack[22]; /* 30 didn't work with tx test app. why? */
void idle_func(void *arg)
{
while(1) {
enter_low_power();
}
}
void schedule_start(void)
{
thread_create(&idle_task, idle_stack, sizeof(idle_stack), idle_func, NULL, THREAD_PRIO_IDLE);
current_thread = threads.list[0];
enable_irq();
start_first_task();
}

View File

@@ -0,0 +1,21 @@
/*
* schedule.h
*
* Created on: Feb 20, 2015
* Author: tkl
*/
#ifndef SCHEDULE_H_
#define SCHEDULE_H_
#ifdef ARCH_MSP430
#include "msp430_schedule.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_ctx.h"
#endif
void schedule_start(void);
#define schedule() arch_schedule()
#endif /* SCHEDULE_H_ */

View File

@@ -0,0 +1,69 @@
/*
* semaphore.c
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#include <stdbool.h>
#include <stddef.h>
#include "irq.h"
#include "queue.h"
#include "semaphore.h"
#include "stack.h"
#include "thread.h"
#include "schedule.h"
extern volatile struct thread_context *current_thread;
int semaphore_init(struct semaphore *sem, int value)
{
if(NULL == sem)
return -1;
sem->cnt = value;
queue_init(&sem->queue);
return 0;
}
int semaphore_wait(struct semaphore *sem)
{
unsigned int irq_state;
if(NULL == sem)
return -1;
irq_state = disable_irq();
if(sem->cnt > 0) {
sem->cnt--;
restore_irq(irq_state);
}
else {
current_thread->sem_queue_node.data = (unsigned int) current_thread;
queue_push(&sem->queue, (struct queue_node *)&current_thread->sem_queue_node);
current_thread->status = THREAD_STATUS_WAITING;
restore_irq(irq_state);
schedule();
}
return 0;
}
int semaphore_post(struct semaphore *sem)
{
unsigned int irq_state;
if(NULL == sem)
return -1;
irq_state = disable_irq();
if(queue_is_empty(&sem->queue))
sem->cnt++;
else {
struct queue_node next;
queue_pop(&sem->queue, &next);
struct thread_context *ctx = (struct thread_context *) next.data;
ctx->status = THREAD_STATUS_EXECUTING;
restore_irq(irq_state);
schedule();
}
restore_irq(irq_state);
return 0;
}

View File

@@ -0,0 +1,20 @@
/*
* semaphore.h
*
* Created on: Oct 25, 2015
* Author: tkl
*/
#ifndef SEMAPHORE_H_
#define SEMAPHORE_H_
struct semaphore {
int cnt;
struct queue queue;
};
int semaphore_init(struct semaphore *sem, int value);
int semaphore_wait(struct semaphore *sem);
int semaphore_post(struct semaphore *sem);
#endif /* SEMAPHORE_H_ */

View File

@@ -0,0 +1,18 @@
/*
* stack.h
*
* Created on: Sep 27, 2015
* Author: tkl
*/
#ifndef STACK_H_
#define STACK_H_
#ifdef ARCH_MSP430
#include "msp430_stack.h"
#endif
#ifdef ARCH_STM32F4XX
#include "stm32f4xx_stack.h"
#endif
#endif /* STACK_H_ */

View File

@@ -0,0 +1,70 @@
/*
* sys_tick.c
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#include "irq.h"
#include "timer.h"
#include "stack.h"
#include "queue.h"
#include "thread.h"
#include "schedule.h"
#include "sys_tick.h"
struct sys_tick_obj
{
struct loki_timer *hw_timer;
unsigned long tick;
unsigned int used;
};
extern volatile struct thread_context *current_thread;
extern volatile struct thread_list threads;
static struct sys_tick_obj sys_tick_obj;
void *timer_cb(void *arg)
{
int i;
sys_tick_obj.tick++;
for(i = 0; i < threads.count; i++) {
if(threads.list[i]->status == THREAD_STATUS_SLEEPING) {
if(threads.list[i]->next_executing_time <= sys_tick_obj.tick) {
threads.list[i]->status = THREAD_STATUS_EXECUTING;
sys_tick_obj.used--;
if(sys_tick_obj.used == 0)
timer_close(sys_tick_obj.hw_timer);
}
}
}
return arg;
}
void sys_tick_init(const struct loki_timer *hw_timer)
{
if(NULL == hw_timer)
return;
sys_tick_obj.tick = 0;
sys_tick_obj.used = 0;
sys_tick_obj.hw_timer = (struct loki_timer *)hw_timer;
timer_set_it_callback(hw_timer, timer_cb, NULL);
}
void sleep_ms(unsigned int ms)
{
int irq;
irq = disable_irq();
current_thread->next_executing_time = sys_tick_obj.tick + ms;
current_thread->status = THREAD_STATUS_SLEEPING;
sys_tick_obj.used++;
if(sys_tick_obj.used == 1)
timer_open(sys_tick_obj.hw_timer);
restore_irq(irq);
schedule();
}

View File

@@ -0,0 +1,15 @@
/*
* sys_tick.h
*
* Created on: Sep 25, 2015
* Author: tkl
*/
#ifndef SYS_TICK_H_
#define SYS_TICK_H_
void sys_tick_init(const struct loki_timer *hw_timer);
void sleep_ms(unsigned int ms);
#endif /* SYS_TICK_H_ */

View File

@@ -0,0 +1,149 @@
/*
* thread.c
*
* Created on: Mar 16, 2015
* Author: tkl
*/
#include <stddef.h>
#include <stdbool.h>
#include "irq.h"
#include "stack.h"
#include "ctx.h"
#include "queue.h"
#include "thread.h"
extern volatile struct thread_context *current_thread;
volatile struct thread_list threads;
void thread_init(void)
{
int i;
for(i = 0; i < MAX_THREAD_COUNT; i++)
threads.list[i] = NULL;
threads.count = 0;
}
static void sort_thread_list_by_priority(void)
{
unsigned int irq, in, out;
struct thread_context *tmp;
irq = disable_irq();
for(out = 0; out < threads.count; out++) {
for(in = 0; in < threads.count - out - 1; in++) {
if(threads.list[in]->priority < threads.list[in + 1]->priority) {
tmp = threads.list[in];
threads.list[in] = threads.list[in + 1];
threads.list[in + 1] = tmp;
}
}
}
restore_irq(irq);
}
static int thread_list_add_node(struct thread_context *node)
{
unsigned int irq;
int i = -1;
if((NULL == node) || (threads.count >= MAX_THREAD_COUNT))
return i;
irq = disable_irq();
for(i = 0; i < MAX_THREAD_COUNT; i++) {
if(threads.list[i] == NULL) {
threads.list[i] = node;
threads.count++;
sort_thread_list_by_priority();
break;
}
}
restore_irq(irq);
return i;
}
static void thread_list_defragment(void)
{
int i;
unsigned int irq_state = disable_irq();
for(i = 0; i < (MAX_THREAD_COUNT - 1); i++) {
if((threads.list[i] == NULL) && (threads.list[i + 1] != NULL)) {
threads.list[i] = threads.list[i + 1];
threads.list[i + 1] = NULL;
}
}
restore_irq(irq_state);
}
static int thread_list_remove_node(struct thread_context *node)
{
int i = -1;
unsigned int irq_state;
if(NULL == node)
return i;
irq_state = disable_irq();
for(i = 0; i < MAX_THREAD_COUNT; i++) {
if(threads.list[i] == node) {
threads.list[i] = NULL;
threads.count--;
thread_list_defragment();
break;
}
}
restore_irq(irq_state);
return i;
}
struct thread_context *thread_create(
struct thread_context *thread,
stack_t *stack,
unsigned int stack_size,
void (*thread_func)(void *),
void *arg,
enum thread_priority priority)
{
if((thread == NULL) || (stack == NULL) || (thread_func == NULL) ||
(stack_size == 0))
return NULL;
thread->pid = threads.count;
if(thread->pid < 0)
return NULL;
thread->stack = stack;
thread->stack_size = stack_size;
thread->sp = stack_init(thread_func, arg, stack, stack_size);
thread->status = THREAD_STATUS_EXECUTING;
thread->priority = priority;
thread_list_add_node(thread);
return thread;
}
void thread_switch_context(void) {
int i;
for(i = 0; i < threads.count; i++) {
if(threads.list[i]->status == THREAD_STATUS_EXECUTING) {
current_thread = threads.list[i];
return;
}
}
}
void thread_exit(void)
{
disable_irq();
thread_list_remove_node((struct thread_context *)current_thread);
thread_switch_context();
restore_context();
}
void blocking_read_wakeup(const void *src)
{
int i;
for(i = 0; i < threads.count; i++) {
if( (threads.list[i]->status == THREAD_STATUS_BLOCKING) &&
(threads.list[i]->wakeup_blocking_source == src))
threads.list[i]->status = THREAD_STATUS_EXECUTING;
}
}

View File

@@ -0,0 +1,61 @@
/*
* thread.h
*
* Created on: Apr 13, 2015
* Author: tkl
*/
#ifndef THREAD_H_
#define THREAD_H_
#define MAX_THREAD_COUNT 32
enum thread_priority {
THREAD_PRIO_IDLE = 0,
THREAD_PRIO_LOW,
THREAD_PRIO_MEDIUM,
THREAD_PRIO_HIGH
};
enum thread_status {
THREAD_STATUS_INIT = 0,
THREAD_STATUS_EXECUTING,
THREAD_STATUS_WAITING,
THREAD_STATUS_SLEEPING,
THREAD_STATUS_BLOCKING
};
struct thread_context {
stack_t *sp; /**< thread's stack pointer */
stack_t *stack; /**< thread's stack start address */
unsigned int stack_size; /**< thread's stack size */
unsigned int pid; /**< thread's process id */
enum thread_priority priority; /**< thread's priority */
enum thread_status status; /**< thread's status */
unsigned long next_executing_time;
void *wakeup_blocking_source;
struct queue_node sem_queue_node;
};
struct thread_list {
unsigned int count; //<! Number of elements in list
struct thread_context *list[MAX_THREAD_COUNT];
};
void thread_init(void);
struct thread_context *thread_create(
struct thread_context *thread,
stack_t *stack,
unsigned int stack_size,
void (*thread_func)(void *),
void *arg,
enum thread_priority priority);
void thread_switch_context(void);
void thread_exit(void);
void blocking_read_wakeup(const void *src);
#endif /* THREAD_H_ */