server migration
This commit is contained in:
commit
aec284f125
33 changed files with 5412 additions and 0 deletions
17
README.md
Normal file
17
README.md
Normal 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.
|
847
libraries/c/PCD8544/PCD8544.c
Normal file
847
libraries/c/PCD8544/PCD8544.c
Normal 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--;
|
||||||
|
}
|
||||||
|
}
|
86
libraries/c/PCD8544/PCD8544.h
Normal file
86
libraries/c/PCD8544/PCD8544.h
Normal 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);
|
23
libraries/c/PCD8544/README.md
Normal file
23
libraries/c/PCD8544/README.md
Normal 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.
|
86
libraries/c/PCD8544/samples/PCD8544.h
Normal file
86
libraries/c/PCD8544/samples/PCD8544.h
Normal 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);
|
219
libraries/c/PCD8544/samples/pcd8544_rpi.c
Normal file
219
libraries/c/PCD8544/samples/pcd8544_rpi.c
Normal 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;
|
||||||
|
}
|
155
libraries/c/PCD8544/samples/pcd8544_test.c
Normal file
155
libraries/c/PCD8544/samples/pcd8544_test.c
Normal 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;
|
||||||
|
}
|
129
libraries/c/PCD8544/samples/pcd8544_test2.c
Normal file
129
libraries/c/PCD8544/samples/pcd8544_test2.c
Normal 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;
|
||||||
|
}
|
24
prototyping/fritzing/parts/board/README.md
Normal file
24
prototyping/fritzing/parts/board/README.md
Normal 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.
|
BIN
prototyping/fritzing/parts/board/Raspberry Pi.fzpz
Normal file
BIN
prototyping/fritzing/parts/board/Raspberry Pi.fzpz
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 54 KiB |
|
@ -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 |
|
@ -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 |
|
@ -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 |
24
prototyping/fritzing/projects/i2c-shifter/README.md
Normal file
24
prototyping/fritzing/projects/i2c-shifter/README.md
Normal 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.
|
BIN
prototyping/fritzing/projects/i2c-shifter/i2c_shifter.fzz
Normal file
BIN
prototyping/fritzing/projects/i2c-shifter/i2c_shifter.fzz
Normal file
Binary file not shown.
65
snippets/c/i2c-arduino/Arduino/I2CSlave/Commander.cpp
Normal file
65
snippets/c/i2c-arduino/Arduino/I2CSlave/Commander.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
56
snippets/c/i2c-arduino/Arduino/I2CSlave/Commander.h
Normal file
56
snippets/c/i2c-arduino/Arduino/I2CSlave/Commander.h
Normal 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
|
227
snippets/c/i2c-arduino/Arduino/I2CSlave/I2CSlave.ino
Normal file
227
snippets/c/i2c-arduino/Arduino/I2CSlave/I2CSlave.ino
Normal 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;
|
||||||
|
}
|
22
snippets/c/i2c-arduino/README.md
Normal file
22
snippets/c/i2c-arduino/README.md
Normal 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.
|
128
snippets/c/i2c-arduino/i2c-arduino.c
Normal file
128
snippets/c/i2c-arduino/i2c-arduino.c
Normal 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
106
snippets/c/i2c/rtc_ds1307.c
Normal 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
34
snippets/c/printtest/ip.c
Normal 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;
|
||||||
|
}
|
45
snippets/c/printtest/time.c
Normal file
45
snippets/c/printtest/time.c
Normal 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;
|
||||||
|
}
|
4
snippets/c/watchdog/Makefile
Normal file
4
snippets/c/watchdog/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
all: wdt_test.c
|
||||||
|
cc -o wdt_test wdt_test.c
|
||||||
|
clean:
|
||||||
|
rm -rf wdt_test
|
77
snippets/c/watchdog/wdt_test.c
Normal file
77
snippets/c/watchdog/wdt_test.c
Normal 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;
|
||||||
|
}
|
11
tools/c/sip-tools/Makefile
Normal file
11
tools/c/sip-tools/Makefile
Normal 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
|
85
tools/c/sip-tools/README.md
Normal file
85
tools/c/sip-tools/README.md
Normal 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.
|
58
tools/c/sip-tools/sipcall-sample.sh
Normal file
58
tools/c/sip-tools/sipcall-sample.sh
Normal 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
581
tools/c/sip-tools/sipcall.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
44
tools/c/sip-tools/sipserv-ctrl.sh
Normal file
44
tools/c/sip-tools/sipserv-ctrl.sh
Normal 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
|
65
tools/c/sip-tools/sipserv-sample.cfg
Normal file
65
tools/c/sip-tools/sipserv-sample.cfg
Normal 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
823
tools/c/sip-tools/sipserv.c
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue