server migration

This commit is contained in:
Page Asgardius 2021-07-02 07:59:34 -07:00
commit aec284f125
33 changed files with 5412 additions and 0 deletions

17
README.md Normal file
View file

@ -0,0 +1,17 @@
Raspberry Pi Test
============
In this repository you will find some miscellaneous Raspberry PI stuff by Page Asgardius (Forked from André Wussow's repository).
You can find original repository at https://github.com/binerry/RaspberryPi.
License
-------
The repository content provides free software; you can redistribute it
and/or modify it under the terms of the GNU Lesser General Public License
as published by the Free Software Foundation; either version 2.1 of the License,
or (at your option) any later version.
Everything 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
Lesser General Public License for more details.

View file

@ -0,0 +1,847 @@
/*
=================================================================================
Name : PCD8544.c
Version : 0.1
Copyright (C) 2010 Limor Fried, Adafruit Industries
CORTEX-M3 version by Le Dang Dung, 2011 LeeDangDung@gmail.com (tested on LPC1769)
Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de
Description :
A simple PCD8544 LCD (Nokia3310/5110) driver. Target board is Raspberry Pi.
This driver uses 5 GPIOs on target board with a bit-bang SPI implementation
(hence, may not be as fast).
Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/)
Recommended connection (http://www.raspberrypi.org/archives/384):
LCD pins Raspberry Pi
LCD1 - GND P06 - GND
LCD2 - VCC P01 - 3.3V
LCD3 - CLK P11 - GPIO0
LCD4 - Din P12 - GPIO1
LCD5 - D/C P13 - GPIO2
LCD6 - CS P15 - GPIO3
LCD7 - RST P16 - GPIO4
LCD8 - LED P01 - 3.3V
References :
http://www.arduino.cc/playground/Code/PCD8544
http://ladyada.net/products/nokia5110/
http://code.google.com/p/meshphone/
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include <wiringPi.h>
#include "PCD8544.h"
// An abs() :)
#define abs(a) (((a) < 0) ? -(a) : (a))
// bit set
#define _BV(bit) (0x1 << (bit))
// LCD port variables
static uint8_t cursor_x, cursor_y, textsize, textcolor;
static int8_t _din, _sclk, _dc, _rst, _cs;
// font bitmap
static unsigned char 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,
0x21, 0x54, 0x54, 0x78, 0x41,
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,
0xF0, 0x29, 0x24, 0x29, 0xF0,
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,
0x32, 0x48, 0x48, 0x48, 0x32,
0x32, 0x4A, 0x48, 0x48, 0x30,
0x3A, 0x41, 0x41, 0x21, 0x7A,
0x3A, 0x42, 0x40, 0x20, 0x78,
0x00, 0x9D, 0xA0, 0xA0, 0x7D,
0x39, 0x44, 0x44, 0x44, 0x39,
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,
0xAA, 0x00, 0x55, 0x00, 0xAA,
0xAA, 0x55, 0xAA, 0x55, 0xAA,
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,
0x7C, 0x2A, 0x2A, 0x3E, 0x14,
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,
};
// the memory buffer for the LCD
uint8_t pcd8544_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0,};
// Le: get the bitmap assistance here! : http://en.radzio.dxp.pl/bitmap_converter/
// Andre: or here! : http://www.henningkarlsen.com/electronics/t_imageconverter_mono.php
const uint8_t pi_logo [] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0010 (16) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xFC, 0xAE, 0x0E, 0x0E, 0x06, 0x0E, 0x06, // 0x0020 (32) pixels
0xCE, 0x86, 0x8E, 0x0E, 0x0E, 0x1C, 0xB8, 0xF0, 0xF8, 0x78, 0x38, 0x1E, 0x0E, 0x8E, 0x8E, 0xC6, // 0x0030 (48) pixels
0x0E, 0x06, 0x0E, 0x06, 0x0E, 0x9E, 0xFE, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0040 (64) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0050 (80) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0060 (96) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0xFE, // 0x0070 (112) pixels
0xF8, 0xF0, 0x60, 0x60, 0xE0, 0xE1, 0xE3, 0xF7, 0x7E, 0x3E, 0x1E, 0x1F, 0x1F, 0x1F, 0x3E, 0x7E, // 0x0080 (128) pixels
0xFB, 0xF3, 0xE1, 0xE0, 0x60, 0x70, 0xF0, 0xF8, 0xBE, 0x1F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00, // 0x0090 (144) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00A0 (160) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00B0 (176) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, // 0x00C0 (192) pixels
0xE0, 0xFC, 0xFE, 0xFF, 0xF3, 0x38, 0x38, 0x0C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0E, 0x3C, 0x38, 0xF8, // 0x00D0 (208) pixels
0xF8, 0x38, 0x3C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0E, 0x0C, 0x38, 0x38, 0xF3, 0xFF, 0xFF, 0xF8, 0xE0, // 0x00E0 (224) pixels
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00F0 (240) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0100 (256) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0110 (272) pixels
0x00, 0x7F, 0xFF, 0xE7, 0xC3, 0xC1, 0xE0, 0xFF, 0xFF, 0x78, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, // 0x0120 (288) pixels
0x60, 0x78, 0x38, 0x3F, 0x3F, 0x38, 0x38, 0x60, 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF8, 0x7F, // 0x0130 (304) pixels
0xFF, 0xE0, 0xC1, 0xC3, 0xE7, 0x7F, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0140 (320) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0150 (336) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0160 (352) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x7F, 0xFF, 0xF1, 0xE0, 0xC0, 0x80, 0x01, // 0x0170 (368) pixels
0x03, 0x9F, 0xFF, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xFF, 0x9F, // 0x0180 (384) pixels
0x03, 0x01, 0x80, 0xC0, 0xE0, 0xF1, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0190 (400) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01A0 (416) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01B0 (432) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 0x01C0 (448) pixels
0x03, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3B, 0x71, 0x60, 0x60, 0x60, 0x60, 0x60, 0x71, // 0x01D0 (464) pixels
0x3B, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01E0 (480) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01F0 (496) pixels
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// reduces how much is refreshed, which speeds it up!
// originally derived from Steve Evans/JCW's mod but cleaned up and optimized
//#define enablePartialUpdate
static void my_setpixel(uint8_t x, uint8_t y, uint8_t color)
{
if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
return;
// x is which column
if (color)
pcd8544_buffer[x+ (y/8)*LCDWIDTH] |= _BV(y%8);
else
pcd8544_buffer[x+ (y/8)*LCDWIDTH] &= ~_BV(y%8);
}
void LCDshowLogo()
{
uint32_t i;
for (i = 0; i < LCDWIDTH * LCDHEIGHT / 8; i++ )
{
pcd8544_buffer[i] = pi_logo[i];
}
LCDdisplay();
}
#ifdef enablePartialUpdate
static uint8_t xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax;
#endif
static void updateBoundingBox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax) {
#ifdef enablePartialUpdate
if (xmin < xUpdateMin) xUpdateMin = xmin;
if (xmax > xUpdateMax) xUpdateMax = xmax;
if (ymin < yUpdateMin) yUpdateMin = ymin;
if (ymax > yUpdateMax) yUpdateMax = ymax;
#endif
}
void LCDInit(uint8_t SCLK, uint8_t DIN, uint8_t DC, uint8_t CS, uint8_t RST, uint8_t contrast)
{
_din = DIN;
_sclk = SCLK;
_dc = DC;
_rst = RST;
_cs = CS;
cursor_x = cursor_y = 0;
textsize = 1;
textcolor = BLACK;
// set pin directions
pinMode(_din, OUTPUT);
pinMode(_sclk, OUTPUT);
pinMode(_dc, OUTPUT);
pinMode(_rst, OUTPUT);
pinMode(_cs, OUTPUT);
// toggle RST low to reset; CS low so it'll listen to us
if (_cs > 0)
digitalWrite(_cs, LOW);
digitalWrite(_rst, LOW);
_delay_ms(500);
digitalWrite(_rst, HIGH);
// get into the EXTENDED mode!
LCDcommand(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION );
// LCD bias select (4 is optimal?)
LCDcommand(PCD8544_SETBIAS | 0x4);
// set VOP
if (contrast > 0x7f)
contrast = 0x7f;
LCDcommand( PCD8544_SETVOP | contrast); // Experimentally determined
// normal mode
LCDcommand(PCD8544_FUNCTIONSET);
// Set display to Normal
LCDcommand(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL);
// set up a bounding box for screen updates
updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1);
}
void LCDdrawbitmap(uint8_t x, uint8_t y,const uint8_t *bitmap, uint8_t w, uint8_t h,uint8_t color)
{
uint8_t j,i;
for ( j=0; j<h; j++)
{
for ( i=0; i<w; i++ )
{
if (*(bitmap + i + (j/8)*w) & _BV(j%8))
{
my_setpixel(x+i, y+j, color);
}
}
}
updateBoundingBox(x, y, x+w, y+h);
}
void LCDdrawstring(uint8_t x, uint8_t y, char *c)
{
cursor_x = x;
cursor_y = y;
while (*c)
{
LCDwrite(*c++);
}
}
void LCDdrawstring_P(uint8_t x, uint8_t y, const char *str)
{
cursor_x = x;
cursor_y = y;
while (1)
{
char c = (*str++);
if (! c)
return;
LCDwrite(c);
}
}
void LCDdrawchar(uint8_t x, uint8_t y, char c)
{
if (y >= LCDHEIGHT) return;
if ((x+5) >= LCDWIDTH) return;
uint8_t i,j;
for ( i =0; i<5; i++ )
{
uint8_t d = *(font+(c*5)+i);
uint8_t j;
for (j = 0; j<8; j++)
{
if (d & _BV(j))
{
my_setpixel(x+i, y+j, textcolor);
}
else
{
my_setpixel(x+i, y+j, !textcolor);
}
}
}
for ( j = 0; j<8; j++)
{
my_setpixel(x+5, y+j, !textcolor);
}
updateBoundingBox(x, y, x+5, y + 8);
}
void LCDwrite(uint8_t c)
{
if (c == '\n')
{
cursor_y += textsize*8;
cursor_x = 0;
}
else if (c == '\r')
{
// skip em
}
else
{
LCDdrawchar(cursor_x, cursor_y, c);
cursor_x += textsize*6;
if (cursor_x >= (LCDWIDTH-5))
{
cursor_x = 0;
cursor_y+=8;
}
if (cursor_y >= LCDHEIGHT)
cursor_y = 0;
}
}
void LCDsetCursor(uint8_t x, uint8_t y)
{
cursor_x = x;
cursor_y = y;
}
// bresenham's algorithm - thx wikpedia
void LCDdrawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color)
{
uint8_t steep = abs(y1 - y0) > abs(x1 - x0);
if (steep)
{
swap(x0, y0);
swap(x1, y1);
}
if (x0 > x1)
{
swap(x0, x1);
swap(y0, y1);
}
// much faster to put the test here, since we've already sorted the points
updateBoundingBox(x0, y0, x1, y1);
uint8_t dx, dy;
dx = x1 - x0;
dy = abs(y1 - y0);
int8_t err = dx / 2;
int8_t ystep;
if (y0 < y1)
{
ystep = 1;
} else
{
ystep = -1;
}
for (; x0<=x1; x0++)
{
if (steep)
{
my_setpixel(y0, x0, color);
}
else
{
my_setpixel(x0, y0, color);
}
err -= dy;
if (err < 0)
{
y0 += ystep;
err += dx;
}
}
}
// filled rectangle
void LCDfillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
{
// stupidest version - just pixels - but fast with internal buffer!
uint8_t i,j;
for ( i=x; i<x+w; i++)
{
for ( j=y; j<y+h; j++)
{
my_setpixel(i, j, color);
}
}
updateBoundingBox(x, y, x+w, y+h);
}
// draw a rectangle
void LCDdrawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color)
{
// stupidest version - just pixels - but fast with internal buffer!
uint8_t i;
for ( i=x; i<x+w; i++) {
my_setpixel(i, y, color);
my_setpixel(i, y+h-1, color);
}
for ( i=y; i<y+h; i++) {
my_setpixel(x, i, color);
my_setpixel(x+w-1, i, color);
}
updateBoundingBox(x, y, x+w, y+h);
}
// draw a circle outline
void LCDdrawcircle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
{
updateBoundingBox(x0-r, y0-r, x0+r, y0+r);
int8_t f = 1 - r;
int8_t ddF_x = 1;
int8_t ddF_y = -2 * r;
int8_t x = 0;
int8_t y = r;
my_setpixel(x0, y0+r, color);
my_setpixel(x0, y0-r, color);
my_setpixel(x0+r, y0, color);
my_setpixel(x0-r, y0, color);
while (x<y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
my_setpixel(x0 + x, y0 + y, color);
my_setpixel(x0 - x, y0 + y, color);
my_setpixel(x0 + x, y0 - y, color);
my_setpixel(x0 - x, y0 - y, color);
my_setpixel(x0 + y, y0 + x, color);
my_setpixel(x0 - y, y0 + x, color);
my_setpixel(x0 + y, y0 - x, color);
my_setpixel(x0 - y, y0 - x, color);
}
}
void LCDfillcircle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color)
{
updateBoundingBox(x0-r, y0-r, x0+r, y0+r);
int8_t f = 1 - r;
int8_t ddF_x = 1;
int8_t ddF_y = -2 * r;
int8_t x = 0;
int8_t y = r;
uint8_t i;
for (i=y0-r; i<=y0+r; i++)
{
my_setpixel(x0, i, color);
}
while (x<y)
{
if (f >= 0)
{
y--;
ddF_y += 2;
f += ddF_y;
}
x++;
ddF_x += 2;
f += ddF_x;
for ( i=y0-y; i<=y0+y; i++)
{
my_setpixel(x0+x, i, color);
my_setpixel(x0-x, i, color);
}
for ( i=y0-x; i<=y0+x; i++)
{
my_setpixel(x0+y, i, color);
my_setpixel(x0-y, i, color);
}
}
}
// the most basic function, set a single pixel
void LCDsetPixel(uint8_t x, uint8_t y, uint8_t color)
{
if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
return;
// x is which column
if (color)
pcd8544_buffer[x+ (y/8)*LCDWIDTH] |= _BV(y%8);
else
pcd8544_buffer[x+ (y/8)*LCDWIDTH] &= ~_BV(y%8);
updateBoundingBox(x,y,x,y);
}
// the most basic function, get a single pixel
uint8_t LCDgetPixel(uint8_t x, uint8_t y)
{
if ((x >= LCDWIDTH) || (y >= LCDHEIGHT))
return 0;
return (pcd8544_buffer[x+ (y/8)*LCDWIDTH] >> (7-(y%8))) & 0x1;
}
void LCDspiwrite(uint8_t c)
{
shiftOut(_din, _sclk, MSBFIRST, c);
}
void LCDcommand(uint8_t c)
{
digitalWrite( _dc, LOW);
LCDspiwrite(c);
}
void LCDdata(uint8_t c)
{
digitalWrite(_dc, HIGH);
LCDspiwrite(c);
}
void LCDsetContrast(uint8_t val)
{
if (val > 0x7f) {
val = 0x7f;
}
LCDcommand(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION );
LCDcommand( PCD8544_SETVOP | val);
LCDcommand(PCD8544_FUNCTIONSET);
}
void LCDdisplay(void)
{
uint8_t col, maxcol, p;
for(p = 0; p < 6; p++)
{
#ifdef enablePartialUpdate
// check if this page is part of update
if ( yUpdateMin >= ((p+1)*8) )
{
continue; // nope, skip it!
}
if (yUpdateMax < p*8)
{
break;
}
#endif
LCDcommand(PCD8544_SETYADDR | p);
#ifdef enablePartialUpdate
col = xUpdateMin;
maxcol = xUpdateMax;
#else
// start at the beginning of the row
col = 0;
maxcol = LCDWIDTH-1;
#endif
LCDcommand(PCD8544_SETXADDR | col);
for(; col <= maxcol; col++) {
//uart_putw_dec(col);
//uart_putchar(' ');
LCDdata(pcd8544_buffer[(LCDWIDTH*p)+col]);
}
}
LCDcommand(PCD8544_SETYADDR ); // no idea why this is necessary but it is to finish the last byte?
#ifdef enablePartialUpdate
xUpdateMin = LCDWIDTH - 1;
xUpdateMax = 0;
yUpdateMin = LCDHEIGHT-1;
yUpdateMax = 0;
#endif
}
// clear everything
void LCDclear(void) {
//memset(pcd8544_buffer, 0, LCDWIDTH*LCDHEIGHT/8);
uint32_t i;
for ( i = 0; i < LCDWIDTH*LCDHEIGHT/8 ; i++)
pcd8544_buffer[i] = 0;
updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1);
cursor_y = cursor_x = 0;
}
// bitbang serial shift out on select GPIO pin. Data rate is defined by CPU clk speed and CLKCONST_2.
// Calibrate these value for your need on target platform.
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val)
{
uint8_t i;
uint32_t j;
for (i = 0; i < 8; i++) {
if (bitOrder == LSBFIRST)
digitalWrite(dataPin, !!(val & (1 << i)));
else
digitalWrite(dataPin, !!(val & (1 << (7 - i))));
digitalWrite(clockPin, HIGH);
for (j = CLKCONST_2; j > 0; j--); // clock speed, anyone? (LCD Max CLK input: 4MHz)
digitalWrite(clockPin, LOW);
}
}
// roughly calibrated spin delay
void _delay_ms(uint32_t t)
{
uint32_t nCount = 0;
while (t != 0)
{
nCount = CLKCONST_1;
while(nCount != 0)
nCount--;
t--;
}
}

View file

@ -0,0 +1,86 @@
/*
=================================================================================
Name : PCD8544.h
Version : 0.1
Copyright (C) 2010 Limor Fried, Adafruit Industries
CORTEX-M3 version by Le Dang Dung, 2011 LeeDangDung@gmail.com (tested on LPC1769)
Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de
Description : PCD8544 LCD library!
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include <stdint.h>
#define BLACK 1
#define WHITE 0
#define LCDWIDTH 84
#define LCDHEIGHT 48
#define PCD8544_POWERDOWN 0x04
#define PCD8544_ENTRYMODE 0x02
#define PCD8544_EXTENDEDINSTRUCTION 0x01
#define PCD8544_DISPLAYBLANK 0x0
#define PCD8544_DISPLAYNORMAL 0x4
#define PCD8544_DISPLAYALLON 0x1
#define PCD8544_DISPLAYINVERTED 0x5
// H = 0
#define PCD8544_FUNCTIONSET 0x20
#define PCD8544_DISPLAYCONTROL 0x08
#define PCD8544_SETYADDR 0x40
#define PCD8544_SETXADDR 0x80
// H = 1
#define PCD8544_SETTEMP 0x04
#define PCD8544_SETBIAS 0x10
#define PCD8544_SETVOP 0x80
#define swap(a, b) { uint8_t t = a; a = b; b = t; }
// calibrate clock constants
#define CLKCONST_1 8000
#define CLKCONST_2 400 // 400 is a good tested value for Raspberry Pi
// keywords
#define LSBFIRST 0
#define MSBFIRST 1
void LCDInit(uint8_t SCLK, uint8_t DIN, uint8_t DC, uint8_t CS, uint8_t RST, uint8_t contrast);
void LCDcommand(uint8_t c);
void LCDdata(uint8_t c);
void LCDsetContrast(uint8_t val);
void LCDclear();
void LCDdisplay();
void LCDsetPixel(uint8_t x, uint8_t y, uint8_t color);
uint8_t LCDgetPixel(uint8_t x, uint8_t y);
void LCDfillcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color);
void LCDdrawcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color);
void LCDdrawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color);
void LCDfillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color);
void LCDdrawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color);
void LCDsetCursor(uint8_t x, uint8_t y);
void LCDsetTextSize(uint8_t s);
void LCDsetTextColor(uint8_t c);
void LCDwrite(uint8_t c);
void LCDshowLogo();
void LCDdrawchar(uint8_t x, uint8_t line, char c);
void LCDdrawstring(uint8_t x, uint8_t line, char *c);
void LCDdrawstring_P(uint8_t x, uint8_t line, const char *c);
void LCDdrawbitmap(uint8_t x, uint8_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color);
void LCDspiwrite(uint8_t c);
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
void _delay_ms(uint32_t t);

View file

@ -0,0 +1,23 @@
Raspberry Pi PCD8544 Library
============================
A simple PCD8544 LCD (Nokia3310/5110) driver. Target board is Raspberry Pi.
This driver uses 5 GPIOs on target board with a bit-bang SPI implementation (hence, may not be as fast but seems fast enough).
Makes use of WiringPI-library of _Gordon Henderson_ (https://projects.drogon.net/raspberry-pi/wiringpi/)
Copyright (C) 2010 _Limor Fried_, _Adafruit Industries_
CORTEX-M3 version by _Le Dang Dung_, 2011 LeeDangDung@gmail.com (tested on LPC1769)
Raspberry Pi version by _Andre Wussow_, 2012, desk@binerry.de
For more informations please visit http://binerry.de/post/25787954149/pcd8544-library-for-raspberry-pi.
License
-------
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.

View file

@ -0,0 +1,86 @@
/*
=================================================================================
Name : PCD8544.h
Version : 0.1
Copyright (C) 2010 Limor Fried, Adafruit Industries
CORTEX-M3 version by Le Dang Dung, 2011 LeeDangDung@gmail.com (tested on LPC1769)
Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de
Description : PCD8544 LCD library!
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include <stdint.h>
#define BLACK 1
#define WHITE 0
#define LCDWIDTH 84
#define LCDHEIGHT 48
#define PCD8544_POWERDOWN 0x04
#define PCD8544_ENTRYMODE 0x02
#define PCD8544_EXTENDEDINSTRUCTION 0x01
#define PCD8544_DISPLAYBLANK 0x0
#define PCD8544_DISPLAYNORMAL 0x4
#define PCD8544_DISPLAYALLON 0x1
#define PCD8544_DISPLAYINVERTED 0x5
// H = 0
#define PCD8544_FUNCTIONSET 0x20
#define PCD8544_DISPLAYCONTROL 0x08
#define PCD8544_SETYADDR 0x40
#define PCD8544_SETXADDR 0x80
// H = 1
#define PCD8544_SETTEMP 0x04
#define PCD8544_SETBIAS 0x10
#define PCD8544_SETVOP 0x80
#define swap(a, b) { uint8_t t = a; a = b; b = t; }
// calibrate clock constants
#define CLKCONST_1 8000
#define CLKCONST_2 400 // 400 is a good tested value for Raspberry Pi
// keywords
#define LSBFIRST 0
#define MSBFIRST 1
void LCDInit(uint8_t SCLK, uint8_t DIN, uint8_t DC, uint8_t CS, uint8_t RST, uint8_t contrast);
void LCDcommand(uint8_t c);
void LCDdata(uint8_t c);
void LCDsetContrast(uint8_t val);
void LCDclear();
void LCDdisplay();
void LCDsetPixel(uint8_t x, uint8_t y, uint8_t color);
uint8_t LCDgetPixel(uint8_t x, uint8_t y);
void LCDfillcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color);
void LCDdrawcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color);
void LCDdrawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color);
void LCDfillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color);
void LCDdrawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color);
void LCDsetCursor(uint8_t x, uint8_t y);
void LCDsetTextSize(uint8_t s);
void LCDsetTextColor(uint8_t c);
void LCDwrite(uint8_t c);
void LCDshowLogo();
void LCDdrawchar(uint8_t x, uint8_t line, char c);
void LCDdrawstring(uint8_t x, uint8_t line, char *c);
void LCDdrawstring_P(uint8_t x, uint8_t line, const char *c);
void LCDdrawbitmap(uint8_t x, uint8_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color);
void LCDspiwrite(uint8_t c);
void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val);
void _delay_ms(uint32_t t);

View file

@ -0,0 +1,219 @@
/*
=================================================================================
Name : pcd8544_rpi.c
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
A simple PCD8544 LCD (Nokia3310/5110) for Raspberry Pi for displaying some system informations.
Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/)
Recommended connection (http://www.raspberrypi.org/archives/384):
LCD pins Raspberry Pi
LCD1 - GND P06 - GND
LCD2 - VCC P01 - 3.3V
LCD3 - CLK P11 - GPIO0
LCD4 - Din P12 - GPIO1
LCD5 - D/C P13 - GPIO2
LCD6 - CS P15 - GPIO3
LCD7 - RST P16 - GPIO4
LCD8 - LED P01 - 3.3V
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include <wiringPi.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/sysinfo.h>
#include "PCD8544.h"
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
// pin setup
int _din = 1;
int _sclk = 0;
int _dc = 2;
int _rst = 4;
int _cs = 3;
// lcd contrast
int contrast = 50;
int main (void)
{
//clock
// variables to store date and time components
int hours, minutes, seconds, day, month, year;
//network
int fdl;
int fdr;
struct ifreq ifrl;
struct ifreq ifrr;
// print infos
printf("Raspberry Pi PCD8544 sysinfo display\n");
printf("========================================\n");
// check wiringPi setup
if (wiringPiSetup() == -1)
{
printf("wiringPi-Error\n");
exit(1);
}
// init and clear lcd
LCDInit(_sclk, _din, _dc, _cs, _rst, contrast);
LCDclear();
// show logo
LCDshowLogo();
delay(2000);
for (;;)
{
// clear lcd
LCDclear();
// temp
char tempInfo[10];
FILE *temperatureFile;
double T;
temperatureFile = fopen ("/sys/class/thermal/thermal_zone0/temp", "r");
if (temperatureFile == NULL)
; //print some message
fscanf (temperatureFile, "%lf", &T);
T /= 1000;
sprintf(tempInfo, "Temp %6.3fC", T);
fclose (temperatureFile);
char wrinfo[15];
char wlinfo[15];
fdl = socket(AF_INET, SOCK_DGRAM, 0);
/* I want to get an IPv4 IP address */
ifrl.ifr_addr.sa_family = AF_INET;
/* I want IP address attached to "wlan0" */
strncpy(ifrl.ifr_name, "wlan0", IFNAMSIZ-1);
ioctl(fdl, SIOCGIFADDR, &ifrl);
/* grab flags associated with this interface */
ioctl(fdl, SIOCGIFFLAGS, &ifrl);
if (ifrl.ifr_flags & IFF_RUNNING) {
sprintf(wlinfo, "%s", inet_ntoa(((struct sockaddr_in *)&ifrl.ifr_addr)->sin_addr));
} else {
sprintf(wlinfo, "offline");
}
close(fdl);
fdr = socket(AF_INET, SOCK_DGRAM, 0);
/* I want to get an IPv4 IP address */
ifrr.ifr_addr.sa_family = AF_INET;
/* I want IP address attached to "wlan0" */
strncpy(ifrr.ifr_name, "eth0", IFNAMSIZ-1);
ioctl(fdr, SIOCGIFADDR, &ifrr);
/* grab flags associated with this interface */
ioctl(fdr, SIOCGIFFLAGS, &ifrr);
if (ifrr.ifr_flags & IFF_RUNNING) {
sprintf(wrinfo, "%s", inet_ntoa(((struct sockaddr_in *)&ifrr.ifr_addr)->sin_addr));
} else {
sprintf(wrinfo, "offline");
}
close(fdr);
// time_t is arithmetic time type
//time_t now;
// Obtain current time
// time() returns the current time of the system as a time_t value
//time(&now);
// localtime converts a time_t value to calendar time and
// returns a pointer to a tm structure with its members
// filled with the corresponding values
//struct tm *local = localtime(&now);
// get system usage / info
struct sysinfo sys_info;
if(sysinfo(&sys_info) != 0)
{
printf("sysinfo-Error\n");
}
// time info
//char timeInfo[10];
//unsigned long seconds = local->tm_sec;
//unsigned long minutes = local->tm_min;
//unsigned long hours = local->tm_hour;
//sprintf(timeInfo, " %02d:%02d:%02d", hours, minutes, seconds);
// uptime
char uptimeInfo[15];
unsigned long uph = sys_info.uptime / 3600;
unsigned long upm = (sys_info.uptime / 60) - (uph * 60);
unsigned long ups = sys_info.uptime - (upm * 60) - (uph * 3600);
sprintf(uptimeInfo, "Up %02d:%02d:%02d", uph, upm, ups);
// cpu info
char cpuInfo[10];
unsigned long avgCpuLoad = sys_info.loads[0] / 4000;
sprintf(cpuInfo, "CPU %ld%%", avgCpuLoad);
// ram info
char ramInfo[10];
unsigned long totalRam = (sys_info.totalram - sys_info.freeram - sys_info.bufferram - sys_info.sharedram) / 1024 / 1024;
sprintf(ramInfo, "RAM %ld MB", totalRam);
// build screen
LCDdrawstring(0, 0, tempInfo);
//LCDdrawstring(0, 0, "Raspberry Pi:");
//LCDdrawline(0, 10, 83, 10, BLACK);
LCDdrawstring(0, 8, uptimeInfo);
LCDdrawstring(0, 16, cpuInfo);
LCDdrawstring(0, 24, ramInfo);
LCDdrawstring(0, 32, wlinfo);
LCDdrawstring(0, 40, wrinfo);
LCDdisplay();
delay(1000);
}
//for (;;){
// printf("LED On\n");
// digitalWrite(pin, 1);
// delay(250);
// printf("LED Off\n");
// digitalWrite(pin, 0);
// delay(250);
//}
return 0;
}

View file

@ -0,0 +1,155 @@
/*
=================================================================================
Name : pcd8544_test.c
Version : 0.1
Copyright (C) 2010 Limor Fried, Adafruit Industries
Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de
Description :
A simple PCD8544 LCD (Nokia3310/5110) test for Raspberry PI PCD8544 Library.
Based on Limor Fried's PCD8544 Arduino samples
(https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library/blob/master/examples/pcdtest/pcdtest.pde)
Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/)
Recommended connection (http://www.raspberrypi.org/archives/384):
LCD pins Raspberry Pi
LCD1 - GND P06 - GND
LCD2 - VCC P01 - 3.3V
LCD3 - CLK P11 - GPIO0
LCD4 - Din P12 - GPIO1
LCD5 - D/C P13 - GPIO2
LCD6 - CS P15 - GPIO3
LCD7 - RST P16 - GPIO4
LCD8 - LED P01 - 3.3V
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include "PCD8544.h"
// pin setup
int _din = 1;
int _sclk = 0;
int _dc = 2;
int _rst = 4;
int _cs = 3;
// lcd contrast
int contrast = 50;
int main (void)
{
// print infos
printf("Raspberry Pi PCD8544 test\n");
printf("========================================\n");
printf("CLK on Port %i \n", _sclk);
printf("DIN on Port %i \n", _din);
printf("DC on Port %i \n", _dc);
printf("CS on Port %i \n", _cs);
printf("RST on Port %i \n", _rst);
printf("========================================\n");
// check wiringPi setup
if (wiringPiSetup() == -1)
{
printf("wiringPi-Error\n");
exit(1);
}
// init and clear lcd
LCDInit(_sclk, _din, _dc, _cs, _rst, contrast);
LCDclear();
// turn all the pixels on (a handy test)
printf("Test: All pixels on.\n");
LCDcommand(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYALLON);
delay(1000);
// back to normal
printf("Test: All pixels off.\n");
LCDcommand(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL);
LCDclear();
// display logo
printf("Test: Display logo.\n");
LCDshowLogo();
delay(2000);
LCDclear();
// draw a single pixel
printf("Test: Display single pixel.\n");
LCDsetPixel(10, 10, BLACK);
LCDdisplay();
delay(2000);
LCDclear();
// draw many lines
printf("Test: Draw many lines.\n");
int i;
for (i=0; i<84; i+=4) {
LCDdrawline(0, 0, i, 47, BLACK);
}
for (i=0; i<48; i+=4) {
LCDdrawline(0, 0, 83, i, BLACK);
}
LCDdisplay();
delay(2000);
LCDclear();
// draw rectangles
printf("Test: Draw rectangles.\n");
for (i=0; i<48; i+=2) {
LCDdrawrect(i, i, 96-i, 48-i, BLACK);
}
LCDdisplay();
delay(2000);
LCDclear();
// draw multiple rectangles
printf("Test: Draw multiple rectangles.\n");
for (i=0; i<48; i++) {
// alternate colors for moire effect
LCDfillrect(i, i, 84-i, 48-i, i%2);
}
LCDdisplay();
delay(2000);
LCDclear();
// draw mulitple circles
printf("Test: Draw multiple circles.\n");
for (i=0; i<48; i+=2) {
LCDdrawcircle(41, 23, i, BLACK);
}
LCDdisplay();
delay(2000);
LCDclear();
// draw the first ~120 characters in the font
printf("Test: Draw the first ~120 chars.\n");
for (i=0; i < 64; i++) {
LCDdrawchar((i % 14) * 6, (i/14) * 8, i);
}
LCDdisplay();
delay(2000);
for (i=0; i < 64; i++) {
LCDdrawchar((i % 14) * 6, (i/14) * 8, i + 64);
}
LCDdisplay();
delay(2000);
LCDclear();
return 0;
}

View file

@ -0,0 +1,129 @@
/*
=================================================================================
Name : pcd8544_test2.c
Version : 0.1
Copyright (C) 2010 Limor Fried, Adafruit Industries
Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de
Description :
A simple PCD8544 LCD (Nokia3310/5110) test for Raspberry PI PCD8544 Library.
Based on Limor Fried's PCD8544 Arduino samples
(https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library/blob/master/examples/pcdtest/pcdtest.pde)
Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/)
Recommended connection (http://www.raspberrypi.org/archives/384):
LCD pins Raspberry Pi
LCD1 - GND P06 - GND
LCD2 - VCC P01 - 3.3V
LCD3 - CLK P11 - GPIO0
LCD4 - Din P12 - GPIO1
LCD5 - D/C P13 - GPIO2
LCD6 - CS P15 - GPIO3
LCD7 - RST P16 - GPIO4
LCD8 - LED P01 - 3.3V
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include <wiringPi.h>
#include <stdio.h>
#include <stdlib.h>
#include "PCD8544.h"
// animation setup
#define NUMFLAKES 8
#define XPOS 0
#define YPOS 1
#define DELTAY 2
// pin setup
int _din = 1;
int _sclk = 0;
int _dc = 2;
int _rst = 4;
int _cs = 3;
// lcd contrast
int contrast = 50;
// a bitmap of a 16x16 smiley icon
// get the bitmap assistance here! : http://en.radzio.dxp.pl/bitmap_converter/
// or here! : http://www.henningkarlsen.com/electronics/t_imageconverter_mono.php
const uint8_t smiley[]={
0x00, 0xE0, 0x30, 0x18, 0x0C, 0x66, 0x62, 0x02, 0x02, 0x62, 0x66, 0x0C, 0x18, 0x30, 0xE0, 0x00, // 0x0010 (16) pixels
0x00, 0x07, 0x0C, 0x18, 0x30, 0x62, 0x44, 0x4C, 0x4C, 0x44, 0x62, 0x30, 0x18, 0x0C, 0x07, 0x00, // 0x0020 (32) pixels
};
#define SMILEY_HEIGHT 16
#define SMILEY_WIDTH 16
int main (void)
{
// print infos
printf("Raspberry Pi PCD8544 animation test\n");
printf("========================================\n");
printf("CLK on Port %i \n", _sclk);
printf("DIN on Port %i \n", _din);
printf("DC on Port %i \n", _dc);
printf("CS on Port %i \n", _cs);
printf("RST on Port %i \n", _rst);
printf("========================================\n");
// check wiringPi setup
if (wiringPiSetup() == -1)
{
printf("wiringPi-Error\n");
exit(1);
}
// init and clear lcd
LCDInit(_sclk, _din, _dc, _cs, _rst, contrast);
LCDclear();
// turn all the pixels on (a handy test)
uint8_t icons[NUMFLAKES][3];
srandom(666); // whatever seed
// initialize
int f;
for (f=0; f< NUMFLAKES; f++) {
icons[f][XPOS] = random() % LCDWIDTH;
icons[f][YPOS] = 0;
icons[f][DELTAY] = random() % 5 + 1;
}
while (1) {
// draw each icon
for (f=0; f< NUMFLAKES; f++) {
LCDdrawbitmap(icons[f][XPOS], icons[f][YPOS], smiley, SMILEY_WIDTH, SMILEY_HEIGHT, BLACK);
}
LCDdisplay();
delay(500);
// then erase it + move it
for (f=0; f< NUMFLAKES; f++) {
LCDdrawbitmap(icons[f][XPOS], icons[f][YPOS], smiley, SMILEY_WIDTH, SMILEY_HEIGHT, 0);
// move it
icons[f][YPOS] += icons[f][DELTAY];
// if its gone, reinit
if (icons[f][YPOS] > LCDHEIGHT) {
icons[f][XPOS] = random() % LCDWIDTH;
icons[f][YPOS] = 0;
icons[f][DELTAY] = random() % 5 + 1;
}
}
}
return 0;
}

View file

@ -0,0 +1,24 @@
Raspberry Pi Fritzing Part
==========================
For doing some prototyping stuff it maybe really helpfull to use Raspberry Pi
within' Fritzing. This is the Fritzing Part (fzpz) of the main board, model b.
Copyright (C) 2012 by _Andre Wussow_, desk@binerry.de
Fritzing is an open-source initiative of the University of Applied Sciences Potsdam
to support designers, artists, researchers and hobbyists to work creatively with
interactive electronics. For more informations and downloads visit http://fritzing.org
For more informations please visit http://binerry.de/post/26227980624/raspberry-pi-fritzing-part
License
-------
This part is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This part 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
Lesser General Public License for more details.

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 54 KiB

View file

@ -0,0 +1,207 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="165"
height="193"
id="svg8639"
version="1.1"
>
<defs
id="defs8641" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
/>
<metadata
id="metadata8644">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-0.35714287,-1.5764639)">
<image
y="1.5764639"
x="0.35714287"
id="image8655"
xlink:href="data:image/png;base64,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
TkSuQmCC
"
height="193"
width="165" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
width="303.30707"
height="190.98425"
id="svg7963">
<defs
id="defs7965" />
<metadata
id="metadata7968">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
transform="translate(0,-861.37794)"
id="layer1">
<g
transform="matrix(1.2499997,0,0,1.2499997,80.417165,280.90006)"
id="copper1">
<g
id="copper0">
<circle
cx="1.98"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="connector1pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="9.1800003"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="dnc3pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="16.884001"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="connector5pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="24.084"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="connector7pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="31.284"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="connector9pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="38.485001"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="connector11pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="45.685001"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="dnc13pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="52.883999"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="connector15pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="60.084"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="connector17pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="67.283997"
cy="2.484"
r="2.0999999"
transform="translate(-60.592923,467.91902)"
id="dnc19pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="52.883999"
cy="2.484"
r="2.0999999"
transform="translate(-39.039706,467.89043)"
id="connector21pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="60.084"
cy="2.484"
r="2.0999999"
transform="translate(-39.039706,467.89043)"
id="connector23pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="67.283997"
cy="2.484"
r="2.0999999"
transform="translate(-39.039706,467.89043)"
id="connector25pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="1.98"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector0pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="9.1800003"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector2pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="16.884001"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector4pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="24.084"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector6pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="31.284"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="dnc8pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="38.485001"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector10pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="45.685001"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector12pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="52.883999"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector14pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="60.084"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="dnc16pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="67.283997"
cy="2.484"
r="2.0999999"
transform="translate(-60.531669,475.09702)"
id="connector18pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="52.883999"
cy="2.484"
r="2.0999999"
transform="translate(-38.978452,475.06844)"
id="connector20pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="60.084"
cy="2.484"
r="2.0999999"
transform="translate(-38.978452,475.06844)"
id="connector22pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
<circle
cx="67.283997"
cy="2.484"
r="2.0999999"
transform="translate(-38.978452,475.06844)"
id="dnc24pin"
style="fill:none;stroke:#ffbf00;stroke-width:1.29999995" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.1 KiB

View file

@ -0,0 +1,671 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="268.51877"
height="506.70215"
id="svg7408"
version="1.1"
>
<defs
id="defs7410" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
/>
<metadata
id="metadata7413">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<g
id="layer1"
transform="translate(-237.1692,55.2746)">
<g
transform="matrix(1.25,0,0,1.25,237.10357,-55.273538)"
id="schematic">
<rect
style="fill:none"
id="connector6pin"
x="203.16499"
y="42.675999"
width="10.486"
height="2.099" />
<rect
style="fill:none"
id="connector21pin"
x="203.172"
y="63.911999"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector17pin"
x="203.172"
y="85.148003"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector15pin"
x="203.172"
y="106.387"
width="10.488"
height="2.098" />
<rect
style="fill:none"
id="connector14pin"
x="203.172"
y="127.622"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector12pin"
x="203.172"
y="148.85699"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector11pin"
x="203.172"
y="170.095"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector10pin"
x="203.172"
y="191.33099"
width="10.488"
height="2.0999999" />
<rect
style="fill:none"
id="connector7pin"
x="203.172"
y="254.30984"
width="10.488"
height="2.0999999" />
<rect
style="fill:none"
id="connector2pin"
x="203.172"
y="360.508"
width="10.488"
height="2.0999999" />
<rect
style="fill:none"
id="connector4pin"
x="203.172"
y="339.62701"
width="10.488"
height="2.0999999" />
<rect
style="fill:none"
id="connector9pin"
x="203.172"
y="275.54684"
width="10.488"
height="2.0999999" />
<rect
style="fill:none"
id="connector0pin"
x="63.896"
y="0.97500002"
width="2.1010001"
height="10.488" />
<rect
style="fill:none"
id="connector1pin"
x="85.132004"
y="0.97500002"
width="2.098"
height="10.488" />
<rect
style="fill:none"
id="connector5pin"
x="106.406"
y="393.897"
width="2.0969999"
height="10.488" />
<rect
style="fill:none"
id="connector18pin"
x="1.26"
y="233.63699"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector20pin"
x="1.26"
y="254.87399"
width="10.488"
height="2.1010001" />
<rect
style="fill:none"
id="connector22pin"
x="1.26"
y="276.10901"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector23pin"
x="1.26"
y="297.345"
width="10.488"
height="2.099" />
<rect
style="fill:none"
id="connector25pin"
x="1.26"
y="318.58401"
width="10.488"
height="2.098" />
<rect
style="fill:none"
id="connector6terminal"
x="211.659"
y="42.675999"
width="1.993"
height="2.099" />
<rect
style="fill:none"
id="connector21terminal"
x="211.66701"
y="63.911999"
width="1.994"
height="2.099" />
<rect
style="fill:none"
id="connector17terminal"
x="211.66701"
y="85.148003"
width="1.994"
height="2.099" />
<rect
style="fill:none"
id="connector15terminal"
x="211.66701"
y="106.387"
width="1.994"
height="2.098" />
<rect
style="fill:none"
id="connector14terminal"
x="211.66701"
y="127.622"
width="1.994"
height="2.099" />
<rect
style="fill:none"
id="connector12terminal"
x="211.66701"
y="148.85699"
width="1.994"
height="2.099" />
<rect
style="fill:none"
id="connector11terminal"
x="211.66701"
y="170.095"
width="1.994"
height="2.099" />
<rect
style="fill:none"
id="connector10terminal"
x="211.66701"
y="191.33099"
width="1.994"
height="2.0999999" />
<rect
style="fill:none"
id="connector7terminal"
x="211.66701"
y="254.30984"
width="1.994"
height="2.0999999" />
<rect
style="fill:none"
id="connector2terminal"
x="211.66701"
y="360.508"
width="1.994"
height="2.0999999" />
<rect
style="fill:none"
id="connector4terminal"
x="211.66701"
y="339.62701"
width="1.994"
height="2.0999999" />
<rect
style="fill:none"
id="connector9terminal"
x="211.66701"
y="275.54684"
width="1.994"
height="2.0999999" />
<rect
style="fill:none"
id="connector0terminal"
x="63.896"
y="0.97500002"
width="2.1010001"
height="1.995" />
<rect
style="fill:none"
id="connector1terminal"
x="85.132004"
y="0.97500002"
width="2.098"
height="1.995" />
<rect
style="fill:none"
id="connector5terminal"
x="106.406"
y="402.39301"
width="2.0969999"
height="1.992" />
<rect
style="fill:none"
id="connector18terminal"
x="1.26"
y="233.63699"
width="1.995"
height="2.099" />
<rect
style="fill:none"
id="connector20terminal"
x="1.26"
y="254.87399"
width="1.995"
height="2.1010001" />
<rect
style="fill:none"
id="connector22terminal"
x="1.26"
y="276.10901"
width="1.995"
height="2.099" />
<rect
style="fill:none"
id="connector23terminal"
x="1.26"
y="297.345"
width="1.995"
height="2.099" />
<rect
style="fill:none"
id="connector25terminal"
x="1.26"
y="318.58401"
width="1.995"
height="2.098" />
<g
id="g7250">
<rect
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x="22.445999"
y="22.211"
width="169.97301"
height="360.936"
id="rect7252" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="1.26"
y1="234.51801"
x2="22.445999"
y2="234.51801"
id="line7266" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="1.26"
y1="255.754"
x2="22.445999"
y2="255.754"
id="line7268" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="1.26"
y1="276.98901"
x2="22.445999"
y2="276.98901"
id="line7270" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="1.26"
y1="298.22501"
x2="22.445999"
y2="298.22501"
id="line7272" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="1.26"
y1="319.46301"
x2="22.445999"
y2="319.46301"
id="line7274" />
<line
style="fill:none;stroke:#000000;stroke-width:1.95169997;stroke-linecap:round;stroke-linejoin:round"
x1="213.653"
y1="43.894001"
x2="192.418"
y2="43.894001"
id="line7278" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="65.128998"
x2="192.418"
y2="65.128998"
id="line7280" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="86.366997"
x2="192.418"
y2="86.366997"
id="line7282" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="107.603"
x2="192.418"
y2="107.603"
id="line7284" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="128.838"
x2="192.418"
y2="128.838"
id="line7286" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="150.076"
x2="192.418"
y2="150.076"
id="line7288" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="171.312"
x2="192.418"
y2="171.312"
id="line7290" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="192.548"
x2="192.418"
y2="192.548"
id="line7292" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="340.491"
x2="192.418"
y2="340.491"
id="line7302" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="361.72699"
x2="192.418"
y2="361.72699"
id="line7304" />
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7306"
x="157.20911"
y="343.2417">SCL0</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7308"
x="156.37546"
y="364.42429">SDA0</text>
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="255.52884"
x2="192.418"
y2="255.52884"
id="line7310" />
<line
style="fill:none;stroke:#000000;stroke-width:2.41499996;stroke-linecap:round;stroke-linejoin:round"
x1="213.66"
y1="276.76483"
x2="192.418"
y2="276.76483"
id="line7312" />
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(32.2927,237.0103)"
font-size="9.9889"
id="text7318">MOSI</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(32.2927,258.4458)"
font-size="9.9889"
id="text7320">MISO</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(32.2927,258.4458)"
font-size="9.9889"
id="text7884" />
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(32.2927,279.8853)"
font-size="9.9889"
id="text7322">SCLK</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(32.2927,301.3228)"
font-size="9.9889"
id="text7324">CE0_N</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(32.2927,322.7603)"
font-size="9.9889"
id="text7326">CE1_N</text>
<line
style="fill:none;stroke:#000000;stroke-width:1.95169997;stroke-linecap:round;stroke-linejoin:round"
x1="64.900002"
y1="22.211"
x2="64.900002"
y2="0.97500002"
id="line7330" />
<line
style="fill:none;stroke:#000000;stroke-width:1.95169997;stroke-linecap:round;stroke-linejoin:round"
x1="86.136002"
y1="22.211"
x2="86.136002"
y2="0.97500002"
id="line7332" />
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(56.5574,39.3721)"
font-size="9.9889"
id="text7336">3V3</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(80.5505,39.3721)"
font-size="9.9889"
id="text7338">5V</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="matrix(0,1,-1,0,0,0)"
font-size="9.9889"
id="text7342"
x="268.9118"
y="-74.936188">SPI</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7344"
x="152.23476"
y="88.803703">GPIO5</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7346"
x="152.23476"
y="110.4131">GPIO4</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7348"
x="152.93474"
y="131.5947">GPIO3</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7350"
x="152.93474"
y="152.35159">GPIO2</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7352"
x="152.93474"
y="173.96091">GPIO1</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7354"
x="152.93474"
y="194.7197">GPIO0</text>
<text
style="font-size:6.9921999px;font-family:DroidSans"
font-size="6.9922"
id="text7364"
x="196.6985"
y="252.01715">TX</text>
<text
style="font-size:6.9921999px;font-family:DroidSans"
font-size="6.9922"
id="text7366"
x="196.6985"
y="272.41364">RX</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7380"
x="162.07768"
y="258.28082">TXD</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7382"
x="152.23476"
y="46.438499">GPIO7</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7384"
x="152.23476"
y="67.621101">GPIO6</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7386"
x="161.50626"
y="279.46445">RXD</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="matrix(0,-1,1,0,0,0)"
font-size="9.9889"
id="text7388"
x="-157.28925"
y="142.07765">Digital Input/Output</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
font-size="9.9889"
id="text7390"
x="59.680031"
y="53.917999">Power</text>
<text
style="font-size:17.97999954px;font-family:DroidSans"
font-size="17.98"
id="text7392"
x="27.876535"
y="144.12117">RaspberryPi</text>
<line
style="fill:none;stroke:#000000;stroke-width:1.95169997;stroke-linecap:round;stroke-linejoin:round"
x1="107.458"
y1="404.38501"
x2="107.458"
y2="383.147"
id="line7394" />
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="translate(96.9275,372.9604)"
font-size="9.9889"
id="text7396">GND</text>
<polygon
points="211.05,293.036 206.345,295.752 206.345,290.319 "
id="polygon7398"
transform="translate(0,-43.2)" />
<polygon
points="206.345,313.643 211.05,310.928 211.05,316.364 "
id="polygon7400"
transform="translate(0,-43.2)" />
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="matrix(0,-1,1,0,0,0)"
font-size="9.9889"
id="text7388-5"
x="-357.27725"
y="142.29678">I2C</text>
<text
style="font-size:9.98890018px;font-family:DroidSans"
transform="matrix(0,-1,1,0,0,0)"
font-size="9.9889"
id="text7388-5-8"
x="-283.80096"
y="141.91336">SERIAL</text>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

View file

@ -0,0 +1,24 @@
i2c-shifter/i2c-bridge Fritzing Prototype
=========================================
Prototype for a i2c-level-shifter / i2c-bridge for enabling intercommunication
between two devices at different logic/voltage-levels.
Copyright (C) 2012 by _Andre Wussow_, desk@binerry.de
Fritzing is an open-source initiative of the University of Applied Sciences Potsdam
to support designers, artists, researchers and hobbyists to work creatively with
interactive electronics. For more informations and downloads visit http://fritzing.org
For more informations please visit http://binerry.de/post/27067411903/i2c-level-shifter-i2c-bridge
License
-------
This prototype is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This prototype 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
Lesser General Public License for more details.

View file

@ -0,0 +1,65 @@
/*
=================================================================================
Name : Commander.cpp
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
Commander library for Arduino as i2c-slave for processing commands/actions.
References :
http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include "Arduino.h"
#include "Commander.h"
// constructor:
Commander::Commander()
{
for (int i = 0; i < MAX_COMMANDS; i++) {
this->commands[i].isActive = false;
}
}
// add command method:
void Commander::addCommand(Command_t command)
{
for (int i = 0; i < MAX_COMMANDS; i++) {
if (!this->commands[i].isActive)
{
this->commands[i] = command;
this->commands[i].isActive = true;
break;
}
}
}
// process command method:
void Commander::processCommand(String command)
{
for (int i = 0; i < MAX_COMMANDS; i++)
{
if (this->commands[i].isActive)
{
if (this->commands[i].execCommand == command)
{
// call callback-function
this->commands[i].callback(command);
break;
}
}
}
}

View file

@ -0,0 +1,56 @@
/*
=================================================================================
Name : Commander.h
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
Commander library for Arduino as i2c-slave for processing commands/actions.
References :
http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave
================================================================================
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
================================================================================
*/
#include "Arduino.h"
// ensure this library description is only included once:
#ifndef Commander_h
#define Commander_h
// constants:
#define MAX_COMMANDS 8 // max supported commands
// structs:
// Command-Struct:
typedef struct {
String execCommand; // command for execution
void (*callback)(String); // callback function
uint8_t isActive :1; // true if this command is enabled
} Command_t;
// Commander library interface description:
class Commander {
public:
// constructor:
Commander();
// methods:
void addCommand(Command_t command);
void processCommand(String command);
private:
// properties
Command_t commands[MAX_COMMANDS];
};
#endif

View file

@ -0,0 +1,227 @@
/*
=================================================================================
Name : I2CSlave.ino
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
Sample of controlling an Arduino connected to Raspberry Pi via I2C.
Recommended connection (http://www.raspberrypi.org/archives/384):
Arduino pins I2C-Shifter Raspberry Pi
GND P06 - GND
5V 5V
SDA SDA2
SCL SCL2
3V3 P01 - 3.3V
SDA1 P03 - SDA
SCL1 P05 - SCL
D2 LED1 with 1k resistor to GND
D3 LED2 with 1k resistor to GND
D4 LED3 with 1k resistor to GND
D5 Relay with transistor driver
References :
http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave
================================================================================
This sample is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This sample 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
Lesser General Public License for more details.
================================================================================
*/
#include "Commander.h"
#include "Wire.h"
/*
General Setup
*/
// define i2c commands
#define LED1_ON_COMMAND "L11"
#define LED1_OFF_COMMAND "L10"
#define LED2_ON_COMMAND "L21"
#define LED2_OFF_COMMAND "L20"
#define LED3_ON_COMMAND "L31"
#define LED3_OFF_COMMAND "L30"
#define RELAY_ON_COMMAND "R11"
#define RELAY_OFF_COMMAND "R10"
// define slave address (0x2A = 42 [the answer to the ultimate question of life, the universe, and everything ;)] )
#define SLAVE_ADDRESS 0x2A
// instantiate i2cCommander
Commander commander = Commander();
// pin setup
int led1pin = 2;
int led2pin = 3;
int led3pin = 4;
int relaypin = 5;
// other vars
int answer = 0;
void setup() {
// initialize the digital pins for leds and relay as an output
pinMode(led1pin, OUTPUT);
pinMode(led2pin, OUTPUT);
pinMode(led3pin, OUTPUT);
pinMode(relaypin, OUTPUT);
// create commands for i2cCommander
// led 1:
Command_t cmdLed1On;
cmdLed1On.execCommand = LED1_ON_COMMAND;
cmdLed1On.callback = led1On;
Command_t cmdLed1Off;
cmdLed1Off.execCommand = LED1_OFF_COMMAND;
cmdLed1Off.callback = led1Off;
// led 2:
Command_t cmdLed2On;
cmdLed2On.execCommand = LED2_ON_COMMAND;
cmdLed2On.callback = led2On;
Command_t cmdLed2Off;
cmdLed2Off.execCommand = LED2_OFF_COMMAND;
cmdLed2Off.callback = led2Off;
// led 3:
Command_t cmdLed3On;
cmdLed3On.execCommand = LED3_ON_COMMAND;
cmdLed3On.callback = led3On;
Command_t cmdLed3Off;
cmdLed3Off.execCommand = LED3_OFF_COMMAND;
cmdLed3Off.callback = led3Off;
// relay:
Command_t cmdRelayOn;
cmdRelayOn.execCommand = RELAY_ON_COMMAND;
cmdRelayOn.callback = relayOn;
Command_t cmdRelayOff;
cmdRelayOff.execCommand = RELAY_OFF_COMMAND;
cmdRelayOff.callback = relayOff;
// add commands to i2cCommander
commander.addCommand(cmdLed1On);
commander.addCommand(cmdLed1Off);
commander.addCommand(cmdLed2On);
commander.addCommand(cmdLed2Off);
commander.addCommand(cmdLed3On);
commander.addCommand(cmdLed3Off);
commander.addCommand(cmdRelayOn);
commander.addCommand(cmdRelayOff);
// initialize i2c as slave
Wire.begin(SLAVE_ADDRESS);
// define callbacks for i2c communication
Wire.onReceive(receiveData);
Wire.onRequest(sendData);
}
void loop() {
}
// callback for received data
void receiveData(int byteCount)
{
String requestCommand = "";
while(Wire.available())
{
requestCommand = requestCommand + (char)Wire.read();
}
commander.processCommand(requestCommand);
}
// callback for sending data
void sendData()
{
Wire.write(answer);
answer = 0;
}
void led1On(String command)
{
// switch led 1 on
digitalWrite(led1pin, HIGH);
// reply with command and success info
answer = 1;
}
void led1Off(String command)
{
// switch led 1 off
digitalWrite(led1pin, LOW);
// reply with command and success info
answer = 1;
}
void led2On(String command)
{
// switch led 2 on
digitalWrite(led2pin, HIGH);
// reply with command and success info
answer = 1;
}
void led2Off(String command)
{
// switch led 2 off
digitalWrite(led2pin, LOW);
// reply with command and success info
answer = 1;
}
void led3On(String command)
{
// switch led 3 on
digitalWrite(led3pin, HIGH);
// reply with command and success info
answer = 1;
}
void led3Off(String command)
{
// switch led 3 off
digitalWrite(led3pin, LOW);
// reply with command and success info
answer = 1;
}
void relayOn(String command)
{
// switch relay 3 on
digitalWrite(relaypin, HIGH);
// reply with command and success info
answer = 1;
}
void relayOff(String command)
{
// switch relay off
digitalWrite(relaypin, LOW);
// reply with command and success info
answer = 1;
}

View file

@ -0,0 +1,22 @@
Raspberry Pi with Arduino as I2C-Slave
======================================
Sample of controlling an Arduino connected to Raspberry Pi via I2C.
http://www.raspberrypi.org
http://arduino.cc
Copyright (C) 2012 by _Andre Wussow_, 2012, desk@binerry.de
For more informations please visit http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave.
License
-------
This sample is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This sample 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
Lesser General Public License for more details.

View file

@ -0,0 +1,128 @@
/*
=================================================================================
Name : i2c-arduino.c
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
Sample of controlling an Arduino connected to Raspberry Pi via I2C.
Recommended connection (http://www.raspberrypi.org/archives/384):
Arduino pins I2C-Shifter Raspberry Pi
GND P06 - GND
5V 5V
SDA SDA2
SCL SCL2
3V3 P01 - 3.3V
SDA1 P03 - SDA
SCL1 P05 - SCL
References :
http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave
================================================================================
This sample is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This sample 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
Lesser General Public License for more details.
================================================================================
*/
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
#include <stdio.h>
#include <unistd.h>
int deviceHandle;
int readBytes;
char buffer[7];
void testCommand(char command[3], char identifier[5]);
int main (void)
{
// print infos
printf("Raspberry Pi I2C Arduino Sample\n");
printf("========================================\n");
// initialize buffer
buffer[0] = 0x00;
// address of i2c Arduino device
int deviceI2CAddress = 0x2A; // (0x2A = 42)
// open device on /dev/i2c-0
if ((deviceHandle = open("/dev/i2c-0", O_RDWR)) < 0) {
printf("Error: Couldn't open device! %d\n", deviceHandle);
return 1;
}
// connect to arduino as i2c slave
if (ioctl(deviceHandle, I2C_SLAVE, deviceI2CAddress) < 0) {
printf("Error: Couldn't find arduino on address!\n");
return 1;
}
// begin transmission and request acknowledgement
readBytes = write(deviceHandle, buffer, 1);
if (readBytes != 1)
{
printf("Error: Received no ACK-Bit, couldn't established connection!");
}
else
{
// drive some tests
testCommand("L11", "LED1 on");
usleep(2000000); // 2s
testCommand("L10", "LED1 off");
usleep(2000000); // 2s
testCommand("L21", "LED2 on");
usleep(2000000); // 2s
testCommand("L20", "LED2 off");
usleep(2000000); // 2s
testCommand("L31", "LED3 on");
usleep(2000000); // 2s
testCommand("L30", "LED3 off");
usleep(2000000); // 2s
testCommand("R11", "Relay on");
usleep(2000000); // 2s
testCommand("R10", "Relay off");
}
// close connection and return
close(deviceHandle);
return 0;
}
// function for testing command
void testCommand(char command[3], char action[10])
{
// switch on
printf("Switching %s ... ", action);
readBytes = write(deviceHandle, command, 3);
// give arduino some reaction time
usleep(100000); // 100ms
// read success
readBytes = read(deviceHandle, buffer, 1);
if (readBytes != 1)
{
printf("Error: Received no data!");
}
else
{
// check response: 0 = error / 1 = success
if (buffer[0] == 1)
{
printf("OK!\n");
}
}
}

106
snippets/c/i2c/rtc_ds1307.c Normal file
View file

@ -0,0 +1,106 @@
/*
=================================================================================
Name : rtc_ds1307.c
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
A simple test for querying the RTC DS1307.
Connection (http://www.raspberrypi.org/archives/384):
DS1307 pins Raspberry Pi Other
1 - X1 Clock oscillator X1
2 - X2 Clock oscillator X2
3 - VBat Coin cell battery CR2032 3V
4 - GND P05 - GND
5 - Vcc P01 - 5V
6 - SQW/OUT
7 - SCL P04 - SCL0
8 - SDA P02 - SDA0
References :
http://binerry.de/post/26685647322/raspberry-pi-and-i2c
http://pdfserv.maxim-ic.com/en/ds/DS1307.pdf
================================================================================
This sample is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This sample 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
Lesser General Public License for more details.
================================================================================
*/
#include <stdio.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>
#include <linux/i2c.h>
int main (void)
{
// print infos
printf("Raspberry Pi RTC DS1307 Sample\n");
printf("========================================\n");
int deviceHandle;
int readBytes;
char buffer[7];
// initialize buffer
buffer[0] = 0x00;
// address of DS1307 RTC device
int deviceI2CAddress = 0x68;
// open device on /dev/i2c-0
if ((deviceHandle = open("/dev/i2c-0", O_RDWR)) < 0) {
printf("Error: Couldn't open device! %d\n", deviceHandle);
return 1;
}
// connect to DS1307 as i2c slave
if (ioctl(deviceHandle, I2C_SLAVE, deviceI2CAddress) < 0) {
printf("Error: Couldn't find device on address!\n");
return 1;
}
// begin transmission and request acknowledgement
readBytes = write(deviceHandle, buffer, 1);
if (readBytes != 1)
{
printf("Error: Received no ACK-Bit, couldn't established connection!");
}
else
{
// read response
readBytes = read(deviceHandle, buffer, 7);
if (readBytes != 7)
{
printf("Error: Received no data!");
}
else
{
// get data
int seconds = buffer[0]; // 0-59
int minutes = buffer[1]; // 0-59
int hours = buffer[2]; // 1-23
int dayOfWeek = buffer[3]; // 1-7
int day = buffer[4]; // 1-28/29/30/31
int month = buffer[5]; // 1-12
int year = buffer[6]; // 0-99;
// and print results
printf("Actual RTC-time:\n");
printf("Date: %x-%x-%x\n", year, month, day);
printf("Time: %x:%x:%x\n", hours, minutes, seconds);
}
}
// close connection and return
close(deviceHandle);
return 0;
}

34
snippets/c/printtest/ip.c Normal file
View file

@ -0,0 +1,34 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h> /* for strncpy */
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
int
main()
{
int fd;
struct ifreq ifr;
fd = socket(AF_INET, SOCK_DGRAM, 0);
/* I want to get an IPv4 IP address */
ifr.ifr_addr.sa_family = AF_INET;
/* I want IP address attached to "eth0" */
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ-1);
ioctl(fd, SIOCGIFADDR, &ifr);
close(fd);
/* display result */
printf("%s\n", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
return 0;
}

View file

@ -0,0 +1,45 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// Print current date and time in C
int main(void)
{
// variables to store date and time components
int hours, minutes, seconds, day, month, year;
// time_t is arithmetic time type
time_t now;
// Obtain current time
// time() returns the current time of the system as a time_t value
time(&now);
// Convert to local time format and print to stdout
printf("Today is : %s", ctime(&now));
// localtime converts a time_t value to calendar time and
// returns a pointer to a tm structure with its members
// filled with the corresponding values
struct tm *local = localtime(&now);
hours = local->tm_hour; // get hours since midnight (0-23)
minutes = local->tm_min; // get minutes passed after the hour (0-59)
seconds = local->tm_sec; // get seconds passed after minute (0-59)
day = local->tm_mday; // get day of month (1 to 31)
month = local->tm_mon + 1; // get month of year (0 to 11)
year = local->tm_year + 1900; // get year since 1900
// print local time
if (hours < 12) // before midday
printf("Time is : %02d:%02d:%02d am\n", hours, minutes, seconds);
else // after midday
printf("Time is : %02d:%02d:%02d pm\n", hours - 12, minutes, seconds);
// print current date
printf("Date is : %02d/%02d/%d\n", day, month, year);
return 0;
}

View file

@ -0,0 +1,4 @@
all: wdt_test.c
cc -o wdt_test wdt_test.c
clean:
rm -rf wdt_test

View file

@ -0,0 +1,77 @@
/*
=================================================================================
Name : wdt_test.c
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
A simple test for working with the Raspberry Pi BCM2835 Watchdog.
References :
http://binerry.de/post/28263824530/raspberry-pi-watchdog-timer
================================================================================
This sample is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This sample 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
Lesser General Public License for more details.
================================================================================
*/
#include <stdio.h>
#include <fcntl.h>
#include <linux/watchdog.h>
int main (int argc, char *argv[])
{
// print infos
printf("Raspberry Pi BCM2835 Watchdog Sample\n");
printf("========================================\n");
int deviceHandle;
int disableWatchdog = 1;
// test watchdog reset via t-param
if (argc > 1) {
if (!strncasecmp(argv[1], "-t", 2)) {
disableWatchdog = 0;
}
}
printf("Disabling watchdog before closing device: %d\n", disableWatchdog);
// open watchdog device on /dev/watchdog
if ((deviceHandle = open("/dev/watchdog", O_RDWR | O_NOCTTY)) < 0) {
printf("Error: Couldn't open watchdog device! %d\n", deviceHandle);
return 1;
}
// get timeout info of watchdog (try to set it to 15s before)
int timeout = 15;
ioctl(deviceHandle, WDIOC_SETTIMEOUT, &timeout);
ioctl(deviceHandle, WDIOC_GETTIMEOUT, &timeout);
printf("The watchdog timeout is %d seconds.\n\n", timeout);
// feed watchdog 3 times with heartbeats
int i;
for (i = 0; i < 3; i++) {
printf("Feeding the dog with a heartbeat.\n");
ioctl(deviceHandle, WDIOC_KEEPALIVE, 0);
sleep(10);
}
if (disableWatchdog)
{
printf("Disable watchdog.\n");
write(deviceHandle, "V", 1);
}
// close connection and return
close(deviceHandle);
return 0;
}

View file

@ -0,0 +1,11 @@
all: sipcall sipserv
sipcall: sipcall.c
cc -o $@ $< `pkg-config --cflags --libs libpjproject`
sipserv: sipserv.c
cc -o $@ $< `pkg-config --cflags --libs libpjproject`
clean:
rm -rf sipcall
rm -rf sipserv

View file

@ -0,0 +1,85 @@
Sip-Tools - Automated calls and answering machine
=================================================
sipcall - Automated calls over SIP/VOIP with TTS
sipserv - Answering machine for SIP/VOIP with TTS
Dependencies:
- PJSUA API (http://www.pjsip.org)
- eSpeak (http://espeak.sourceforge.net)
Copyright (C) 2012 by _Andre Wussow_, 2012, desk@binerry.de
For more informations please visit http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine.
sipcall
-------
Usage:
sipcall [options]
Mandatory options:
-sd=string _Set sip provider domain._
-su=string _Set sip username._
-sp=string _Set sip password._
-pn=string _Set target phone number to call_
-tts=string _Text to speak_
Optional options:
-ttsf=string _TTS speech file name_
-rcf=string _Record call file name_
-mr=int _Repeat message x-times_
-s=int _Silent mode (hide info messages) (0/1)_
_see also source of sipcall-sample.sh_
sipserv
-------
Usage:
sipserv [options]
Commandline:
Mandatory options:
--config-file=string _Set config file_
Optional options:
-s=int _Silent mode (hide info messages) (0/1)_
Config file:
Mandatory options:
sd=string _Set sip provider domain._
su=string _Set sip username._
sp=string _Set sip password._
_and at least one dtmf configuration (X = dtmf-key index):_
dtmf.X.active=int _Set dtmf-setting active (0/1)._
dtmf.X.description=string _Set description._
dtmf.X.tts-intro=string _Set tts intro._
dtmf.X.tts-answer=string _Set tts answer._
dtmf.X.cmd=string _Set dtmf command._
Optional options:
rc=int _Record call (0/1)_
_a sample configuration can be found in sipserv-sample.cfg_
_sipserv can be controlled with ./sipserv-ctrl.sh start and ./sipserv-ctrl.sh stop_
License
-------
This tools are free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This tools are 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
Lesser General Public License for more details.

View file

@ -0,0 +1,58 @@
#!/bin/bash
#
#=================================================================================
# Name : sipcall-sample.sh
# Version : 0.1
#
# Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
#
# Description :
# Sample Script for checking average load and making call with sipcall.
#
# Dependencies:
# - sipcall
#
# References :
# http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine
#
#================================================================================
#This script is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This script 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
#Lesser General Public License for more details.
#================================================================================
# define sip-settings
sip_domain="samplesip.com";
sip_user="12345678";
sip_password="XXXXXX";
play_file="play.wav";
# define number to call
phone_number="0123456789";
# define allowed load limit
maxload=0;
# read actual load values
avgload1="$(uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $1}')";
avgload5="$(uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $2}')";
avgload15="$(uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $3}')";
# check average load within last 5 minutes
avgload="$(echo $avgload5 | awk -F',' '{print $1}')";
check="$(($avgload >= $maxload))";
# creating text to speak
tts="$(echo This is raspberry pi and the load is high. The average load within the last 5 minutes was $avgload5)";
if [ $check = 1 ]; then
# make call with sipcall
$(./sipcall -sd $sip_domain -su $sip_user -sp $sip_password -pn $phone_number -s 1 -mr 2 -tts "$tts" -ttsf $play_file > /dev/null);
fi

581
tools/c/sip-tools/sipcall.c Normal file
View file

@ -0,0 +1,581 @@
/*
=================================================================================
Name : sipcall.c
Version : 0.1 alpha
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
Tool for making automated calls over SIP/VOIP with PJSUA library and eSpeak.
Dependencies:
- PJSUA API (PJSIP)
- eSpeak
References :
http://www.pjsip.org/
http://www.pjsip.org/docs/latest/pjsip/docs/html/group__PJSUA__LIB.htm
http://espeak.sourceforge.net/
http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine
================================================================================
This tool is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This tool 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
Lesser General Public License for more details.
================================================================================
*/
// definition of endianess (e.g. needed on raspberry pi)
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
// includes
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pjsua-lib/pjsua.h>
// some espeak options
#define ESPEAK_LANGUAGE "en"
#define ESPEAK_AMPLITUDE 100
#define ESPEAK_CAPITALS_PITCH 20
#define ESPEAK_SPEED 150
#define ESPEAK_PITCH 75
// disable pjsua logging
#define PJSUA_LOG_LEVEL 0
// struct for app configuration settings
struct app_config {
char *sip_domain;
char *sip_user;
char *sip_password;
char *phone_number;
char *tts;
char *tts_file;
int record_call;
char *record_file;
int repetition_limit;
int silent_mode;
} app_cfg;
// global helper vars
int call_confirmed = 0;
int media_counter = 0;
int app_exiting = 0;
// global vars for pjsua
pjsua_acc_id acc_id;
pjsua_player_id play_id = PJSUA_INVALID_ID;
pjmedia_port *play_port;
pjsua_recorder_id rec_id = PJSUA_INVALID_ID;
// header of helper-methods
static void create_player(pjsua_call_id);
static void create_recorder(pjsua_call_info);
static void log_message(char *);
static void make_sip_call();
static void register_sip(void);
static void setup_sip(void);
static void synthesize_speech(char *);
static void usage(int);
static int try_get_argument(int, char *, char **, int, char *[]);
// header of callback-methods
static void on_call_media_state(pjsua_call_id);
static void on_call_state(pjsua_call_id, pjsip_event *);
static pj_status_t on_media_finished(pjmedia_port *, void *);
static void signal_handler(int);
// header of app-control-methods
static void app_exit();
static void error_exit(const char *, pj_status_t);
// main application
int main(int argc, char *argv[])
{
// first set some default values
app_cfg.tts_file = "play.wav";
app_cfg.record_call = 0;
app_cfg.repetition_limit = 3;
app_cfg.silent_mode = 0;
// parse arguments
if (argc > 1)
{
int arg;
for( arg = 1; arg < argc; arg+=2 )
{
// check if usage info needs to be displayed
if (!strcasecmp(argv[arg], "--help"))
{
// display usage info and exit app
usage(0);
exit(0);
}
// check for sip domain
if (try_get_argument(arg, "-sd", &app_cfg.sip_domain, argc, argv) == 1)
{
continue;
}
// check for sip user
if (try_get_argument(arg, "-su", &app_cfg.sip_user, argc, argv) == 1)
{
continue;
}
// check for sip password
if (try_get_argument(arg, "-sp", &app_cfg.sip_password, argc, argv) == 1)
{
continue;
}
// check for target phone number
if (try_get_argument(arg, "-pn", &app_cfg.phone_number, argc, argv) == 1)
{
continue;
}
// check for text to speak
if (try_get_argument(arg, "-tts", &app_cfg.tts, argc, argv) == 1)
{
continue;
}
// check for record call option
if (try_get_argument(arg, "-ttsf", &app_cfg.tts_file, argc, argv) == 1)
{
continue;
}
// check for record call option
if (try_get_argument(arg, "-rcf", &app_cfg.record_file, argc, argv) == 1)
{
app_cfg.record_call = 1;
continue;
}
// check for message repetition option
char *mr;
if (try_get_argument(arg, "-mr", &mr, argc, argv) == 1)
{
app_cfg.repetition_limit = atoi(mr);
continue;
}
// check for silent mode option
char *s;
try_get_argument(arg, "-s", &s, argc, argv);
if (!strcasecmp(s, "1"))
{
app_cfg.silent_mode = 1;
continue;
}
}
}
else
{
// no arguments specified - display usage info and exit app
usage(1);
exit(1);
}
if (!app_cfg.sip_domain || !app_cfg.sip_user || !app_cfg.sip_password || !app_cfg.phone_number || !app_cfg.tts)
{
// too few arguments specified - display usage info and exit app
usage(1);
exit(1);
}
// print infos
log_message("SIP Call - Simple TTS-based Automated Calls\n");
log_message("===========================================\n");
// register signal handler for break-in-keys (e.g. ctrl+c)
signal(SIGINT, signal_handler);
signal(SIGKILL, signal_handler);
// synthesize speech
synthesize_speech(app_cfg.tts_file);
// setup up sip library pjsua
setup_sip();
// create account and register to sip server
register_sip();
// initiate call
make_sip_call();
// app loop
for (;;) { }
// exit app
app_exit();
return 0;
}
// helper for displaying usage infos
static void usage(int error)
{
if (error == 1)
{
puts("Error, to few arguments.");
puts ("");
}
puts ("Usage:");
puts (" sipcall [options]");
puts ("");
puts ("Mandatory options:");
puts (" -sd=string Set sip provider domain.");
puts (" -su=string Set sip username.");
puts (" -sp=string Set sip password.");
puts (" -pn=string Set target phone number to call");
puts (" -tts=string Text to speak");
puts ("");
puts ("Optional options:");
puts (" -ttsf=string TTS speech file name to save text");
puts (" -rcf=string Record call file name to save answer");
puts (" -mr=int Repeat message x-times");
puts (" -s=int Silent mode (hide info messages) (0/1)");
puts ("");
fflush(stdout);
}
// helper for parsing command-line-argument
static int try_get_argument(int arg, char *arg_id, char **arg_val, int argc, char *argv[])
{
int found = 0;
// check if actual argument is searched argument
if (!strcasecmp(argv[arg], arg_id))
{
// check if actual argument has a value
if (argc >= (arg+1))
{
// set value
*arg_val = argv[arg+1];
found = 1;
}
}
return found;
}
// helper for logging messages to console (disabled if silent mode is active)
static void log_message(char *message)
{
if (!app_cfg.silent_mode)
{
fprintf(stderr, message);
}
}
// helper for setting up sip library pjsua
static void setup_sip(void)
{
pj_status_t status;
log_message("Setting up pjsua ... ");
// create pjsua
status = pjsua_create();
if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);
// configure pjsua
pjsua_config cfg;
pjsua_config_default(&cfg);
// enable just 1 simultaneous call
cfg.max_calls = 1;
// callback configuration
cfg.cb.on_call_media_state = &on_call_media_state;
cfg.cb.on_call_state = &on_call_state;
// logging configuration
pjsua_logging_config log_cfg;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = PJSUA_LOG_LEVEL;
// initialize pjsua
status = pjsua_init(&cfg, &log_cfg, NULL);
if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
// add udp transport
pjsua_transport_config udpcfg;
pjsua_transport_config_default(&udpcfg);
udpcfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &udpcfg, NULL);
if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
// initialization is done, start pjsua
status = pjsua_start();
if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
// disable sound - use null sound device
status = pjsua_set_null_snd_dev();
if (status != PJ_SUCCESS) error_exit("Error disabling audio", status);
log_message("Done.\n");
}
// helper for creating and registering sip-account
static void register_sip(void)
{
pj_status_t status;
log_message("Registering account ... ");
// prepare account configuration
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
// build sip-user-url
char sip_user_url[40];
sprintf(sip_user_url, "sip:%s@%s", app_cfg.sip_user, app_cfg.sip_domain);
// build sip-provder-url
char sip_provider_url[40];
sprintf(sip_provider_url, "sip:%s", app_cfg.sip_domain);
// create and define account
cfg.id = pj_str(sip_user_url);
cfg.reg_uri = pj_str(sip_provider_url);
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str(app_cfg.sip_domain);
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str(app_cfg.sip_user);
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str(app_cfg.sip_password);
// add account
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS) error_exit("Error adding account", status);
log_message("Done.\n");
}
// helper for making calls over sip-account
static void make_sip_call()
{
pj_status_t status;
log_message("Starting call ... ");
// build target sip-url
char sip_target_url[40];
sprintf(sip_target_url, "sip:%s@%s", app_cfg.phone_number, app_cfg.sip_domain);
// start call with sip-url
pj_str_t uri = pj_str(sip_target_url);
status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL);
if (status != PJ_SUCCESS) error_exit("Error making call", status);
log_message("Done.\n");
}
// helper for creating call-media-player
static void create_player(pjsua_call_id call_id)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
pj_str_t name;
pj_status_t status = PJ_ENOTFOUND;
log_message("Creating player ... ");
// create player for playback media
status = pjsua_player_create(pj_cstr(&name, app_cfg.tts_file), 0, &play_id);
if (status != PJ_SUCCESS) error_exit("Error playing sound-playback", status);
// connect active call to media player
pjsua_conf_connect(pjsua_player_get_conf_port(play_id), ci.conf_slot);
// get media port (play_port) from play_id
status = pjsua_player_get_port(play_id, &play_port);
if (status != PJ_SUCCESS) error_exit("Error getting sound player port", status);
// register media finished callback
status = pjmedia_wav_player_set_eof_cb(play_port, NULL, &on_media_finished);
if (status != PJ_SUCCESS) error_exit("Error adding sound-playback callback", status);
log_message("Done.\n");
}
// helper for creating call-recorder
static void create_recorder(pjsua_call_info ci)
{
// specify target file
pj_str_t rec_file = pj_str(app_cfg.record_file);
pj_status_t status = PJ_ENOTFOUND;
log_message("Creating recorder ... ");
// Create recorder for call
status = pjsua_recorder_create(&rec_file, 0, NULL, 0, 0, &rec_id);
if (status != PJ_SUCCESS) error_exit("Error recording answer", status);
// connect active call to call recorder
pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(rec_id);
pjsua_conf_connect(ci.conf_slot, rec_port);
log_message("Done.\n");
}
// synthesize speech / create message via espeak
static void synthesize_speech(char *file)
{
log_message("Synthesizing speech ... ");
int speech_status = -1;
char speech_command[200];
sprintf(speech_command, "espeak -v%s -a%i -k%i -s%i -p%i -w %s '%s'", ESPEAK_LANGUAGE, ESPEAK_AMPLITUDE, ESPEAK_CAPITALS_PITCH, ESPEAK_SPEED, ESPEAK_PITCH, file, app_cfg.tts);
speech_status = system(speech_command);
if (speech_status != 0) error_exit("Error while creating phone text", speech_status);
log_message("Done.\n");
}
// handler for call-media-state-change-events
static void on_call_media_state(pjsua_call_id call_id)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
pj_status_t status = PJ_ENOTFOUND;
// check state if call is established/active
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
log_message("Call media activated.\n");
// create and start media player
create_player(call_id);
// create and start call recorder
if (app_cfg.record_call)
{
create_recorder(ci);
}
}
}
// handler for call-state-change-events
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
// prevent warning about unused argument e
PJ_UNUSED_ARG(e);
// check call state
if (ci.state == PJSIP_INV_STATE_CONFIRMED)
{
log_message("Call confirmed.\n");
call_confirmed = 1;
// ensure that message is played from start
if (play_id != PJSUA_INVALID_ID)
{
pjmedia_wav_player_port_set_pos(play_port, 0);
}
}
if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
{
log_message("Call disconnected.\n");
// exit app if call is finished/disconnected
app_exit();
}
}
// handler for media-finished-events
static pj_status_t on_media_finished(pjmedia_port *media_port, void *user_data)
{
PJ_UNUSED_ARG(media_port);
PJ_UNUSED_ARG(user_data);
if (call_confirmed)
{
// count repetition
media_counter++;
// exit app if repetition limit is reached
if (app_cfg.repetition_limit <= media_counter)
{
app_exit();
}
}
pj_status_t status;
return status;
}
// handler for "break-in-key"-events (e.g. ctrl+c)
static void signal_handler(int signal)
{
// exit app
app_exit();
}
// clean application exit
static void app_exit()
{
if (!app_exiting)
{
app_exiting = 1;
log_message("Stopping application ... ");
// check if player/recorder is active and stop them
if (play_id != -1) pjsua_player_destroy(play_id);
if (rec_id != -1) pjsua_recorder_destroy(rec_id);
// hangup open calls and stop pjsua
pjsua_call_hangup_all();
pjsua_destroy();
log_message("Done.\n");
exit(0);
}
}
// display error and exit application
static void error_exit(const char *title, pj_status_t status)
{
if (!app_exiting)
{
app_exiting = 1;
pjsua_perror("SIP Call", title, status);
// check if player/recorder is active and stop them
if (play_id != -1) pjsua_player_destroy(play_id);
if (rec_id != -1) pjsua_recorder_destroy(rec_id);
// hangup open calls and stop pjsua
pjsua_call_hangup_all();
pjsua_destroy();
exit(1);
}
}

View file

@ -0,0 +1,44 @@
#!/bin/bash
#
#=================================================================================
# Name : sipserv-ctrl.sh
# Version : 0.1
#
# Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
#
# Description :
# Sample Script for controlling sipserv.
#
# Dependencies:
# - sipcall
#
# References :
# http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine
#
#================================================================================
#This script is free software; you can redistribute it and/or
#modify it under the terms of the GNU Lesser General Public
#License as published by the Free Software Foundation; either
#version 2.1 of the License, or (at your option) any later version.
#
#This script 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
#Lesser General Public License for more details.
#================================================================================
# define config-file
serv_cfg="sipserv.cfg";
if [ $1 = "start" ]; then
# start sipserv in background
$(./sipserv -s 1 --config-file $serv_cfg > /dev/null &);
echo "sipserv started.";
fi
if [ $1 = "stop" ]; then
# stop sipserv
pid="$(ps aux | awk '/[s]ipserv/ {print $2}' | head -1)";
$(kill $pid > /dev/null);
echo "sipserv stopped.";
fi

View file

@ -0,0 +1,65 @@
# SIP account data
sd=samplesip.com
su=12345678
sp=XXXXXX
# disable call recording
rc=0
# intro message
tts=Hello, this is raspberry pi and this are your options:
# dtmf configuration
dtmf.1.active=1
dtmf.1.description=Get average load
dtmf.1.tts-intro=Press 1 to get the average system load within last 5 minutes.
dtmf.1.tts-answer=The average load within last 5 minutes is %s.
dtmf.1.cmd=uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $2}'
dtmf.2.active=1
dtmf.2.description=Get free memory
dtmf.2.tts-intro=Press 2 to get the actual free memory.
dtmf.2.tts-answer=The currently free memory is %s megabytes.
dtmf.2.cmd=free |awk '/^Mem:/{print ($2/1024)}'
dtmf.3.active=0
dtmf.3.description=
dtmf.3.tts-intro=
dtmf.3.tts-answer=
dtmf.3.cmd=
dtmf.4.active=0
dtmf.4.description=
dtmf.4.tts-intro=
dtmf.4.tts-answer=
dtmf.4.cmd=
dtmf.5.active=0
dtmf.5.description=
dtmf.5.tts-intro=
dtmf.5.tts-answer=
dtmf.5.cmd=
dtmf.6.active=0
dtmf.6.description=
dtmf.6.tts-intro=
dtmf.6.tts-answer=
dtmf.6.cmd=
dtmf.7.active=0
dtmf.7.description=
dtmf.7.tts-intro=
dtmf.7.tts-answer=
dtmf.7.cmd=
dtmf.8.active=0
dtmf.8.description=
dtmf.8.tts-intro=
dtmf.8.tts-answer=
dtmf.8.cmd=
dtmf.9.active=0
dtmf.9.description=
dtmf.9.tts-intro=
dtmf.9.tts-answer=
dtmf.9.cmd=

823
tools/c/sip-tools/sipserv.c Normal file
View file

@ -0,0 +1,823 @@
/*
=================================================================================
Name : sipserv.c
Version : 0.1
Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de
Description :
Tool for automated, flexible answered calls over SIP/VOIP with PJSUA library and eSpeak.
Dependencies:
- PJSUA API (PJSIP)
- eSpeak
References :
http://www.pjsip.org/
http://www.pjsip.org/docs/latest/pjsip/docs/html/group__PJSUA__LIB.htm
http://espeak.sourceforge.net/
http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine
================================================================================
This tool is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This tool 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
Lesser General Public License for more details.
================================================================================
*/
// definition of endianess (e.g. needed on raspberry pi)
#define PJ_IS_LITTLE_ENDIAN 1
#define PJ_IS_BIG_ENDIAN 0
// includes
#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pjsua-lib/pjsua.h>
// some espeak options
#define ESPEAK_LANGUAGE "en"
#define ESPEAK_AMPLITUDE 100
#define ESPEAK_CAPITALS_PITCH 20
#define ESPEAK_SPEED 125
#define ESPEAK_PITCH 75
// disable pjsua logging
#define PJSUA_LOG_LEVEL 0
// define max supported dtmf settings
#define MAX_DTMF_SETTINGS 9
// struct for app dtmf settings
struct dtmf_config {
int id;
int active;
int processing_active;
char *description;
char *tts_intro;
char *tts_answer;
char *cmd;
};
// struct for app configuration settings
struct app_config {
char *sip_domain;
char *sip_user;
char *sip_password;
int record_calls;
int silent_mode;
char *tts;
char *log_file;
struct dtmf_config dtmf_cfg[MAX_DTMF_SETTINGS];
} app_cfg;
// global holder vars for further app arguments
char *tts_file = "play.wav";
char *tts_answer_file = "ans.wav";
char *rec_ans_file = "rec.wav";
// global helper vars
int call_confirmed = 0;
int media_counter = 0;
int app_exiting = 0;
// global vars for pjsua
pjsua_acc_id acc_id;
pjsua_player_id play_id = PJSUA_INVALID_ID;
pjmedia_port *play_port;
pjsua_recorder_id rec_id = PJSUA_INVALID_ID;
pjsua_call_id current_call = PJSUA_INVALID_ID;
// header of helper-methods
static void create_player(pjsua_call_id, char *);
static void create_recorder(pjsua_call_info);
static void log_message(char *);
static void parse_config_file(char *);
static void register_sip(void);
static void setup_sip(void);
static int synthesize_speech(char *, char *);
static void usage(int);
static int try_get_argument(int, char *, char **, int, char *[]);
// header of callback-methods
static void on_incoming_call(pjsua_acc_id, pjsua_call_id, pjsip_rx_data *);
static void on_call_media_state(pjsua_call_id);
static void on_call_state(pjsua_call_id, pjsip_event *);
static void on_dtmf_digit(pjsua_call_id, int);
static void signal_handler(int);
static char *trim_string(char *);
// header of app-control-methods
static void app_exit();
static void error_exit(const char *, pj_status_t);
// main application
int main(int argc, char *argv[])
{
// first set some default values
app_cfg.record_calls = 0;
app_cfg.silent_mode = 0;
// init dtmf settings (dtmf 0 is reserved for exit call)
int i;
for (i = 0; i < MAX_DTMF_SETTINGS; i++)
{
struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[i];
d_cfg->id = i+1;
d_cfg->active = 0;
d_cfg->processing_active = 0;
}
// parse arguments
if (argc > 1)
{
int arg;
for( arg = 1; arg < argc; arg+=2 )
{
// check if usage info needs to be displayed
if (!strcasecmp(argv[arg], "--help"))
{
// display usage info and exit app
usage(0);
exit(0);
}
// check for config file location
if (!strcasecmp(argv[arg], "--config-file"))
{
if (argc >= (arg+1))
{
app_cfg.log_file = argv[arg+1];
}
continue;
}
// check for silent mode option
char *s;
try_get_argument(arg, "-s", &s, argc, argv);
if (!strcasecmp(s, "1"))
{
app_cfg.silent_mode = 1;
continue;
}
}
}
if (!app_cfg.log_file)
{
// too few arguments specified - display usage info and exit app
usage(1);
exit(1);
}
// read app configuration from config file
parse_config_file(app_cfg.log_file);
if (!app_cfg.sip_domain || !app_cfg.sip_user || !app_cfg.sip_password)
{
// too few arguments specified - display usage info and exit app
usage(1);
exit(1);
}
// print infos
log_message("SIP Call - Simple TTS/DTMF-based answering machine\n");
log_message("==================================================\n");
// register signal handler for break-in-keys (e.g. ctrl+c)
signal(SIGINT, signal_handler);
signal(SIGKILL, signal_handler);
// generate texts
log_message("Generating texts ... ");
char tts_buffer[1024];
strcpy(tts_buffer, app_cfg.tts);
strcat(tts_buffer, " ");
for (i = 0; i < MAX_DTMF_SETTINGS; i++)
{
struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[i];
if (d_cfg->active == 1)
{
strcat(tts_buffer, d_cfg->tts_intro);
strcat(tts_buffer, " ");
}
}
log_message("Done.\n");
// synthesizing speech
log_message("Synthesizing speech ... ");
int synth_status = -1;
synth_status = synthesize_speech(tts_buffer, tts_file);
if (synth_status != 0) error_exit("Error while creating phone text", synth_status);
log_message("Done.\n");
// setup up sip library pjsua
setup_sip();
// create account and register to sip server
register_sip();
// app loop
for (;;) { }
// exit app
app_exit();
return 0;
}
// helper for displaying usage infos
static void usage(int error)
{
if (error == 1)
{
puts("Error, to few arguments.");
puts ("");
}
puts ("Usage:");
puts (" sipserv [options]");
puts ("");
puts ("Commandline:");
puts ("Mandatory options:");
puts (" --config-file=string Set config file");
puts ("");
puts ("Optional options:");
puts (" -s=int Silent mode (hide info messages) (0/1)");
puts ("");
puts ("");
puts ("Config file:");
puts ("Mandatory options:");
puts (" sd=string Set sip provider domain.");
puts (" su=string Set sip username.");
puts (" sp=string Set sip password.");
puts ("");
puts (" and at least one dtmf configuration (X = dtmf-key index):");
puts (" dtmf.X.active=int Set dtmf-setting active (0/1).");
puts (" dtmf.X.description=string Set description.");
puts (" dtmf.X.tts-intro=string Set tts intro.");
puts (" dtmf.X.tts-answer=string Set tts answer.");
puts (" dtmf.X.cmd=string Set dtmf command.");
puts ("");
puts ("Optional options:");
puts (" rc=int Record call (0/1)");
puts ("");
fflush(stdout);
}
// helper for parsing command-line-argument
static int try_get_argument(int arg, char *arg_id, char **arg_val, int argc, char *argv[])
{
int found = 0;
// check if actual argument is searched argument
if (!strcasecmp(argv[arg], arg_id))
{
// check if actual argument has a value
if (argc >= (arg+1))
{
// set value
*arg_val = argv[arg+1];
found = 1;
}
}
return found;
}
// helper for parsing config file
static void parse_config_file(char *cfg_file)
{
// open config file
char line[200];
FILE *file = fopen(cfg_file, "r");
if (file!=NULL)
{
// start parsing file
while(fgets(line, 200, file) != NULL)
{
char *arg, *val;
// ignore comments and just new lines
if(line[0] == '#') continue;
if(line[0] == '\n') continue;
// split string at '='-char
arg = strtok(line, "=");
if (arg == NULL) continue;
val = strtok(NULL, "=");
// check for new line char and remove it
char *nl_check;
nl_check = strstr (val, "\n");
if (nl_check != NULL) strncpy(nl_check, " ", 1);
// remove trailing spaces
// duplicate string for having own instance of it
char *arg_val = strdup(val);
// check for sip domain argument
if (!strcasecmp(arg, "sd"))
{
app_cfg.sip_domain = trim_string(arg_val);
continue;
}
// check for sip user argument
if (!strcasecmp(arg, "su"))
{
app_cfg.sip_user = trim_string(arg_val);
continue;
}
// check for sip domain argument
if (!strcasecmp(arg, "sp"))
{
app_cfg.sip_password = trim_string(arg_val);
continue;
}
// check for record calls argument
if (!strcasecmp(arg, "rc"))
{
app_cfg.record_calls = atoi(val);
continue;
}
// check for silent mode argument
if (!strcasecmp(arg, "s"))
{
app_cfg.silent_mode = atoi(val);
continue;
}
// check for tts intro
if (!strcasecmp(arg, "tts"))
{
app_cfg.tts = arg_val;
continue;
}
// check for a dtmf argument
char dtmf_id[1];
char dtmf_setting[25];
if(sscanf(arg, "dtmf.%1[^.].%s", dtmf_id, dtmf_setting) == 2)
{
// parse dtmf id (key)
int d_id;
d_id = atoi(dtmf_id);
// check if actual dtmf id blasts maxium settings
if (d_id >= MAX_DTMF_SETTINGS) continue;
// get pointer to actual dtmf_cfg entry
struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[d_id-1];
// check for dtmf active setting
if (!strcasecmp(dtmf_setting, "active"))
{
d_cfg->active = atoi(val);
continue;
}
// check for dtmf description setting
if (!strcasecmp(dtmf_setting, "description"))
{
d_cfg->description = arg_val;
continue;
}
// check for dtmf tts intro setting
if (!strcasecmp(dtmf_setting, "tts-intro"))
{
d_cfg->tts_intro = arg_val;
continue;
}
// check for dtmf tts answer setting
if (!strcasecmp(dtmf_setting, "tts-answer"))
{
d_cfg->tts_answer = arg_val;
continue;
}
// check for dtmf cmd setting
if (!strcasecmp(dtmf_setting, "cmd"))
{
d_cfg->cmd = arg_val;
continue;
}
}
// write warning if unknown configuration setting is found
char warning[200];
sprintf(warning, "Warning: Unknown configuration with arg '%s' and val '%s'\n", arg, val);
log_message(warning);
}
}
else
{
// return if config file not found
log_message("Error while parsing config file: Not found.\n");
exit(1);
}
}
// helper for removing leading and trailing strings (source taken from kernel source, lib/string.c)
static char *trim_string(char *str)
{
while (isspace(*str)) ++str;
char *s = (char *)str;
size_t size;
char *end;
size = strlen(s);
if (!size) return s;
end = s + size - 1;
while (end >= s && isspace(*end)) end--;
*(end + 1) = '\0';
return s;
}
// helper for logging messages to console (disabled if silent mode is active)
static void log_message(char *message)
{
if (!app_cfg.silent_mode)
{
fprintf(stderr, message);
}
}
// helper for setting up sip library pjsua
static void setup_sip(void)
{
pj_status_t status;
log_message("Setting up pjsua ... ");
// create pjsua
status = pjsua_create();
if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status);
// configure pjsua
pjsua_config cfg;
pjsua_config_default(&cfg);
// enable just 1 simultaneous call
cfg.max_calls = 1;
// callback configuration
cfg.cb.on_incoming_call = &on_incoming_call;
cfg.cb.on_call_media_state = &on_call_media_state;
cfg.cb.on_call_state = &on_call_state;
cfg.cb.on_dtmf_digit = &on_dtmf_digit;
// logging configuration
pjsua_logging_config log_cfg;
pjsua_logging_config_default(&log_cfg);
log_cfg.console_level = PJSUA_LOG_LEVEL;
// media configuration
pjsua_media_config media_cfg;
pjsua_media_config_default(&media_cfg);
media_cfg.snd_play_latency = 100;
media_cfg.clock_rate = 8000;
media_cfg.snd_clock_rate = 8000;
media_cfg.quality = 10;
// initialize pjsua
status = pjsua_init(&cfg, &log_cfg, &media_cfg);
if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status);
// add udp transport
pjsua_transport_config udpcfg;
pjsua_transport_config_default(&udpcfg);
udpcfg.port = 5060;
status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &udpcfg, NULL);
if (status != PJ_SUCCESS) error_exit("Error creating transport", status);
// initialization is done, start pjsua
status = pjsua_start();
if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status);
// disable sound - use null sound device
status = pjsua_set_null_snd_dev();
if (status != PJ_SUCCESS) error_exit("Error disabling audio", status);
log_message("Done.\n");
}
// helper for creating and registering sip-account
static void register_sip(void)
{
pj_status_t status;
log_message("Registering account ... ");
// prepare account configuration
pjsua_acc_config cfg;
pjsua_acc_config_default(&cfg);
// build sip-user-url
char sip_user_url[40];
sprintf(sip_user_url, "sip:%s@%s", app_cfg.sip_user, app_cfg.sip_domain);
// build sip-provder-url
char sip_provider_url[40];
sprintf(sip_provider_url, "sip:%s", app_cfg.sip_domain);
// create and define account
cfg.id = pj_str(sip_user_url);
cfg.reg_uri = pj_str(sip_provider_url);
cfg.cred_count = 1;
cfg.cred_info[0].realm = pj_str(app_cfg.sip_domain);
cfg.cred_info[0].scheme = pj_str("digest");
cfg.cred_info[0].username = pj_str(app_cfg.sip_user);
cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD;
cfg.cred_info[0].data = pj_str(app_cfg.sip_password);
// add account
status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id);
if (status != PJ_SUCCESS) error_exit("Error adding account", status);
log_message("Done.\n");
}
// helper for creating call-media-player
static void create_player(pjsua_call_id call_id, char *file)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
pj_str_t name;
pj_status_t status = PJ_ENOTFOUND;
log_message("Creating player ... ");
// create player for playback media
status = pjsua_player_create(pj_cstr(&name, file), PJMEDIA_FILE_NO_LOOP, &play_id);
if (status != PJ_SUCCESS) error_exit("Error playing sound-playback", status);
// connect active call to media player
pjsua_conf_connect(pjsua_player_get_conf_port(play_id), ci.conf_slot);
// get media port (play_port) from play_id
status = pjsua_player_get_port(play_id, &play_port);
if (status != PJ_SUCCESS) error_exit("Error getting sound player port", status);
log_message("Done.\n");
}
// helper for creating call-recorder
static void create_recorder(pjsua_call_info ci)
{
// specify target file
pj_str_t rec_file = pj_str(rec_ans_file);
pj_status_t status = PJ_ENOTFOUND;
log_message("Creating recorder ... ");
// Create recorder for call
status = pjsua_recorder_create(&rec_file, 0, NULL, 0, 0, &rec_id);
if (status != PJ_SUCCESS) error_exit("Error recording answer", status);
// connect active call to call recorder
pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(rec_id);
pjsua_conf_connect(ci.conf_slot, rec_port);
log_message("Done.\n");
}
// synthesize speech / create message via espeak
static int synthesize_speech(char *speech, char *file)
{
int speech_status = -1;
char speech_command[1024];
sprintf(speech_command, "espeak -v%s -a%i -k%i -s%i -p%i -w %s '%s'", ESPEAK_LANGUAGE, ESPEAK_AMPLITUDE, ESPEAK_CAPITALS_PITCH, ESPEAK_SPEED, ESPEAK_PITCH, file, speech);
speech_status = system(speech_command);
return speech_status;
}
// handler for incoming-call-events
static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
PJ_UNUSED_ARG(acc_id);
PJ_UNUSED_ARG(rdata);
current_call = call_id;
// log call info
char info[100];
sprintf(info, "Incoming call from %s\n", ci.remote_info.ptr);
log_message(info);
// automatically answer incoming call with 200 status/OK
pjsua_call_answer(call_id, 200, NULL, NULL);
}
// handler for call-media-state-change-events
static void on_call_media_state(pjsua_call_id call_id)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
pj_status_t status = PJ_ENOTFOUND;
// check state if call is established/active
if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) {
log_message("Call media activated.\n");
// create and start media player
create_player(call_id, tts_file);
// create and start call recorder
if (app_cfg.record_calls)
{
create_recorder(ci);
}
}
}
// handler for call-state-change-events
static void on_call_state(pjsua_call_id call_id, pjsip_event *e)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
// prevent warning about unused argument e
PJ_UNUSED_ARG(e);
// check call state
if (ci.state == PJSIP_INV_STATE_CONFIRMED)
{
log_message("Call confirmed.\n");
call_confirmed = 1;
// ensure that message is played from start
if (play_id != PJSUA_INVALID_ID)
{
pjmedia_wav_player_port_set_pos(play_port, 0);
}
}
if (ci.state == PJSIP_INV_STATE_DISCONNECTED)
{
log_message("Call disconnected.\n");
// disable player
if (play_id != -1) pjsua_player_destroy(play_id);
}
}
// handler for dtmf-events
static void on_dtmf_digit(pjsua_call_id call_id, int digit)
{
// get call infos
pjsua_call_info ci;
pjsua_call_get_info(call_id, &ci);
// work on detected dtmf digit
int dtmf_key = digit - 48;
char info[100];
sprintf(info, "DTMF command detected: %i\n", dtmf_key);
log_message(info);
struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[dtmf_key-1];
if (d_cfg->processing_active == 0)
{
d_cfg->processing_active = 1;
if (d_cfg->active == 1)
{
log_message("Active DTMF command found for received digit.\n");
log_message("Creating answer ... ");
int error = 0;
FILE *fp;
fp = popen(d_cfg->cmd, "r");
if (fp == NULL) {
error = 1;
log_message(" (Failed to run command) ");
}
char result[20];
if (!error)
{
if (fgets(result, sizeof(result)-1, fp) == NULL)
{
error = 1;
log_message(" (Failed to read result) ");
}
}
if (!error)
{
if (play_id != -1) pjsua_player_destroy(play_id);
char tts_buffer[200];
sprintf(tts_buffer, d_cfg->tts_answer, result);
int synth_status = -1;
synth_status = synthesize_speech(tts_buffer, tts_answer_file);
if (synth_status != 0) log_message(" (Failed to synthesize speech) ");
create_player(call_id, tts_answer_file);
}
log_message("Done.\n");
}
else
{
log_message("No active DTMF command found for received digit.\n");
}
d_cfg->processing_active = 0;
}
else
{
log_message("DTMF command dropped - state is actual processing.\n");
}
}
// handler for "break-in-key"-events (e.g. ctrl+c)
static void signal_handler(int signal)
{
// exit app
app_exit();
}
// clean application exit
static void app_exit()
{
if (!app_exiting)
{
app_exiting = 1;
log_message("Stopping application ... ");
// check if player/recorder is active and stop them
if (play_id != -1) pjsua_player_destroy(play_id);
if (rec_id != -1) pjsua_recorder_destroy(rec_id);
// hangup open calls and stop pjsua
pjsua_call_hangup_all();
pjsua_destroy();
log_message("Done.\n");
exit(0);
}
}
// display error and exit application
static void error_exit(const char *title, pj_status_t status)
{
if (!app_exiting)
{
app_exiting = 1;
pjsua_perror("SIP Call", title, status);
// check if player/recorder is active and stop them
if (play_id != -1) pjsua_player_destroy(play_id);
if (rec_id != -1) pjsua_recorder_destroy(rec_id);
// hangup open calls and stop pjsua
pjsua_call_hangup_all();
pjsua_destroy();
exit(1);
}
}