├── README.md ├── libraries └── c │ └── PCD8544 │ ├── PCD8544.c │ ├── PCD8544.h │ ├── README.md │ └── samples │ ├── pcd8544_rpi.c │ ├── pcd8544_test.c │ └── pcd8544_test2.c ├── prototyping └── fritzing │ ├── parts │ └── board │ │ ├── README.md │ │ ├── Raspberry Pi.fzpz │ │ └── svgs │ │ ├── controller_raspberry_pi_breadboard.svg │ │ ├── controller_raspberry_pi_logo.svg │ │ ├── controller_raspberry_pi_pcb.svg │ │ └── controller_raspberry_pi_schematic.svg │ └── projects │ └── i2c-shifter │ ├── README.md │ └── i2c_shifter.fzz ├── snippets └── c │ ├── i2c-arduino │ ├── Arduino │ │ └── I2CSlave │ │ │ ├── Commander.cpp │ │ │ ├── Commander.h │ │ │ └── I2CSlave.ino │ ├── README.md │ └── i2c-arduino.c │ ├── i2c │ └── rtc_ds1307.c │ └── watchdog │ ├── Makefile │ └── wdt_test.c └── tools └── c └── sip-tools ├── Makefile ├── README.md ├── sipcall-sample.sh ├── sipcall.c ├── sipserv-ctrl.sh ├── sipserv-sample.cfg └── sipserv.c /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binerry/RaspberryPi/a80745bbd098e7f49aba6e51499cadca98d9e457/README.md -------------------------------------------------------------------------------- /libraries/c/PCD8544/PCD8544.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : PCD8544.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2010 Limor Fried, Adafruit Industries 7 | CORTEX-M3 version by Le Dang Dung, 2011 LeeDangDung@gmail.com (tested on LPC1769) 8 | Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de 9 | 10 | Description : 11 | A simple PCD8544 LCD (Nokia3310/5110) driver. Target board is Raspberry Pi. 12 | This driver uses 5 GPIOs on target board with a bit-bang SPI implementation 13 | (hence, may not be as fast). 14 | Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/) 15 | 16 | Recommended connection (http://www.raspberrypi.org/archives/384): 17 | LCD pins Raspberry Pi 18 | LCD1 - GND P06 - GND 19 | LCD2 - VCC P01 - 3.3V 20 | LCD3 - CLK P11 - GPIO0 21 | LCD4 - Din P12 - GPIO1 22 | LCD5 - D/C P13 - GPIO2 23 | LCD6 - CS P15 - GPIO3 24 | LCD7 - RST P16 - GPIO4 25 | LCD8 - LED P01 - 3.3V 26 | 27 | References : 28 | http://www.arduino.cc/playground/Code/PCD8544 29 | http://ladyada.net/products/nokia5110/ 30 | http://code.google.com/p/meshphone/ 31 | 32 | ================================================================================ 33 | This library is free software; you can redistribute it and/or 34 | modify it under the terms of the GNU Lesser General Public 35 | License as published by the Free Software Foundation; either 36 | version 2.1 of the License, or (at your option) any later version. 37 | 38 | This library is distributed in the hope that it will be useful, 39 | but WITHOUT ANY WARRANTY; without even the implied warranty of 40 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 41 | Lesser General Public License for more details. 42 | ================================================================================ 43 | */ 44 | #include 45 | #include "PCD8544.h" 46 | 47 | // An abs() :) 48 | #define abs(a) (((a) < 0) ? -(a) : (a)) 49 | 50 | // bit set 51 | #define _BV(bit) (0x1 << (bit)) 52 | 53 | // LCD port variables 54 | static uint8_t cursor_x, cursor_y, textsize, textcolor; 55 | static int8_t _din, _sclk, _dc, _rst, _cs; 56 | 57 | // font bitmap 58 | static unsigned char font[] = { 59 | 0x00, 0x00, 0x00, 0x00, 0x00, 60 | 0x3E, 0x5B, 0x4F, 0x5B, 0x3E, 61 | 0x3E, 0x6B, 0x4F, 0x6B, 0x3E, 62 | 0x1C, 0x3E, 0x7C, 0x3E, 0x1C, 63 | 0x18, 0x3C, 0x7E, 0x3C, 0x18, 64 | 0x1C, 0x57, 0x7D, 0x57, 0x1C, 65 | 0x1C, 0x5E, 0x7F, 0x5E, 0x1C, 66 | 0x00, 0x18, 0x3C, 0x18, 0x00, 67 | 0xFF, 0xE7, 0xC3, 0xE7, 0xFF, 68 | 0x00, 0x18, 0x24, 0x18, 0x00, 69 | 0xFF, 0xE7, 0xDB, 0xE7, 0xFF, 70 | 0x30, 0x48, 0x3A, 0x06, 0x0E, 71 | 0x26, 0x29, 0x79, 0x29, 0x26, 72 | 0x40, 0x7F, 0x05, 0x05, 0x07, 73 | 0x40, 0x7F, 0x05, 0x25, 0x3F, 74 | 0x5A, 0x3C, 0xE7, 0x3C, 0x5A, 75 | 0x7F, 0x3E, 0x1C, 0x1C, 0x08, 76 | 0x08, 0x1C, 0x1C, 0x3E, 0x7F, 77 | 0x14, 0x22, 0x7F, 0x22, 0x14, 78 | 0x5F, 0x5F, 0x00, 0x5F, 0x5F, 79 | 0x06, 0x09, 0x7F, 0x01, 0x7F, 80 | 0x00, 0x66, 0x89, 0x95, 0x6A, 81 | 0x60, 0x60, 0x60, 0x60, 0x60, 82 | 0x94, 0xA2, 0xFF, 0xA2, 0x94, 83 | 0x08, 0x04, 0x7E, 0x04, 0x08, 84 | 0x10, 0x20, 0x7E, 0x20, 0x10, 85 | 0x08, 0x08, 0x2A, 0x1C, 0x08, 86 | 0x08, 0x1C, 0x2A, 0x08, 0x08, 87 | 0x1E, 0x10, 0x10, 0x10, 0x10, 88 | 0x0C, 0x1E, 0x0C, 0x1E, 0x0C, 89 | 0x30, 0x38, 0x3E, 0x38, 0x30, 90 | 0x06, 0x0E, 0x3E, 0x0E, 0x06, 91 | 0x00, 0x00, 0x00, 0x00, 0x00, 92 | 0x00, 0x00, 0x5F, 0x00, 0x00, 93 | 0x00, 0x07, 0x00, 0x07, 0x00, 94 | 0x14, 0x7F, 0x14, 0x7F, 0x14, 95 | 0x24, 0x2A, 0x7F, 0x2A, 0x12, 96 | 0x23, 0x13, 0x08, 0x64, 0x62, 97 | 0x36, 0x49, 0x56, 0x20, 0x50, 98 | 0x00, 0x08, 0x07, 0x03, 0x00, 99 | 0x00, 0x1C, 0x22, 0x41, 0x00, 100 | 0x00, 0x41, 0x22, 0x1C, 0x00, 101 | 0x2A, 0x1C, 0x7F, 0x1C, 0x2A, 102 | 0x08, 0x08, 0x3E, 0x08, 0x08, 103 | 0x00, 0x80, 0x70, 0x30, 0x00, 104 | 0x08, 0x08, 0x08, 0x08, 0x08, 105 | 0x00, 0x00, 0x60, 0x60, 0x00, 106 | 0x20, 0x10, 0x08, 0x04, 0x02, 107 | 0x3E, 0x51, 0x49, 0x45, 0x3E, 108 | 0x00, 0x42, 0x7F, 0x40, 0x00, 109 | 0x72, 0x49, 0x49, 0x49, 0x46, 110 | 0x21, 0x41, 0x49, 0x4D, 0x33, 111 | 0x18, 0x14, 0x12, 0x7F, 0x10, 112 | 0x27, 0x45, 0x45, 0x45, 0x39, 113 | 0x3C, 0x4A, 0x49, 0x49, 0x31, 114 | 0x41, 0x21, 0x11, 0x09, 0x07, 115 | 0x36, 0x49, 0x49, 0x49, 0x36, 116 | 0x46, 0x49, 0x49, 0x29, 0x1E, 117 | 0x00, 0x00, 0x14, 0x00, 0x00, 118 | 0x00, 0x40, 0x34, 0x00, 0x00, 119 | 0x00, 0x08, 0x14, 0x22, 0x41, 120 | 0x14, 0x14, 0x14, 0x14, 0x14, 121 | 0x00, 0x41, 0x22, 0x14, 0x08, 122 | 0x02, 0x01, 0x59, 0x09, 0x06, 123 | 0x3E, 0x41, 0x5D, 0x59, 0x4E, 124 | 0x7C, 0x12, 0x11, 0x12, 0x7C, 125 | 0x7F, 0x49, 0x49, 0x49, 0x36, 126 | 0x3E, 0x41, 0x41, 0x41, 0x22, 127 | 0x7F, 0x41, 0x41, 0x41, 0x3E, 128 | 0x7F, 0x49, 0x49, 0x49, 0x41, 129 | 0x7F, 0x09, 0x09, 0x09, 0x01, 130 | 0x3E, 0x41, 0x41, 0x51, 0x73, 131 | 0x7F, 0x08, 0x08, 0x08, 0x7F, 132 | 0x00, 0x41, 0x7F, 0x41, 0x00, 133 | 0x20, 0x40, 0x41, 0x3F, 0x01, 134 | 0x7F, 0x08, 0x14, 0x22, 0x41, 135 | 0x7F, 0x40, 0x40, 0x40, 0x40, 136 | 0x7F, 0x02, 0x1C, 0x02, 0x7F, 137 | 0x7F, 0x04, 0x08, 0x10, 0x7F, 138 | 0x3E, 0x41, 0x41, 0x41, 0x3E, 139 | 0x7F, 0x09, 0x09, 0x09, 0x06, 140 | 0x3E, 0x41, 0x51, 0x21, 0x5E, 141 | 0x7F, 0x09, 0x19, 0x29, 0x46, 142 | 0x26, 0x49, 0x49, 0x49, 0x32, 143 | 0x03, 0x01, 0x7F, 0x01, 0x03, 144 | 0x3F, 0x40, 0x40, 0x40, 0x3F, 145 | 0x1F, 0x20, 0x40, 0x20, 0x1F, 146 | 0x3F, 0x40, 0x38, 0x40, 0x3F, 147 | 0x63, 0x14, 0x08, 0x14, 0x63, 148 | 0x03, 0x04, 0x78, 0x04, 0x03, 149 | 0x61, 0x59, 0x49, 0x4D, 0x43, 150 | 0x00, 0x7F, 0x41, 0x41, 0x41, 151 | 0x02, 0x04, 0x08, 0x10, 0x20, 152 | 0x00, 0x41, 0x41, 0x41, 0x7F, 153 | 0x04, 0x02, 0x01, 0x02, 0x04, 154 | 0x40, 0x40, 0x40, 0x40, 0x40, 155 | 0x00, 0x03, 0x07, 0x08, 0x00, 156 | 0x20, 0x54, 0x54, 0x78, 0x40, 157 | 0x7F, 0x28, 0x44, 0x44, 0x38, 158 | 0x38, 0x44, 0x44, 0x44, 0x28, 159 | 0x38, 0x44, 0x44, 0x28, 0x7F, 160 | 0x38, 0x54, 0x54, 0x54, 0x18, 161 | 0x00, 0x08, 0x7E, 0x09, 0x02, 162 | 0x18, 0xA4, 0xA4, 0x9C, 0x78, 163 | 0x7F, 0x08, 0x04, 0x04, 0x78, 164 | 0x00, 0x44, 0x7D, 0x40, 0x00, 165 | 0x20, 0x40, 0x40, 0x3D, 0x00, 166 | 0x7F, 0x10, 0x28, 0x44, 0x00, 167 | 0x00, 0x41, 0x7F, 0x40, 0x00, 168 | 0x7C, 0x04, 0x78, 0x04, 0x78, 169 | 0x7C, 0x08, 0x04, 0x04, 0x78, 170 | 0x38, 0x44, 0x44, 0x44, 0x38, 171 | 0xFC, 0x18, 0x24, 0x24, 0x18, 172 | 0x18, 0x24, 0x24, 0x18, 0xFC, 173 | 0x7C, 0x08, 0x04, 0x04, 0x08, 174 | 0x48, 0x54, 0x54, 0x54, 0x24, 175 | 0x04, 0x04, 0x3F, 0x44, 0x24, 176 | 0x3C, 0x40, 0x40, 0x20, 0x7C, 177 | 0x1C, 0x20, 0x40, 0x20, 0x1C, 178 | 0x3C, 0x40, 0x30, 0x40, 0x3C, 179 | 0x44, 0x28, 0x10, 0x28, 0x44, 180 | 0x4C, 0x90, 0x90, 0x90, 0x7C, 181 | 0x44, 0x64, 0x54, 0x4C, 0x44, 182 | 0x00, 0x08, 0x36, 0x41, 0x00, 183 | 0x00, 0x00, 0x77, 0x00, 0x00, 184 | 0x00, 0x41, 0x36, 0x08, 0x00, 185 | 0x02, 0x01, 0x02, 0x04, 0x02, 186 | 0x3C, 0x26, 0x23, 0x26, 0x3C, 187 | 0x1E, 0xA1, 0xA1, 0x61, 0x12, 188 | 0x3A, 0x40, 0x40, 0x20, 0x7A, 189 | 0x38, 0x54, 0x54, 0x55, 0x59, 190 | 0x21, 0x55, 0x55, 0x79, 0x41, 191 | 0x21, 0x54, 0x54, 0x78, 0x41, 192 | 0x21, 0x55, 0x54, 0x78, 0x40, 193 | 0x20, 0x54, 0x55, 0x79, 0x40, 194 | 0x0C, 0x1E, 0x52, 0x72, 0x12, 195 | 0x39, 0x55, 0x55, 0x55, 0x59, 196 | 0x39, 0x54, 0x54, 0x54, 0x59, 197 | 0x39, 0x55, 0x54, 0x54, 0x58, 198 | 0x00, 0x00, 0x45, 0x7C, 0x41, 199 | 0x00, 0x02, 0x45, 0x7D, 0x42, 200 | 0x00, 0x01, 0x45, 0x7C, 0x40, 201 | 0xF0, 0x29, 0x24, 0x29, 0xF0, 202 | 0xF0, 0x28, 0x25, 0x28, 0xF0, 203 | 0x7C, 0x54, 0x55, 0x45, 0x00, 204 | 0x20, 0x54, 0x54, 0x7C, 0x54, 205 | 0x7C, 0x0A, 0x09, 0x7F, 0x49, 206 | 0x32, 0x49, 0x49, 0x49, 0x32, 207 | 0x32, 0x48, 0x48, 0x48, 0x32, 208 | 0x32, 0x4A, 0x48, 0x48, 0x30, 209 | 0x3A, 0x41, 0x41, 0x21, 0x7A, 210 | 0x3A, 0x42, 0x40, 0x20, 0x78, 211 | 0x00, 0x9D, 0xA0, 0xA0, 0x7D, 212 | 0x39, 0x44, 0x44, 0x44, 0x39, 213 | 0x3D, 0x40, 0x40, 0x40, 0x3D, 214 | 0x3C, 0x24, 0xFF, 0x24, 0x24, 215 | 0x48, 0x7E, 0x49, 0x43, 0x66, 216 | 0x2B, 0x2F, 0xFC, 0x2F, 0x2B, 217 | 0xFF, 0x09, 0x29, 0xF6, 0x20, 218 | 0xC0, 0x88, 0x7E, 0x09, 0x03, 219 | 0x20, 0x54, 0x54, 0x79, 0x41, 220 | 0x00, 0x00, 0x44, 0x7D, 0x41, 221 | 0x30, 0x48, 0x48, 0x4A, 0x32, 222 | 0x38, 0x40, 0x40, 0x22, 0x7A, 223 | 0x00, 0x7A, 0x0A, 0x0A, 0x72, 224 | 0x7D, 0x0D, 0x19, 0x31, 0x7D, 225 | 0x26, 0x29, 0x29, 0x2F, 0x28, 226 | 0x26, 0x29, 0x29, 0x29, 0x26, 227 | 0x30, 0x48, 0x4D, 0x40, 0x20, 228 | 0x38, 0x08, 0x08, 0x08, 0x08, 229 | 0x08, 0x08, 0x08, 0x08, 0x38, 230 | 0x2F, 0x10, 0xC8, 0xAC, 0xBA, 231 | 0x2F, 0x10, 0x28, 0x34, 0xFA, 232 | 0x00, 0x00, 0x7B, 0x00, 0x00, 233 | 0x08, 0x14, 0x2A, 0x14, 0x22, 234 | 0x22, 0x14, 0x2A, 0x14, 0x08, 235 | 0xAA, 0x00, 0x55, 0x00, 0xAA, 236 | 0xAA, 0x55, 0xAA, 0x55, 0xAA, 237 | 0x00, 0x00, 0x00, 0xFF, 0x00, 238 | 0x10, 0x10, 0x10, 0xFF, 0x00, 239 | 0x14, 0x14, 0x14, 0xFF, 0x00, 240 | 0x10, 0x10, 0xFF, 0x00, 0xFF, 241 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 242 | 0x14, 0x14, 0x14, 0xFC, 0x00, 243 | 0x14, 0x14, 0xF7, 0x00, 0xFF, 244 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 245 | 0x14, 0x14, 0xF4, 0x04, 0xFC, 246 | 0x14, 0x14, 0x17, 0x10, 0x1F, 247 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 248 | 0x14, 0x14, 0x14, 0x1F, 0x00, 249 | 0x10, 0x10, 0x10, 0xF0, 0x00, 250 | 0x00, 0x00, 0x00, 0x1F, 0x10, 251 | 0x10, 0x10, 0x10, 0x1F, 0x10, 252 | 0x10, 0x10, 0x10, 0xF0, 0x10, 253 | 0x00, 0x00, 0x00, 0xFF, 0x10, 254 | 0x10, 0x10, 0x10, 0x10, 0x10, 255 | 0x10, 0x10, 0x10, 0xFF, 0x10, 256 | 0x00, 0x00, 0x00, 0xFF, 0x14, 257 | 0x00, 0x00, 0xFF, 0x00, 0xFF, 258 | 0x00, 0x00, 0x1F, 0x10, 0x17, 259 | 0x00, 0x00, 0xFC, 0x04, 0xF4, 260 | 0x14, 0x14, 0x17, 0x10, 0x17, 261 | 0x14, 0x14, 0xF4, 0x04, 0xF4, 262 | 0x00, 0x00, 0xFF, 0x00, 0xF7, 263 | 0x14, 0x14, 0x14, 0x14, 0x14, 264 | 0x14, 0x14, 0xF7, 0x00, 0xF7, 265 | 0x14, 0x14, 0x14, 0x17, 0x14, 266 | 0x10, 0x10, 0x1F, 0x10, 0x1F, 267 | 0x14, 0x14, 0x14, 0xF4, 0x14, 268 | 0x10, 0x10, 0xF0, 0x10, 0xF0, 269 | 0x00, 0x00, 0x1F, 0x10, 0x1F, 270 | 0x00, 0x00, 0x00, 0x1F, 0x14, 271 | 0x00, 0x00, 0x00, 0xFC, 0x14, 272 | 0x00, 0x00, 0xF0, 0x10, 0xF0, 273 | 0x10, 0x10, 0xFF, 0x10, 0xFF, 274 | 0x14, 0x14, 0x14, 0xFF, 0x14, 275 | 0x10, 0x10, 0x10, 0x1F, 0x00, 276 | 0x00, 0x00, 0x00, 0xF0, 0x10, 277 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 278 | 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 279 | 0xFF, 0xFF, 0xFF, 0x00, 0x00, 280 | 0x00, 0x00, 0x00, 0xFF, 0xFF, 281 | 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 282 | 0x38, 0x44, 0x44, 0x38, 0x44, 283 | 0x7C, 0x2A, 0x2A, 0x3E, 0x14, 284 | 0x7E, 0x02, 0x02, 0x06, 0x06, 285 | 0x02, 0x7E, 0x02, 0x7E, 0x02, 286 | 0x63, 0x55, 0x49, 0x41, 0x63, 287 | 0x38, 0x44, 0x44, 0x3C, 0x04, 288 | 0x40, 0x7E, 0x20, 0x1E, 0x20, 289 | 0x06, 0x02, 0x7E, 0x02, 0x02, 290 | 0x99, 0xA5, 0xE7, 0xA5, 0x99, 291 | 0x1C, 0x2A, 0x49, 0x2A, 0x1C, 292 | 0x4C, 0x72, 0x01, 0x72, 0x4C, 293 | 0x30, 0x4A, 0x4D, 0x4D, 0x30, 294 | 0x30, 0x48, 0x78, 0x48, 0x30, 295 | 0xBC, 0x62, 0x5A, 0x46, 0x3D, 296 | 0x3E, 0x49, 0x49, 0x49, 0x00, 297 | 0x7E, 0x01, 0x01, 0x01, 0x7E, 298 | 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 299 | 0x44, 0x44, 0x5F, 0x44, 0x44, 300 | 0x40, 0x51, 0x4A, 0x44, 0x40, 301 | 0x40, 0x44, 0x4A, 0x51, 0x40, 302 | 0x00, 0x00, 0xFF, 0x01, 0x03, 303 | 0xE0, 0x80, 0xFF, 0x00, 0x00, 304 | 0x08, 0x08, 0x6B, 0x6B, 0x08, 305 | 0x36, 0x12, 0x36, 0x24, 0x36, 306 | 0x06, 0x0F, 0x09, 0x0F, 0x06, 307 | 0x00, 0x00, 0x18, 0x18, 0x00, 308 | 0x00, 0x00, 0x10, 0x10, 0x00, 309 | 0x30, 0x40, 0xFF, 0x01, 0x01, 310 | 0x00, 0x1F, 0x01, 0x01, 0x1E, 311 | 0x00, 0x19, 0x1D, 0x17, 0x12, 312 | 0x00, 0x3C, 0x3C, 0x3C, 0x3C, 313 | 0x00, 0x00, 0x00, 0x00, 0x00, 314 | }; 315 | 316 | // the memory buffer for the LCD 317 | uint8_t pcd8544_buffer[LCDWIDTH * LCDHEIGHT / 8] = {0,}; 318 | 319 | // Le: get the bitmap assistance here! : http://en.radzio.dxp.pl/bitmap_converter/ 320 | // Andre: or here! : http://www.henningkarlsen.com/electronics/t_imageconverter_mono.php 321 | const uint8_t pi_logo [] = { 322 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0010 (16) pixels 323 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xFC, 0xAE, 0x0E, 0x0E, 0x06, 0x0E, 0x06, // 0x0020 (32) pixels 324 | 0xCE, 0x86, 0x8E, 0x0E, 0x0E, 0x1C, 0xB8, 0xF0, 0xF8, 0x78, 0x38, 0x1E, 0x0E, 0x8E, 0x8E, 0xC6, // 0x0030 (48) pixels 325 | 0x0E, 0x06, 0x0E, 0x06, 0x0E, 0x9E, 0xFE, 0xFC, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0040 (64) pixels 326 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0050 (80) pixels 327 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0060 (96) pixels 328 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x0F, 0xFE, // 0x0070 (112) pixels 329 | 0xF8, 0xF0, 0x60, 0x60, 0xE0, 0xE1, 0xE3, 0xF7, 0x7E, 0x3E, 0x1E, 0x1F, 0x1F, 0x1F, 0x3E, 0x7E, // 0x0080 (128) pixels 330 | 0xFB, 0xF3, 0xE1, 0xE0, 0x60, 0x70, 0xF0, 0xF8, 0xBE, 0x1F, 0x0F, 0x07, 0x00, 0x00, 0x00, 0x00, // 0x0090 (144) pixels 331 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00A0 (160) pixels 332 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00B0 (176) pixels 333 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, // 0x00C0 (192) pixels 334 | 0xE0, 0xFC, 0xFE, 0xFF, 0xF3, 0x38, 0x38, 0x0C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0E, 0x3C, 0x38, 0xF8, // 0x00D0 (208) pixels 335 | 0xF8, 0x38, 0x3C, 0x0E, 0x0F, 0x0F, 0x0F, 0x0E, 0x0C, 0x38, 0x38, 0xF3, 0xFF, 0xFF, 0xF8, 0xE0, // 0x00E0 (224) pixels 336 | 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x00F0 (240) pixels 337 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0100 (256) pixels 338 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0110 (272) pixels 339 | 0x00, 0x7F, 0xFF, 0xE7, 0xC3, 0xC1, 0xE0, 0xFF, 0xFF, 0x78, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, // 0x0120 (288) pixels 340 | 0x60, 0x78, 0x38, 0x3F, 0x3F, 0x38, 0x38, 0x60, 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xF8, 0x7F, // 0x0130 (304) pixels 341 | 0xFF, 0xE0, 0xC1, 0xC3, 0xE7, 0x7F, 0x3E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0140 (320) pixels 342 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0150 (336) pixels 343 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0160 (352) pixels 344 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x0F, 0x7F, 0xFF, 0xF1, 0xE0, 0xC0, 0x80, 0x01, // 0x0170 (368) pixels 345 | 0x03, 0x9F, 0xFF, 0xF0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xF0, 0xFF, 0x9F, // 0x0180 (384) pixels 346 | 0x03, 0x01, 0x80, 0xC0, 0xE0, 0xF1, 0x7F, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x0190 (400) pixels 347 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01A0 (416) pixels 348 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01B0 (432) pixels 349 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // 0x01C0 (448) pixels 350 | 0x03, 0x03, 0x07, 0x07, 0x0F, 0x1F, 0x1F, 0x3F, 0x3B, 0x71, 0x60, 0x60, 0x60, 0x60, 0x60, 0x71, // 0x01D0 (464) pixels 351 | 0x3B, 0x1F, 0x0F, 0x0F, 0x0F, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01E0 (480) pixels 352 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // 0x01F0 (496) pixels 353 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 354 | }; 355 | 356 | // reduces how much is refreshed, which speeds it up! 357 | // originally derived from Steve Evans/JCW's mod but cleaned up and optimized 358 | //#define enablePartialUpdate 359 | 360 | static void my_setpixel(uint8_t x, uint8_t y, uint8_t color) 361 | { 362 | if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) 363 | return; 364 | // x is which column 365 | if (color) 366 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] |= _BV(y%8); 367 | else 368 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] &= ~_BV(y%8); 369 | } 370 | 371 | void LCDshowLogo() 372 | { 373 | uint32_t i; 374 | for (i = 0; i < LCDWIDTH * LCDHEIGHT / 8; i++ ) 375 | { 376 | pcd8544_buffer[i] = pi_logo[i]; 377 | } 378 | LCDdisplay(); 379 | } 380 | 381 | #ifdef enablePartialUpdate 382 | static uint8_t xUpdateMin, xUpdateMax, yUpdateMin, yUpdateMax; 383 | #endif 384 | 385 | static void updateBoundingBox(uint8_t xmin, uint8_t ymin, uint8_t xmax, uint8_t ymax) { 386 | #ifdef enablePartialUpdate 387 | if (xmin < xUpdateMin) xUpdateMin = xmin; 388 | if (xmax > xUpdateMax) xUpdateMax = xmax; 389 | if (ymin < yUpdateMin) yUpdateMin = ymin; 390 | if (ymax > yUpdateMax) yUpdateMax = ymax; 391 | #endif 392 | } 393 | 394 | void LCDInit(uint8_t SCLK, uint8_t DIN, uint8_t DC, uint8_t CS, uint8_t RST, uint8_t contrast) 395 | { 396 | _din = DIN; 397 | _sclk = SCLK; 398 | _dc = DC; 399 | _rst = RST; 400 | _cs = CS; 401 | cursor_x = cursor_y = 0; 402 | textsize = 1; 403 | textcolor = BLACK; 404 | 405 | // set pin directions 406 | pinMode(_din, OUTPUT); 407 | pinMode(_sclk, OUTPUT); 408 | pinMode(_dc, OUTPUT); 409 | pinMode(_rst, OUTPUT); 410 | pinMode(_cs, OUTPUT); 411 | 412 | // toggle RST low to reset; CS low so it'll listen to us 413 | if (_cs > 0) 414 | digitalWrite(_cs, LOW); 415 | 416 | digitalWrite(_rst, LOW); 417 | _delay_ms(500); 418 | digitalWrite(_rst, HIGH); 419 | 420 | // get into the EXTENDED mode! 421 | LCDcommand(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION ); 422 | 423 | // LCD bias select (4 is optimal?) 424 | LCDcommand(PCD8544_SETBIAS | 0x4); 425 | 426 | // set VOP 427 | if (contrast > 0x7f) 428 | contrast = 0x7f; 429 | 430 | LCDcommand( PCD8544_SETVOP | contrast); // Experimentally determined 431 | 432 | // normal mode 433 | LCDcommand(PCD8544_FUNCTIONSET); 434 | 435 | // Set display to Normal 436 | LCDcommand(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL); 437 | 438 | // set up a bounding box for screen updates 439 | updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); 440 | 441 | } 442 | 443 | void LCDdrawbitmap(uint8_t x, uint8_t y,const uint8_t *bitmap, uint8_t w, uint8_t h,uint8_t color) 444 | { 445 | uint8_t j,i; 446 | for ( j=0; j= LCDHEIGHT) return; 485 | if ((x+5) >= LCDWIDTH) return; 486 | uint8_t i,j; 487 | for ( i =0; i<5; i++ ) 488 | { 489 | uint8_t d = *(font+(c*5)+i); 490 | uint8_t j; 491 | for (j = 0; j<8; j++) 492 | { 493 | if (d & _BV(j)) 494 | { 495 | my_setpixel(x+i, y+j, textcolor); 496 | } 497 | else 498 | { 499 | my_setpixel(x+i, y+j, !textcolor); 500 | } 501 | } 502 | } 503 | 504 | for ( j = 0; j<8; j++) 505 | { 506 | my_setpixel(x+5, y+j, !textcolor); 507 | } 508 | updateBoundingBox(x, y, x+5, y + 8); 509 | } 510 | 511 | void LCDwrite(uint8_t c) 512 | { 513 | if (c == '\n') 514 | { 515 | cursor_y += textsize*8; 516 | cursor_x = 0; 517 | } 518 | else if (c == '\r') 519 | { 520 | // skip em 521 | } 522 | else 523 | { 524 | LCDdrawchar(cursor_x, cursor_y, c); 525 | cursor_x += textsize*6; 526 | if (cursor_x >= (LCDWIDTH-5)) 527 | { 528 | cursor_x = 0; 529 | cursor_y+=8; 530 | } 531 | if (cursor_y >= LCDHEIGHT) 532 | cursor_y = 0; 533 | } 534 | } 535 | 536 | void LCDsetCursor(uint8_t x, uint8_t y) 537 | { 538 | cursor_x = x; 539 | cursor_y = y; 540 | } 541 | 542 | // bresenham's algorithm - thx wikpedia 543 | void LCDdrawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color) 544 | { 545 | uint8_t steep = abs(y1 - y0) > abs(x1 - x0); 546 | if (steep) 547 | { 548 | swap(x0, y0); 549 | swap(x1, y1); 550 | } 551 | 552 | if (x0 > x1) 553 | { 554 | swap(x0, x1); 555 | swap(y0, y1); 556 | } 557 | 558 | // much faster to put the test here, since we've already sorted the points 559 | updateBoundingBox(x0, y0, x1, y1); 560 | 561 | uint8_t dx, dy; 562 | dx = x1 - x0; 563 | dy = abs(y1 - y0); 564 | 565 | int8_t err = dx / 2; 566 | int8_t ystep; 567 | 568 | if (y0 < y1) 569 | { 570 | ystep = 1; 571 | } else 572 | { 573 | ystep = -1; 574 | } 575 | 576 | for (; x0<=x1; x0++) 577 | { 578 | if (steep) 579 | { 580 | my_setpixel(y0, x0, color); 581 | } 582 | else 583 | { 584 | my_setpixel(x0, y0, color); 585 | } 586 | err -= dy; 587 | if (err < 0) 588 | { 589 | y0 += ystep; 590 | err += dx; 591 | } 592 | } 593 | } 594 | 595 | // filled rectangle 596 | void LCDfillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h, uint8_t color) 597 | { 598 | // stupidest version - just pixels - but fast with internal buffer! 599 | uint8_t i,j; 600 | for ( i=x; i= 0) 646 | { 647 | y--; 648 | ddF_y += 2; 649 | f += ddF_y; 650 | } 651 | x++; 652 | ddF_x += 2; 653 | f += ddF_x; 654 | 655 | my_setpixel(x0 + x, y0 + y, color); 656 | my_setpixel(x0 - x, y0 + y, color); 657 | my_setpixel(x0 + x, y0 - y, color); 658 | my_setpixel(x0 - x, y0 - y, color); 659 | 660 | my_setpixel(x0 + y, y0 + x, color); 661 | my_setpixel(x0 - y, y0 + x, color); 662 | my_setpixel(x0 + y, y0 - x, color); 663 | my_setpixel(x0 - y, y0 - x, color); 664 | 665 | } 666 | } 667 | 668 | void LCDfillcircle(uint8_t x0, uint8_t y0, uint8_t r, uint8_t color) 669 | { 670 | updateBoundingBox(x0-r, y0-r, x0+r, y0+r); 671 | int8_t f = 1 - r; 672 | int8_t ddF_x = 1; 673 | int8_t ddF_y = -2 * r; 674 | int8_t x = 0; 675 | int8_t y = r; 676 | uint8_t i; 677 | 678 | for (i=y0-r; i<=y0+r; i++) 679 | { 680 | my_setpixel(x0, i, color); 681 | } 682 | 683 | while (x= 0) 686 | { 687 | y--; 688 | ddF_y += 2; 689 | f += ddF_y; 690 | } 691 | x++; 692 | ddF_x += 2; 693 | f += ddF_x; 694 | 695 | for ( i=y0-y; i<=y0+y; i++) 696 | { 697 | my_setpixel(x0+x, i, color); 698 | my_setpixel(x0-x, i, color); 699 | } 700 | for ( i=y0-x; i<=y0+x; i++) 701 | { 702 | my_setpixel(x0+y, i, color); 703 | my_setpixel(x0-y, i, color); 704 | } 705 | } 706 | } 707 | 708 | // the most basic function, set a single pixel 709 | void LCDsetPixel(uint8_t x, uint8_t y, uint8_t color) 710 | { 711 | if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) 712 | return; 713 | 714 | // x is which column 715 | if (color) 716 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] |= _BV(y%8); 717 | else 718 | pcd8544_buffer[x+ (y/8)*LCDWIDTH] &= ~_BV(y%8); 719 | updateBoundingBox(x,y,x,y); 720 | } 721 | 722 | // the most basic function, get a single pixel 723 | uint8_t LCDgetPixel(uint8_t x, uint8_t y) 724 | { 725 | if ((x >= LCDWIDTH) || (y >= LCDHEIGHT)) 726 | return 0; 727 | 728 | return (pcd8544_buffer[x+ (y/8)*LCDWIDTH] >> (7-(y%8))) & 0x1; 729 | } 730 | 731 | void LCDspiwrite(uint8_t c) 732 | { 733 | shiftOut(_din, _sclk, MSBFIRST, c); 734 | } 735 | 736 | void LCDcommand(uint8_t c) 737 | { 738 | digitalWrite( _dc, LOW); 739 | LCDspiwrite(c); 740 | } 741 | 742 | void LCDdata(uint8_t c) 743 | { 744 | digitalWrite(_dc, HIGH); 745 | LCDspiwrite(c); 746 | } 747 | 748 | void LCDsetContrast(uint8_t val) 749 | { 750 | if (val > 0x7f) { 751 | val = 0x7f; 752 | } 753 | LCDcommand(PCD8544_FUNCTIONSET | PCD8544_EXTENDEDINSTRUCTION ); 754 | LCDcommand( PCD8544_SETVOP | val); 755 | LCDcommand(PCD8544_FUNCTIONSET); 756 | } 757 | 758 | void LCDdisplay(void) 759 | { 760 | uint8_t col, maxcol, p; 761 | 762 | for(p = 0; p < 6; p++) 763 | { 764 | #ifdef enablePartialUpdate 765 | // check if this page is part of update 766 | if ( yUpdateMin >= ((p+1)*8) ) 767 | { 768 | continue; // nope, skip it! 769 | } 770 | if (yUpdateMax < p*8) 771 | { 772 | break; 773 | } 774 | #endif 775 | 776 | LCDcommand(PCD8544_SETYADDR | p); 777 | 778 | 779 | #ifdef enablePartialUpdate 780 | col = xUpdateMin; 781 | maxcol = xUpdateMax; 782 | #else 783 | // start at the beginning of the row 784 | col = 0; 785 | maxcol = LCDWIDTH-1; 786 | #endif 787 | 788 | LCDcommand(PCD8544_SETXADDR | col); 789 | 790 | for(; col <= maxcol; col++) { 791 | //uart_putw_dec(col); 792 | //uart_putchar(' '); 793 | LCDdata(pcd8544_buffer[(LCDWIDTH*p)+col]); 794 | } 795 | } 796 | 797 | LCDcommand(PCD8544_SETYADDR ); // no idea why this is necessary but it is to finish the last byte? 798 | #ifdef enablePartialUpdate 799 | xUpdateMin = LCDWIDTH - 1; 800 | xUpdateMax = 0; 801 | yUpdateMin = LCDHEIGHT-1; 802 | yUpdateMax = 0; 803 | #endif 804 | 805 | } 806 | 807 | // clear everything 808 | void LCDclear(void) { 809 | //memset(pcd8544_buffer, 0, LCDWIDTH*LCDHEIGHT/8); 810 | uint32_t i; 811 | for ( i = 0; i < LCDWIDTH*LCDHEIGHT/8 ; i++) 812 | pcd8544_buffer[i] = 0; 813 | updateBoundingBox(0, 0, LCDWIDTH-1, LCDHEIGHT-1); 814 | cursor_y = cursor_x = 0; 815 | } 816 | 817 | // bitbang serial shift out on select GPIO pin. Data rate is defined by CPU clk speed and CLKCONST_2. 818 | // Calibrate these value for your need on target platform. 819 | void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val) 820 | { 821 | uint8_t i; 822 | uint32_t j; 823 | 824 | for (i = 0; i < 8; i++) { 825 | if (bitOrder == LSBFIRST) 826 | digitalWrite(dataPin, !!(val & (1 << i))); 827 | else 828 | digitalWrite(dataPin, !!(val & (1 << (7 - i)))); 829 | 830 | digitalWrite(clockPin, HIGH); 831 | for (j = CLKCONST_2; j > 0; j--); // clock speed, anyone? (LCD Max CLK input: 4MHz) 832 | digitalWrite(clockPin, LOW); 833 | } 834 | } 835 | 836 | // roughly calibrated spin delay 837 | void _delay_ms(uint32_t t) 838 | { 839 | uint32_t nCount = 0; 840 | while (t != 0) 841 | { 842 | nCount = CLKCONST_1; 843 | while(nCount != 0) 844 | nCount--; 845 | t--; 846 | } 847 | } -------------------------------------------------------------------------------- /libraries/c/PCD8544/PCD8544.h: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : PCD8544.h 4 | Version : 0.1 5 | 6 | Copyright (C) 2010 Limor Fried, Adafruit Industries 7 | CORTEX-M3 version by Le Dang Dung, 2011 LeeDangDung@gmail.com (tested on LPC1769) 8 | Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de 9 | 10 | Description : PCD8544 LCD library! 11 | 12 | ================================================================================ 13 | This library is free software; you can redistribute it and/or 14 | modify it under the terms of the GNU Lesser General Public 15 | License as published by the Free Software Foundation; either 16 | version 2.1 of the License, or (at your option) any later version. 17 | 18 | This library is distributed in the hope that it will be useful, 19 | but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | Lesser General Public License for more details. 22 | ================================================================================ 23 | */ 24 | #include 25 | 26 | #define BLACK 1 27 | #define WHITE 0 28 | 29 | #define LCDWIDTH 84 30 | #define LCDHEIGHT 48 31 | 32 | #define PCD8544_POWERDOWN 0x04 33 | #define PCD8544_ENTRYMODE 0x02 34 | #define PCD8544_EXTENDEDINSTRUCTION 0x01 35 | 36 | #define PCD8544_DISPLAYBLANK 0x0 37 | #define PCD8544_DISPLAYNORMAL 0x4 38 | #define PCD8544_DISPLAYALLON 0x1 39 | #define PCD8544_DISPLAYINVERTED 0x5 40 | 41 | // H = 0 42 | #define PCD8544_FUNCTIONSET 0x20 43 | #define PCD8544_DISPLAYCONTROL 0x08 44 | #define PCD8544_SETYADDR 0x40 45 | #define PCD8544_SETXADDR 0x80 46 | 47 | // H = 1 48 | #define PCD8544_SETTEMP 0x04 49 | #define PCD8544_SETBIAS 0x10 50 | #define PCD8544_SETVOP 0x80 51 | 52 | #define swap(a, b) { uint8_t t = a; a = b; b = t; } 53 | 54 | // calibrate clock constants 55 | #define CLKCONST_1 8000 56 | #define CLKCONST_2 400 // 400 is a good tested value for Raspberry Pi 57 | 58 | // keywords 59 | #define LSBFIRST 0 60 | #define MSBFIRST 1 61 | 62 | void LCDInit(uint8_t SCLK, uint8_t DIN, uint8_t DC, uint8_t CS, uint8_t RST, uint8_t contrast); 63 | void LCDcommand(uint8_t c); 64 | void LCDdata(uint8_t c); 65 | void LCDsetContrast(uint8_t val); 66 | void LCDclear(); 67 | void LCDdisplay(); 68 | void LCDsetPixel(uint8_t x, uint8_t y, uint8_t color); 69 | uint8_t LCDgetPixel(uint8_t x, uint8_t y); 70 | void LCDfillcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color); 71 | void LCDdrawcircle(uint8_t x0, uint8_t y0, uint8_t r,uint8_t color); 72 | void LCDdrawrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color); 73 | void LCDfillrect(uint8_t x, uint8_t y, uint8_t w, uint8_t h,uint8_t color); 74 | void LCDdrawline(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t color); 75 | void LCDsetCursor(uint8_t x, uint8_t y); 76 | void LCDsetTextSize(uint8_t s); 77 | void LCDsetTextColor(uint8_t c); 78 | void LCDwrite(uint8_t c); 79 | void LCDshowLogo(); 80 | void LCDdrawchar(uint8_t x, uint8_t line, char c); 81 | void LCDdrawstring(uint8_t x, uint8_t line, char *c); 82 | void LCDdrawstring_P(uint8_t x, uint8_t line, const char *c); 83 | void LCDdrawbitmap(uint8_t x, uint8_t y, const uint8_t *bitmap, uint8_t w, uint8_t h, uint8_t color); 84 | void LCDspiwrite(uint8_t c); 85 | void shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t val); 86 | void _delay_ms(uint32_t t); -------------------------------------------------------------------------------- /libraries/c/PCD8544/README.md: -------------------------------------------------------------------------------- 1 | Raspberry Pi PCD8544 Library 2 | ============================ 3 | A simple PCD8544 LCD (Nokia3310/5110) driver. Target board is Raspberry Pi. 4 | This driver uses 5 GPIOs on target board with a bit-bang SPI implementation (hence, may not be as fast but seems fast enough). 5 | Makes use of WiringPI-library of _Gordon Henderson_ (https://projects.drogon.net/raspberry-pi/wiringpi/) 6 | 7 | Copyright (C) 2010 _Limor Fried_, _Adafruit Industries_ 8 | CORTEX-M3 version by _Le Dang Dung_, 2011 LeeDangDung@gmail.com (tested on LPC1769) 9 | Raspberry Pi version by _Andre Wussow_, 2012, desk@binerry.de 10 | 11 | For more informations please visit http://binerry.de/post/25787954149/pcd8544-library-for-raspberry-pi. 12 | 13 | License 14 | ------- 15 | This library is free software; you can redistribute it and/or 16 | modify it under the terms of the GNU Lesser General Public 17 | License as published by the Free Software Foundation; either 18 | version 2.1 of the License, or (at your option) any later version. 19 | 20 | This library is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | Lesser General Public License for more details. -------------------------------------------------------------------------------- /libraries/c/PCD8544/samples/pcd8544_rpi.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : pcd8544_rpi.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | A simple PCD8544 LCD (Nokia3310/5110) for Raspberry Pi for displaying some system informations. 10 | Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/) 11 | 12 | Recommended connection (http://www.raspberrypi.org/archives/384): 13 | LCD pins Raspberry Pi 14 | LCD1 - GND P06 - GND 15 | LCD2 - VCC P01 - 3.3V 16 | LCD3 - CLK P11 - GPIO0 17 | LCD4 - Din P12 - GPIO1 18 | LCD5 - D/C P13 - GPIO2 19 | LCD6 - CS P15 - GPIO3 20 | LCD7 - RST P16 - GPIO4 21 | LCD8 - LED P01 - 3.3V 22 | 23 | ================================================================================ 24 | This library is free software; you can redistribute it and/or 25 | modify it under the terms of the GNU Lesser General Public 26 | License as published by the Free Software Foundation; either 27 | version 2.1 of the License, or (at your option) any later version. 28 | 29 | This library is distributed in the hope that it will be useful, 30 | but WITHOUT ANY WARRANTY; without even the implied warranty of 31 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 32 | Lesser General Public License for more details. 33 | ================================================================================ 34 | */ 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "PCD8544.h" 42 | 43 | // pin setup 44 | int _din = 1; 45 | int _sclk = 0; 46 | int _dc = 2; 47 | int _rst = 4; 48 | int _cs = 3; 49 | 50 | // lcd contrast 51 | int contrast = 50; 52 | 53 | int main (void) 54 | { 55 | // print infos 56 | printf("Raspberry Pi PCD8544 sysinfo display\n"); 57 | printf("========================================\n"); 58 | 59 | // check wiringPi setup 60 | if (wiringPiSetup() == -1) 61 | { 62 | printf("wiringPi-Error\n"); 63 | exit(1); 64 | } 65 | 66 | // init and clear lcd 67 | LCDInit(_sclk, _din, _dc, _cs, _rst, contrast); 68 | LCDclear(); 69 | 70 | // show logo 71 | LCDshowLogo(); 72 | 73 | delay(2000); 74 | 75 | for (;;) 76 | { 77 | // clear lcd 78 | LCDclear(); 79 | 80 | // get system usage / info 81 | struct sysinfo sys_info; 82 | if(sysinfo(&sys_info) != 0) 83 | { 84 | printf("sysinfo-Error\n"); 85 | } 86 | 87 | // uptime 88 | char uptimeInfo[15]; 89 | unsigned long uptime = sys_info.uptime / 60; 90 | sprintf(uptimeInfo, "Uptime %ld min.", uptime); 91 | 92 | // cpu info 93 | char cpuInfo[10]; 94 | unsigned long avgCpuLoad = sys_info.loads[0] / 1000; 95 | sprintf(cpuInfo, "CPU %ld%%", avgCpuLoad); 96 | 97 | // ram info 98 | char ramInfo[10]; 99 | unsigned long totalRam = sys_info.freeram / 1024 / 1024; 100 | sprintf(ramInfo, "RAM %ld MB", totalRam); 101 | 102 | // build screen 103 | LCDdrawstring(0, 0, "Raspberry Pi:"); 104 | LCDdrawline(0, 10, 83, 10, BLACK); 105 | LCDdrawstring(0, 12, uptimeInfo); 106 | LCDdrawstring(0, 20, cpuInfo); 107 | LCDdrawstring(0, 28, ramInfo); 108 | LCDdisplay(); 109 | 110 | delay(10000); 111 | } 112 | 113 | //for (;;){ 114 | // printf("LED On\n"); 115 | // digitalWrite(pin, 1); 116 | // delay(250); 117 | // printf("LED Off\n"); 118 | // digitalWrite(pin, 0); 119 | // delay(250); 120 | //} 121 | 122 | return 0; 123 | } -------------------------------------------------------------------------------- /libraries/c/PCD8544/samples/pcd8544_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : pcd8544_test.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2010 Limor Fried, Adafruit Industries 7 | Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de 8 | 9 | Description : 10 | A simple PCD8544 LCD (Nokia3310/5110) test for Raspberry PI PCD8544 Library. 11 | Based on Limor Fried's PCD8544 Arduino samples 12 | (https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library/blob/master/examples/pcdtest/pcdtest.pde) 13 | Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/) 14 | 15 | Recommended connection (http://www.raspberrypi.org/archives/384): 16 | LCD pins Raspberry Pi 17 | LCD1 - GND P06 - GND 18 | LCD2 - VCC P01 - 3.3V 19 | LCD3 - CLK P11 - GPIO0 20 | LCD4 - Din P12 - GPIO1 21 | LCD5 - D/C P13 - GPIO2 22 | LCD6 - CS P15 - GPIO3 23 | LCD7 - RST P16 - GPIO4 24 | LCD8 - LED P01 - 3.3V 25 | 26 | ================================================================================ 27 | This library is free software; you can redistribute it and/or 28 | modify it under the terms of the GNU Lesser General Public 29 | License as published by the Free Software Foundation; either 30 | version 2.1 of the License, or (at your option) any later version. 31 | 32 | This library is distributed in the hope that it will be useful, 33 | but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35 | Lesser General Public License for more details. 36 | ================================================================================ 37 | */ 38 | #include 39 | #include 40 | #include 41 | #include "PCD8544.h" 42 | 43 | // pin setup 44 | int _din = 1; 45 | int _sclk = 0; 46 | int _dc = 2; 47 | int _rst = 4; 48 | int _cs = 3; 49 | 50 | // lcd contrast 51 | int contrast = 50; 52 | 53 | int main (void) 54 | { 55 | // print infos 56 | printf("Raspberry Pi PCD8544 test\n"); 57 | printf("========================================\n"); 58 | 59 | printf("CLK on Port %i \n", _sclk); 60 | printf("DIN on Port %i \n", _din); 61 | printf("DC on Port %i \n", _dc); 62 | printf("CS on Port %i \n", _cs); 63 | printf("RST on Port %i \n", _rst); 64 | printf("========================================\n"); 65 | 66 | // check wiringPi setup 67 | if (wiringPiSetup() == -1) 68 | { 69 | printf("wiringPi-Error\n"); 70 | exit(1); 71 | } 72 | 73 | // init and clear lcd 74 | LCDInit(_sclk, _din, _dc, _cs, _rst, contrast); 75 | LCDclear(); 76 | 77 | // turn all the pixels on (a handy test) 78 | printf("Test: All pixels on.\n"); 79 | LCDcommand(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYALLON); 80 | delay(1000); 81 | // back to normal 82 | printf("Test: All pixels off.\n"); 83 | LCDcommand(PCD8544_DISPLAYCONTROL | PCD8544_DISPLAYNORMAL); 84 | LCDclear(); 85 | 86 | // display logo 87 | printf("Test: Display logo.\n"); 88 | LCDshowLogo(); 89 | delay(2000); 90 | LCDclear(); 91 | 92 | // draw a single pixel 93 | printf("Test: Display single pixel.\n"); 94 | LCDsetPixel(10, 10, BLACK); 95 | LCDdisplay(); 96 | delay(2000); 97 | LCDclear(); 98 | 99 | // draw many lines 100 | printf("Test: Draw many lines.\n"); 101 | int i; 102 | for (i=0; i<84; i+=4) { 103 | LCDdrawline(0, 0, i, 47, BLACK); 104 | } 105 | for (i=0; i<48; i+=4) { 106 | LCDdrawline(0, 0, 83, i, BLACK); 107 | } 108 | LCDdisplay(); 109 | delay(2000); 110 | LCDclear(); 111 | 112 | // draw rectangles 113 | printf("Test: Draw rectangles.\n"); 114 | for (i=0; i<48; i+=2) { 115 | LCDdrawrect(i, i, 96-i, 48-i, BLACK); 116 | } 117 | LCDdisplay(); 118 | delay(2000); 119 | LCDclear(); 120 | 121 | // draw multiple rectangles 122 | printf("Test: Draw multiple rectangles.\n"); 123 | for (i=0; i<48; i++) { 124 | // alternate colors for moire effect 125 | LCDfillrect(i, i, 84-i, 48-i, i%2); 126 | } 127 | LCDdisplay(); 128 | delay(2000); 129 | LCDclear(); 130 | 131 | // draw mulitple circles 132 | printf("Test: Draw multiple circles.\n"); 133 | for (i=0; i<48; i+=2) { 134 | LCDdrawcircle(41, 23, i, BLACK); 135 | } 136 | LCDdisplay(); 137 | delay(2000); 138 | LCDclear(); 139 | 140 | // draw the first ~120 characters in the font 141 | printf("Test: Draw the first ~120 chars.\n"); 142 | for (i=0; i < 64; i++) { 143 | LCDdrawchar((i % 14) * 6, (i/14) * 8, i); 144 | } 145 | LCDdisplay(); 146 | delay(2000); 147 | for (i=0; i < 64; i++) { 148 | LCDdrawchar((i % 14) * 6, (i/14) * 8, i + 64); 149 | } 150 | LCDdisplay(); 151 | delay(2000); 152 | LCDclear(); 153 | 154 | return 0; 155 | } -------------------------------------------------------------------------------- /libraries/c/PCD8544/samples/pcd8544_test2.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : pcd8544_test2.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2010 Limor Fried, Adafruit Industries 7 | Raspberry Pi version by Andre Wussow, 2012, desk@binerry.de 8 | 9 | Description : 10 | A simple PCD8544 LCD (Nokia3310/5110) test for Raspberry PI PCD8544 Library. 11 | Based on Limor Fried's PCD8544 Arduino samples 12 | (https://github.com/adafruit/Adafruit-PCD8544-Nokia-5110-LCD-library/blob/master/examples/pcdtest/pcdtest.pde) 13 | Makes use of WiringPI-library of Gordon Henderson (https://projects.drogon.net/raspberry-pi/wiringpi/) 14 | 15 | Recommended connection (http://www.raspberrypi.org/archives/384): 16 | LCD pins Raspberry Pi 17 | LCD1 - GND P06 - GND 18 | LCD2 - VCC P01 - 3.3V 19 | LCD3 - CLK P11 - GPIO0 20 | LCD4 - Din P12 - GPIO1 21 | LCD5 - D/C P13 - GPIO2 22 | LCD6 - CS P15 - GPIO3 23 | LCD7 - RST P16 - GPIO4 24 | LCD8 - LED P01 - 3.3V 25 | 26 | ================================================================================ 27 | This library is free software; you can redistribute it and/or 28 | modify it under the terms of the GNU Lesser General Public 29 | License as published by the Free Software Foundation; either 30 | version 2.1 of the License, or (at your option) any later version. 31 | 32 | This library is distributed in the hope that it will be useful, 33 | but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35 | Lesser General Public License for more details. 36 | ================================================================================ 37 | */ 38 | 39 | #include 40 | #include 41 | #include 42 | #include "PCD8544.h" 43 | 44 | // animation setup 45 | #define NUMFLAKES 8 46 | #define XPOS 0 47 | #define YPOS 1 48 | #define DELTAY 2 49 | 50 | // pin setup 51 | int _din = 1; 52 | int _sclk = 0; 53 | int _dc = 2; 54 | int _rst = 4; 55 | int _cs = 3; 56 | 57 | // lcd contrast 58 | int contrast = 50; 59 | 60 | // a bitmap of a 16x16 smiley icon 61 | // get the bitmap assistance here! : http://en.radzio.dxp.pl/bitmap_converter/ 62 | // or here! : http://www.henningkarlsen.com/electronics/t_imageconverter_mono.php 63 | const uint8_t smiley[]={ 64 | 0x00, 0xE0, 0x30, 0x18, 0x0C, 0x66, 0x62, 0x02, 0x02, 0x62, 0x66, 0x0C, 0x18, 0x30, 0xE0, 0x00, // 0x0010 (16) pixels 65 | 0x00, 0x07, 0x0C, 0x18, 0x30, 0x62, 0x44, 0x4C, 0x4C, 0x44, 0x62, 0x30, 0x18, 0x0C, 0x07, 0x00, // 0x0020 (32) pixels 66 | }; 67 | #define SMILEY_HEIGHT 16 68 | #define SMILEY_WIDTH 16 69 | 70 | int main (void) 71 | { 72 | // print infos 73 | printf("Raspberry Pi PCD8544 animation test\n"); 74 | printf("========================================\n"); 75 | 76 | printf("CLK on Port %i \n", _sclk); 77 | printf("DIN on Port %i \n", _din); 78 | printf("DC on Port %i \n", _dc); 79 | printf("CS on Port %i \n", _cs); 80 | printf("RST on Port %i \n", _rst); 81 | printf("========================================\n"); 82 | 83 | // check wiringPi setup 84 | if (wiringPiSetup() == -1) 85 | { 86 | printf("wiringPi-Error\n"); 87 | exit(1); 88 | } 89 | 90 | // init and clear lcd 91 | LCDInit(_sclk, _din, _dc, _cs, _rst, contrast); 92 | LCDclear(); 93 | 94 | // turn all the pixels on (a handy test) 95 | uint8_t icons[NUMFLAKES][3]; 96 | srandom(666); // whatever seed 97 | 98 | // initialize 99 | int f; 100 | for (f=0; f< NUMFLAKES; f++) { 101 | icons[f][XPOS] = random() % LCDWIDTH; 102 | icons[f][YPOS] = 0; 103 | icons[f][DELTAY] = random() % 5 + 1; 104 | } 105 | 106 | while (1) { 107 | // draw each icon 108 | for (f=0; f< NUMFLAKES; f++) { 109 | LCDdrawbitmap(icons[f][XPOS], icons[f][YPOS], smiley, SMILEY_WIDTH, SMILEY_HEIGHT, BLACK); 110 | } 111 | LCDdisplay(); 112 | delay(500); 113 | 114 | // then erase it + move it 115 | for (f=0; f< NUMFLAKES; f++) { 116 | LCDdrawbitmap(icons[f][XPOS], icons[f][YPOS], smiley, SMILEY_WIDTH, SMILEY_HEIGHT, 0); 117 | // move it 118 | icons[f][YPOS] += icons[f][DELTAY]; 119 | // if its gone, reinit 120 | if (icons[f][YPOS] > LCDHEIGHT) { 121 | icons[f][XPOS] = random() % LCDWIDTH; 122 | icons[f][YPOS] = 0; 123 | icons[f][DELTAY] = random() % 5 + 1; 124 | } 125 | } 126 | } 127 | 128 | return 0; 129 | } -------------------------------------------------------------------------------- /prototyping/fritzing/parts/board/README.md: -------------------------------------------------------------------------------- 1 | Raspberry Pi Fritzing Part 2 | ========================== 3 | For doing some prototyping stuff it maybe really helpfull to use Raspberry Pi 4 | within' Fritzing. This is the Fritzing Part (fzpz) of the main board, model b. 5 | 6 | Copyright (C) 2012 by _Andre Wussow_, desk@binerry.de 7 | 8 | Fritzing is an open-source initiative of the University of Applied Sciences Potsdam 9 | to support designers, artists, researchers and hobbyists to work creatively with 10 | interactive electronics. For more informations and downloads visit http://fritzing.org 11 | 12 | For more informations please visit http://binerry.de/post/26227980624/raspberry-pi-fritzing-part 13 | 14 | License 15 | ------- 16 | This part is free software; you can redistribute it and/or 17 | modify it under the terms of the GNU Lesser General Public 18 | License as published by the Free Software Foundation; either 19 | version 2.1 of the License, or (at your option) any later version. 20 | 21 | This part is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | Lesser General Public License for more details. -------------------------------------------------------------------------------- /prototyping/fritzing/parts/board/Raspberry Pi.fzpz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binerry/RaspberryPi/a80745bbd098e7f49aba6e51499cadca98d9e457/prototyping/fritzing/parts/board/Raspberry Pi.fzpz -------------------------------------------------------------------------------- /prototyping/fritzing/parts/board/svgs/controller_raspberry_pi_breadboard.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | image/svg+xml 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | Raspberry Pi 51 | 52 | 53 | (C)2011 54 | 55 | 56 | http://www.raspberrypi.org 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | OK 70 | 71 | 72 | PWR 73 | 74 | 75 | FDX 76 | 77 | 78 | LNK 79 | 80 | 81 | 10M 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | GPIO 267 | 268 | 269 | P1 270 | 271 | 272 | 273 | -------------------------------------------------------------------------------- /prototyping/fritzing/parts/board/svgs/controller_raspberry_pi_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 19 | 21 | 43 | 45 | 46 | 48 | image/svg+xml 49 | 51 | 52 | 53 | 54 | 55 | 60 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /prototyping/fritzing/parts/board/svgs/controller_raspberry_pi_pcb.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 14 | 16 | 18 | 19 | 21 | image/svg+xml 22 | 24 | 25 | 26 | 27 | 28 | 31 | 34 | 36 | 43 | 50 | 57 | 64 | 71 | 78 | 85 | 92 | 99 | 106 | 113 | 120 | 127 | 134 | 141 | 148 | 155 | 162 | 169 | 176 | 183 | 190 | 197 | 204 | 211 | 218 | 219 | 220 | 221 | 222 | -------------------------------------------------------------------------------- /prototyping/fritzing/parts/board/svgs/controller_raspberry_pi_schematic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 20 | 42 | 44 | 45 | 47 | image/svg+xml 48 | 50 | 51 | 52 | 53 | 54 | 59 | 62 | 69 | 76 | 83 | 90 | 97 | 104 | 111 | 118 | 125 | 132 | 139 | 146 | 153 | 160 | 167 | 174 | 181 | 188 | 195 | 202 | 209 | 216 | 223 | 230 | 237 | 244 | 251 | 258 | 265 | 272 | 279 | 286 | 293 | 300 | 307 | 314 | 321 | 328 | 335 | 342 | 344 | 351 | 358 | 365 | 372 | 379 | 386 | 393 | 400 | 407 | 414 | 421 | 428 | 435 | 442 | 449 | 456 | SCL0 462 | SDA0 468 | 475 | 482 | MOSI 487 | MISO 492 | 497 | SCLK 502 | CE0_N 507 | CE1_N 512 | 519 | 526 | 3V3 531 | 5V 536 | SPI 543 | GPIO5 549 | GPIO4 555 | GPIO3 561 | GPIO2 567 | GPIO1 573 | GPIO0 579 | TX 585 | RX 591 | TXD 597 | GPIO7 603 | GPIO6 609 | RXD 615 | Digital Input/Output 622 | Power 628 | RaspberryPi 634 | 641 | GND 646 | 650 | 654 | I2C 661 | SERIAL 668 | 669 | 670 | 671 | 672 | -------------------------------------------------------------------------------- /prototyping/fritzing/projects/i2c-shifter/README.md: -------------------------------------------------------------------------------- 1 | i2c-shifter/i2c-bridge Fritzing Prototype 2 | ========================================= 3 | Prototype for a i2c-level-shifter / i2c-bridge for enabling intercommunication 4 | between two devices at different logic/voltage-levels. 5 | 6 | Copyright (C) 2012 by _Andre Wussow_, desk@binerry.de 7 | 8 | Fritzing is an open-source initiative of the University of Applied Sciences Potsdam 9 | to support designers, artists, researchers and hobbyists to work creatively with 10 | interactive electronics. For more informations and downloads visit http://fritzing.org 11 | 12 | For more informations please visit http://binerry.de/post/27067411903/i2c-level-shifter-i2c-bridge 13 | 14 | License 15 | ------- 16 | This prototype is free software; you can redistribute it and/or 17 | modify it under the terms of the GNU Lesser General Public 18 | License as published by the Free Software Foundation; either 19 | version 2.1 of the License, or (at your option) any later version. 20 | 21 | This prototype is distributed in the hope that it will be useful, 22 | but WITHOUT ANY WARRANTY; without even the implied warranty of 23 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 | Lesser General Public License for more details. -------------------------------------------------------------------------------- /prototyping/fritzing/projects/i2c-shifter/i2c_shifter.fzz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/binerry/RaspberryPi/a80745bbd098e7f49aba6e51499cadca98d9e457/prototyping/fritzing/projects/i2c-shifter/i2c_shifter.fzz -------------------------------------------------------------------------------- /snippets/c/i2c-arduino/Arduino/I2CSlave/Commander.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : Commander.cpp 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | Commander library for Arduino as i2c-slave for processing commands/actions. 10 | 11 | References : 12 | http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave 13 | 14 | ================================================================================ 15 | This library is free software; you can redistribute it and/or 16 | modify it under the terms of the GNU Lesser General Public 17 | License as published by the Free Software Foundation; either 18 | version 2.1 of the License, or (at your option) any later version. 19 | 20 | This library is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | Lesser General Public License for more details. 24 | ================================================================================ 25 | */ 26 | #include "Arduino.h" 27 | #include "Commander.h" 28 | 29 | // constructor: 30 | Commander::Commander() 31 | { 32 | for (int i = 0; i < MAX_COMMANDS; i++) { 33 | this->commands[i].isActive = false; 34 | } 35 | } 36 | 37 | // add command method: 38 | void Commander::addCommand(Command_t command) 39 | { 40 | for (int i = 0; i < MAX_COMMANDS; i++) { 41 | if (!this->commands[i].isActive) 42 | { 43 | this->commands[i] = command; 44 | this->commands[i].isActive = true; 45 | break; 46 | } 47 | } 48 | } 49 | 50 | // process command method: 51 | void Commander::processCommand(String command) 52 | { 53 | for (int i = 0; i < MAX_COMMANDS; i++) 54 | { 55 | if (this->commands[i].isActive) 56 | { 57 | if (this->commands[i].execCommand == command) 58 | { 59 | // call callback-function 60 | this->commands[i].callback(command); 61 | break; 62 | } 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /snippets/c/i2c-arduino/Arduino/I2CSlave/Commander.h: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : Commander.h 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | Commander library for Arduino as i2c-slave for processing commands/actions. 10 | 11 | References : 12 | http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave 13 | 14 | ================================================================================ 15 | This library is free software; you can redistribute it and/or 16 | modify it under the terms of the GNU Lesser General Public 17 | License as published by the Free Software Foundation; either 18 | version 2.1 of the License, or (at your option) any later version. 19 | 20 | This library is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | Lesser General Public License for more details. 24 | ================================================================================ 25 | */ 26 | #include "Arduino.h" 27 | 28 | // ensure this library description is only included once: 29 | #ifndef Commander_h 30 | #define Commander_h 31 | 32 | // constants: 33 | #define MAX_COMMANDS 8 // max supported commands 34 | 35 | // structs: 36 | // Command-Struct: 37 | typedef struct { 38 | String execCommand; // command for execution 39 | void (*callback)(String); // callback function 40 | uint8_t isActive :1; // true if this command is enabled 41 | } Command_t; 42 | 43 | // Commander library interface description: 44 | class Commander { 45 | public: 46 | // constructor: 47 | Commander(); 48 | 49 | // methods: 50 | void addCommand(Command_t command); 51 | void processCommand(String command); 52 | private: 53 | // properties 54 | Command_t commands[MAX_COMMANDS]; 55 | }; 56 | #endif -------------------------------------------------------------------------------- /snippets/c/i2c-arduino/Arduino/I2CSlave/I2CSlave.ino: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : I2CSlave.ino 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | Sample of controlling an Arduino connected to Raspberry Pi via I2C. 10 | 11 | Recommended connection (http://www.raspberrypi.org/archives/384): 12 | Arduino pins I2C-Shifter Raspberry Pi 13 | GND P06 - GND 14 | 5V 5V 15 | SDA SDA2 16 | SCL SCL2 17 | 3V3 P01 - 3.3V 18 | SDA1 P03 - SDA 19 | SCL1 P05 - SCL 20 | D2 LED1 with 1k resistor to GND 21 | D3 LED2 with 1k resistor to GND 22 | D4 LED3 with 1k resistor to GND 23 | D5 Relay with transistor driver 24 | 25 | 26 | References : 27 | http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave 28 | 29 | ================================================================================ 30 | This sample is free software; you can redistribute it and/or 31 | modify it under the terms of the GNU Lesser General Public 32 | License as published by the Free Software Foundation; either 33 | version 2.1 of the License, or (at your option) any later version. 34 | 35 | This sample is distributed in the hope that it will be useful, 36 | but WITHOUT ANY WARRANTY; without even the implied warranty of 37 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 38 | Lesser General Public License for more details. 39 | ================================================================================ 40 | */ 41 | 42 | #include "Commander.h" 43 | #include "Wire.h" 44 | 45 | /* 46 | General Setup 47 | */ 48 | // define i2c commands 49 | #define LED1_ON_COMMAND "L11" 50 | #define LED1_OFF_COMMAND "L10" 51 | #define LED2_ON_COMMAND "L21" 52 | #define LED2_OFF_COMMAND "L20" 53 | #define LED3_ON_COMMAND "L31" 54 | #define LED3_OFF_COMMAND "L30" 55 | #define RELAY_ON_COMMAND "R11" 56 | #define RELAY_OFF_COMMAND "R10" 57 | 58 | // define slave address (0x2A = 42 [the answer to the ultimate question of life, the universe, and everything ;)] ) 59 | #define SLAVE_ADDRESS 0x2A 60 | 61 | // instantiate i2cCommander 62 | Commander commander = Commander(); 63 | 64 | // pin setup 65 | int led1pin = 2; 66 | int led2pin = 3; 67 | int led3pin = 4; 68 | int relaypin = 5; 69 | 70 | // other vars 71 | int answer = 0; 72 | 73 | void setup() { 74 | // initialize the digital pins for leds and relay as an output 75 | pinMode(led1pin, OUTPUT); 76 | pinMode(led2pin, OUTPUT); 77 | pinMode(led3pin, OUTPUT); 78 | pinMode(relaypin, OUTPUT); 79 | 80 | // create commands for i2cCommander 81 | // led 1: 82 | Command_t cmdLed1On; 83 | cmdLed1On.execCommand = LED1_ON_COMMAND; 84 | cmdLed1On.callback = led1On; 85 | 86 | Command_t cmdLed1Off; 87 | cmdLed1Off.execCommand = LED1_OFF_COMMAND; 88 | cmdLed1Off.callback = led1Off; 89 | 90 | // led 2: 91 | Command_t cmdLed2On; 92 | cmdLed2On.execCommand = LED2_ON_COMMAND; 93 | cmdLed2On.callback = led2On; 94 | 95 | Command_t cmdLed2Off; 96 | cmdLed2Off.execCommand = LED2_OFF_COMMAND; 97 | cmdLed2Off.callback = led2Off; 98 | 99 | // led 3: 100 | Command_t cmdLed3On; 101 | cmdLed3On.execCommand = LED3_ON_COMMAND; 102 | cmdLed3On.callback = led3On; 103 | 104 | Command_t cmdLed3Off; 105 | cmdLed3Off.execCommand = LED3_OFF_COMMAND; 106 | cmdLed3Off.callback = led3Off; 107 | 108 | // relay: 109 | Command_t cmdRelayOn; 110 | cmdRelayOn.execCommand = RELAY_ON_COMMAND; 111 | cmdRelayOn.callback = relayOn; 112 | 113 | Command_t cmdRelayOff; 114 | cmdRelayOff.execCommand = RELAY_OFF_COMMAND; 115 | cmdRelayOff.callback = relayOff; 116 | 117 | // add commands to i2cCommander 118 | commander.addCommand(cmdLed1On); 119 | commander.addCommand(cmdLed1Off); 120 | commander.addCommand(cmdLed2On); 121 | commander.addCommand(cmdLed2Off); 122 | commander.addCommand(cmdLed3On); 123 | commander.addCommand(cmdLed3Off); 124 | commander.addCommand(cmdRelayOn); 125 | commander.addCommand(cmdRelayOff); 126 | 127 | // initialize i2c as slave 128 | Wire.begin(SLAVE_ADDRESS); 129 | 130 | // define callbacks for i2c communication 131 | Wire.onReceive(receiveData); 132 | Wire.onRequest(sendData); 133 | } 134 | 135 | void loop() { 136 | 137 | } 138 | 139 | // callback for received data 140 | void receiveData(int byteCount) 141 | { 142 | String requestCommand = ""; 143 | while(Wire.available()) 144 | { 145 | requestCommand = requestCommand + (char)Wire.read(); 146 | } 147 | commander.processCommand(requestCommand); 148 | } 149 | 150 | // callback for sending data 151 | void sendData() 152 | { 153 | Wire.write(answer); 154 | answer = 0; 155 | } 156 | 157 | void led1On(String command) 158 | { 159 | // switch led 1 on 160 | digitalWrite(led1pin, HIGH); 161 | 162 | // reply with command and success info 163 | answer = 1; 164 | } 165 | 166 | void led1Off(String command) 167 | { 168 | // switch led 1 off 169 | digitalWrite(led1pin, LOW); 170 | 171 | // reply with command and success info 172 | answer = 1; 173 | } 174 | 175 | void led2On(String command) 176 | { 177 | // switch led 2 on 178 | digitalWrite(led2pin, HIGH); 179 | 180 | // reply with command and success info 181 | answer = 1; 182 | } 183 | 184 | void led2Off(String command) 185 | { 186 | // switch led 2 off 187 | digitalWrite(led2pin, LOW); 188 | 189 | // reply with command and success info 190 | answer = 1; 191 | } 192 | 193 | void led3On(String command) 194 | { 195 | // switch led 3 on 196 | digitalWrite(led3pin, HIGH); 197 | 198 | // reply with command and success info 199 | answer = 1; 200 | } 201 | 202 | void led3Off(String command) 203 | { 204 | // switch led 3 off 205 | digitalWrite(led3pin, LOW); 206 | 207 | // reply with command and success info 208 | answer = 1; 209 | } 210 | 211 | void relayOn(String command) 212 | { 213 | // switch relay 3 on 214 | digitalWrite(relaypin, HIGH); 215 | 216 | // reply with command and success info 217 | answer = 1; 218 | } 219 | 220 | void relayOff(String command) 221 | { 222 | // switch relay off 223 | digitalWrite(relaypin, LOW); 224 | 225 | // reply with command and success info 226 | answer = 1; 227 | } -------------------------------------------------------------------------------- /snippets/c/i2c-arduino/README.md: -------------------------------------------------------------------------------- 1 | Raspberry Pi with Arduino as I2C-Slave 2 | ====================================== 3 | Sample of controlling an Arduino connected to Raspberry Pi via I2C. 4 | 5 | http://www.raspberrypi.org 6 | http://arduino.cc 7 | 8 | Copyright (C) 2012 by _Andre Wussow_, 2012, desk@binerry.de 9 | 10 | For more informations please visit http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave. 11 | 12 | License 13 | ------- 14 | This sample is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU Lesser General Public 16 | License as published by the Free Software Foundation; either 17 | version 2.1 of the License, or (at your option) any later version. 18 | 19 | This sample is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 | Lesser General Public License for more details. -------------------------------------------------------------------------------- /snippets/c/i2c-arduino/i2c-arduino.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : i2c-arduino.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | Sample of controlling an Arduino connected to Raspberry Pi via I2C. 10 | 11 | Recommended connection (http://www.raspberrypi.org/archives/384): 12 | Arduino pins I2C-Shifter Raspberry Pi 13 | GND P06 - GND 14 | 5V 5V 15 | SDA SDA2 16 | SCL SCL2 17 | 3V3 P01 - 3.3V 18 | SDA1 P03 - SDA 19 | SCL1 P05 - SCL 20 | 21 | References : 22 | http://binerry.de/post/27128825416/raspberry-pi-with-i2c-arduino-slave 23 | 24 | ================================================================================ 25 | This sample is free software; you can redistribute it and/or 26 | modify it under the terms of the GNU Lesser General Public 27 | License as published by the Free Software Foundation; either 28 | version 2.1 of the License, or (at your option) any later version. 29 | 30 | This sample is distributed in the hope that it will be useful, 31 | but WITHOUT ANY WARRANTY; without even the implied warranty of 32 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 33 | Lesser General Public License for more details. 34 | ================================================================================ 35 | */ 36 | 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | int deviceHandle; 44 | int readBytes; 45 | char buffer[7]; 46 | 47 | void testCommand(char command[3], char identifier[5]); 48 | 49 | int main (void) 50 | { 51 | // print infos 52 | printf("Raspberry Pi I2C Arduino Sample\n"); 53 | printf("========================================\n"); 54 | 55 | // initialize buffer 56 | buffer[0] = 0x00; 57 | 58 | // address of i2c Arduino device 59 | int deviceI2CAddress = 0x2A; // (0x2A = 42) 60 | 61 | // open device on /dev/i2c-0 62 | if ((deviceHandle = open("/dev/i2c-0", O_RDWR)) < 0) { 63 | printf("Error: Couldn't open device! %d\n", deviceHandle); 64 | return 1; 65 | } 66 | 67 | // connect to arduino as i2c slave 68 | if (ioctl(deviceHandle, I2C_SLAVE, deviceI2CAddress) < 0) { 69 | printf("Error: Couldn't find arduino on address!\n"); 70 | return 1; 71 | } 72 | 73 | // begin transmission and request acknowledgement 74 | readBytes = write(deviceHandle, buffer, 1); 75 | if (readBytes != 1) 76 | { 77 | printf("Error: Received no ACK-Bit, couldn't established connection!"); 78 | } 79 | else 80 | { 81 | // drive some tests 82 | testCommand("L11", "LED1 on"); 83 | usleep(2000000); // 2s 84 | testCommand("L10", "LED1 off"); 85 | usleep(2000000); // 2s 86 | testCommand("L21", "LED2 on"); 87 | usleep(2000000); // 2s 88 | testCommand("L20", "LED2 off"); 89 | usleep(2000000); // 2s 90 | testCommand("L31", "LED3 on"); 91 | usleep(2000000); // 2s 92 | testCommand("L30", "LED3 off"); 93 | usleep(2000000); // 2s 94 | testCommand("R11", "Relay on"); 95 | usleep(2000000); // 2s 96 | testCommand("R10", "Relay off"); 97 | } 98 | 99 | // close connection and return 100 | close(deviceHandle); 101 | return 0; 102 | } 103 | 104 | // function for testing command 105 | void testCommand(char command[3], char action[10]) 106 | { 107 | // switch on 108 | printf("Switching %s ... ", action); 109 | readBytes = write(deviceHandle, command, 3); 110 | 111 | // give arduino some reaction time 112 | usleep(100000); // 100ms 113 | 114 | // read success 115 | readBytes = read(deviceHandle, buffer, 1); 116 | if (readBytes != 1) 117 | { 118 | printf("Error: Received no data!"); 119 | } 120 | else 121 | { 122 | // check response: 0 = error / 1 = success 123 | if (buffer[0] == 1) 124 | { 125 | printf("OK!\n"); 126 | } 127 | } 128 | } -------------------------------------------------------------------------------- /snippets/c/i2c/rtc_ds1307.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : rtc_ds1307.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | A simple test for querying the RTC DS1307. 10 | 11 | Connection (http://www.raspberrypi.org/archives/384): 12 | DS1307 pins Raspberry Pi Other 13 | 1 - X1 Clock oscillator X1 14 | 2 - X2 Clock oscillator X2 15 | 3 - VBat Coin cell battery CR2032 3V 16 | 4 - GND P05 - GND 17 | 5 - Vcc P01 - 5V 18 | 6 - SQW/OUT 19 | 7 - SCL P04 - SCL0 20 | 8 - SDA P02 - SDA0 21 | 22 | References : 23 | http://binerry.de/post/26685647322/raspberry-pi-and-i2c 24 | http://pdfserv.maxim-ic.com/en/ds/DS1307.pdf 25 | 26 | ================================================================================ 27 | This sample is free software; you can redistribute it and/or 28 | modify it under the terms of the GNU Lesser General Public 29 | License as published by the Free Software Foundation; either 30 | version 2.1 of the License, or (at your option) any later version. 31 | 32 | This sample is distributed in the hope that it will be useful, 33 | but WITHOUT ANY WARRANTY; without even the implied warranty of 34 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 35 | Lesser General Public License for more details. 36 | ================================================================================ 37 | */ 38 | #include 39 | #include 40 | #include 41 | #include 42 | 43 | int main (void) 44 | { 45 | // print infos 46 | printf("Raspberry Pi RTC DS1307 Sample\n"); 47 | printf("========================================\n"); 48 | 49 | int deviceHandle; 50 | int readBytes; 51 | char buffer[7]; 52 | 53 | // initialize buffer 54 | buffer[0] = 0x00; 55 | 56 | // address of DS1307 RTC device 57 | int deviceI2CAddress = 0x68; 58 | 59 | // open device on /dev/i2c-0 60 | if ((deviceHandle = open("/dev/i2c-0", O_RDWR)) < 0) { 61 | printf("Error: Couldn't open device! %d\n", deviceHandle); 62 | return 1; 63 | } 64 | 65 | // connect to DS1307 as i2c slave 66 | if (ioctl(deviceHandle, I2C_SLAVE, deviceI2CAddress) < 0) { 67 | printf("Error: Couldn't find device on address!\n"); 68 | return 1; 69 | } 70 | 71 | // begin transmission and request acknowledgement 72 | readBytes = write(deviceHandle, buffer, 1); 73 | if (readBytes != 1) 74 | { 75 | printf("Error: Received no ACK-Bit, couldn't established connection!"); 76 | } 77 | else 78 | { 79 | // read response 80 | readBytes = read(deviceHandle, buffer, 7); 81 | if (readBytes != 7) 82 | { 83 | printf("Error: Received no data!"); 84 | } 85 | else 86 | { 87 | // get data 88 | int seconds = buffer[0]; // 0-59 89 | int minutes = buffer[1]; // 0-59 90 | int hours = buffer[2]; // 1-23 91 | int dayOfWeek = buffer[3]; // 1-7 92 | int day = buffer[4]; // 1-28/29/30/31 93 | int month = buffer[5]; // 1-12 94 | int year = buffer[6]; // 0-99; 95 | 96 | // and print results 97 | printf("Actual RTC-time:\n"); 98 | printf("Date: %x-%x-%x\n", year, month, day); 99 | printf("Time: %x:%x:%x\n", hours, minutes, seconds); 100 | } 101 | } 102 | 103 | // close connection and return 104 | close(deviceHandle); 105 | return 0; 106 | } -------------------------------------------------------------------------------- /snippets/c/watchdog/Makefile: -------------------------------------------------------------------------------- 1 | all: wdt_test.c 2 | cc -o wdt_test wdt_test.c 3 | clean: 4 | rm -rf wdt_test -------------------------------------------------------------------------------- /snippets/c/watchdog/wdt_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : wdt_test.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | A simple test for working with the Raspberry Pi BCM2835 Watchdog. 10 | 11 | References : 12 | http://binerry.de/post/28263824530/raspberry-pi-watchdog-timer 13 | 14 | ================================================================================ 15 | This sample is free software; you can redistribute it and/or 16 | modify it under the terms of the GNU Lesser General Public 17 | License as published by the Free Software Foundation; either 18 | version 2.1 of the License, or (at your option) any later version. 19 | 20 | This sample is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 23 | Lesser General Public License for more details. 24 | ================================================================================ 25 | */ 26 | #include 27 | #include 28 | #include 29 | 30 | int main (int argc, char *argv[]) 31 | { 32 | // print infos 33 | printf("Raspberry Pi BCM2835 Watchdog Sample\n"); 34 | printf("========================================\n"); 35 | 36 | int deviceHandle; 37 | int disableWatchdog = 1; 38 | 39 | // test watchdog reset via t-param 40 | if (argc > 1) { 41 | if (!strncasecmp(argv[1], "-t", 2)) { 42 | disableWatchdog = 0; 43 | } 44 | } 45 | 46 | printf("Disabling watchdog before closing device: %d\n", disableWatchdog); 47 | 48 | // open watchdog device on /dev/watchdog 49 | if ((deviceHandle = open("/dev/watchdog", O_RDWR | O_NOCTTY)) < 0) { 50 | printf("Error: Couldn't open watchdog device! %d\n", deviceHandle); 51 | return 1; 52 | } 53 | 54 | // get timeout info of watchdog (try to set it to 15s before) 55 | int timeout = 15; 56 | ioctl(deviceHandle, WDIOC_SETTIMEOUT, &timeout); 57 | ioctl(deviceHandle, WDIOC_GETTIMEOUT, &timeout); 58 | printf("The watchdog timeout is %d seconds.\n\n", timeout); 59 | 60 | // feed watchdog 3 times with heartbeats 61 | int i; 62 | for (i = 0; i < 3; i++) { 63 | printf("Feeding the dog with a heartbeat.\n"); 64 | ioctl(deviceHandle, WDIOC_KEEPALIVE, 0); 65 | sleep(10); 66 | } 67 | 68 | if (disableWatchdog) 69 | { 70 | printf("Disable watchdog.\n"); 71 | write(deviceHandle, "V", 1); 72 | } 73 | 74 | // close connection and return 75 | close(deviceHandle); 76 | return 0; 77 | } -------------------------------------------------------------------------------- /tools/c/sip-tools/Makefile: -------------------------------------------------------------------------------- 1 | all: sipcall sipserv 2 | 3 | sipcall: sipcall.c 4 | cc -o $@ $< `pkg-config --cflags --libs libpjproject` 5 | 6 | sipserv: sipserv.c 7 | cc -o $@ $< `pkg-config --cflags --libs libpjproject` 8 | 9 | clean: 10 | rm -rf sipcall 11 | rm -rf sipserv -------------------------------------------------------------------------------- /tools/c/sip-tools/README.md: -------------------------------------------------------------------------------- 1 | Sip-Tools - Automated calls and answering machine 2 | ================================================= 3 | sipcall - Automated calls over SIP/VOIP with TTS 4 | sipserv - Answering machine for SIP/VOIP with TTS 5 | 6 | Dependencies: 7 | - PJSUA API (http://www.pjsip.org) 8 | - eSpeak (http://espeak.sourceforge.net) 9 | 10 | Copyright (C) 2012 by _Andre Wussow_, 2012, desk@binerry.de 11 | 12 | For more informations please visit http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine. 13 | 14 | 15 | 16 | sipcall 17 | ------- 18 | Usage: 19 | sipcall [options] 20 | 21 | Mandatory options: 22 | -sd=string _Set sip provider domain._ 23 | -su=string _Set sip username._ 24 | -sp=string _Set sip password._ 25 | -pn=string _Set target phone number to call_ 26 | -tts=string _Text to speak_ 27 | 28 | Optional options: 29 | -ttsf=string _TTS speech file name_ 30 | -rcf=string _Record call file name_ 31 | -mr=int _Repeat message x-times_ 32 | -s=int _Silent mode (hide info messages) (0/1)_ 33 | 34 | 35 | _see also source of sipcall-sample.sh_ 36 | 37 | 38 | 39 | sipserv 40 | ------- 41 | Usage: 42 | sipserv [options] 43 | 44 | Commandline: 45 | Mandatory options: 46 | --config-file=string _Set config file_ 47 | 48 | Optional options: 49 | -s=int _Silent mode (hide info messages) (0/1)_ 50 | 51 | 52 | Config file: 53 | Mandatory options: 54 | sd=string _Set sip provider domain._ 55 | su=string _Set sip username._ 56 | sp=string _Set sip password._ 57 | 58 | _and at least one dtmf configuration (X = dtmf-key index):_ 59 | dtmf.X.active=int _Set dtmf-setting active (0/1)._ 60 | dtmf.X.description=string _Set description._ 61 | dtmf.X.tts-intro=string _Set tts intro._ 62 | dtmf.X.tts-answer=string _Set tts answer._ 63 | dtmf.X.cmd=string _Set dtmf command._ 64 | 65 | Optional options: 66 | rc=int _Record call (0/1)_ 67 | 68 | 69 | _a sample configuration can be found in sipserv-sample.cfg_ 70 | 71 | _sipserv can be controlled with ./sipserv-ctrl.sh start and ./sipserv-ctrl.sh stop_ 72 | 73 | 74 | 75 | License 76 | ------- 77 | This tools are free software; you can redistribute it and/or 78 | modify it under the terms of the GNU Lesser General Public 79 | License as published by the Free Software Foundation; either 80 | version 2.1 of the License, or (at your option) any later version. 81 | 82 | This tools are distributed in the hope that it will be useful, 83 | but WITHOUT ANY WARRANTY; without even the implied warranty of 84 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 85 | Lesser General Public License for more details. -------------------------------------------------------------------------------- /tools/c/sip-tools/sipcall-sample.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | #================================================================================= 4 | # Name : sipcall-sample.sh 5 | # Version : 0.1 6 | # 7 | # Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 8 | # 9 | # Description : 10 | # Sample Script for checking average load and making call with sipcall. 11 | # 12 | # Dependencies: 13 | # - sipcall 14 | # 15 | # References : 16 | # http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine 17 | # 18 | #================================================================================ 19 | #This script is free software; you can redistribute it and/or 20 | #modify it under the terms of the GNU Lesser General Public 21 | #License as published by the Free Software Foundation; either 22 | #version 2.1 of the License, or (at your option) any later version. 23 | # 24 | #This script is distributed in the hope that it will be useful, 25 | #but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 | #Lesser General Public License for more details. 28 | #================================================================================ 29 | 30 | # define sip-settings 31 | sip_domain="samplesip.com"; 32 | sip_user="12345678"; 33 | sip_password="XXXXXX"; 34 | play_file="play.wav"; 35 | 36 | # define number to call 37 | phone_number="0123456789"; 38 | 39 | # define allowed load limit 40 | maxload=0; 41 | 42 | # read actual load values 43 | avgload1="$(uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $1}')"; 44 | avgload5="$(uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $2}')"; 45 | avgload15="$(uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $3}')"; 46 | 47 | # check average load within last 5 minutes 48 | avgload="$(echo $avgload5 | awk -F',' '{print $1}')"; 49 | 50 | check="$(($avgload >= $maxload))"; 51 | 52 | # creating text to speak 53 | tts="$(echo This is raspberry pi and the load is high. The average load within the last 5 minutes was $avgload5)"; 54 | 55 | if [ $check = 1 ]; then 56 | # make call with sipcall 57 | $(./sipcall -sd $sip_domain -su $sip_user -sp $sip_password -pn $phone_number -s 1 -mr 2 -tts "$tts" -ttsf $play_file > /dev/null); 58 | fi -------------------------------------------------------------------------------- /tools/c/sip-tools/sipcall.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : sipcall.c 4 | Version : 0.1 alpha 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | Tool for making automated calls over SIP/VOIP with PJSUA library and eSpeak. 10 | 11 | Dependencies: 12 | - PJSUA API (PJSIP) 13 | - eSpeak 14 | 15 | References : 16 | http://www.pjsip.org/ 17 | http://www.pjsip.org/docs/latest/pjsip/docs/html/group__PJSUA__LIB.htm 18 | http://espeak.sourceforge.net/ 19 | http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine 20 | 21 | ================================================================================ 22 | This tool is free software; you can redistribute it and/or 23 | modify it under the terms of the GNU Lesser General Public 24 | License as published by the Free Software Foundation; either 25 | version 2.1 of the License, or (at your option) any later version. 26 | 27 | This tool is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30 | Lesser General Public License for more details. 31 | ================================================================================ 32 | */ 33 | 34 | // definition of endianess (e.g. needed on raspberry pi) 35 | #define PJ_IS_LITTLE_ENDIAN 1 36 | #define PJ_IS_BIG_ENDIAN 0 37 | 38 | // includes 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | // some espeak options 47 | #define ESPEAK_LANGUAGE "en" 48 | #define ESPEAK_AMPLITUDE 100 49 | #define ESPEAK_CAPITALS_PITCH 20 50 | #define ESPEAK_SPEED 150 51 | #define ESPEAK_PITCH 75 52 | 53 | // disable pjsua logging 54 | #define PJSUA_LOG_LEVEL 0 55 | 56 | // struct for app configuration settings 57 | struct app_config { 58 | char *sip_domain; 59 | char *sip_user; 60 | char *sip_password; 61 | char *phone_number; 62 | char *tts; 63 | char *tts_file; 64 | int record_call; 65 | char *record_file; 66 | int repetition_limit; 67 | int silent_mode; 68 | } app_cfg; 69 | 70 | // global helper vars 71 | int call_confirmed = 0; 72 | int media_counter = 0; 73 | int app_exiting = 0; 74 | 75 | // global vars for pjsua 76 | pjsua_acc_id acc_id; 77 | pjsua_player_id play_id = PJSUA_INVALID_ID; 78 | pjmedia_port *play_port; 79 | pjsua_recorder_id rec_id = PJSUA_INVALID_ID; 80 | 81 | // header of helper-methods 82 | static void create_player(pjsua_call_id); 83 | static void create_recorder(pjsua_call_info); 84 | static void log_message(char *); 85 | static void make_sip_call(); 86 | static void register_sip(void); 87 | static void setup_sip(void); 88 | static void synthesize_speech(char *); 89 | static void usage(int); 90 | static int try_get_argument(int, char *, char **, int, char *[]); 91 | 92 | // header of callback-methods 93 | static void on_call_media_state(pjsua_call_id); 94 | static void on_call_state(pjsua_call_id, pjsip_event *); 95 | static pj_status_t on_media_finished(pjmedia_port *, void *); 96 | static void signal_handler(int); 97 | 98 | // header of app-control-methods 99 | static void app_exit(); 100 | static void error_exit(const char *, pj_status_t); 101 | 102 | // main application 103 | int main(int argc, char *argv[]) 104 | { 105 | // first set some default values 106 | app_cfg.tts_file = "play.wav"; 107 | app_cfg.record_call = 0; 108 | app_cfg.repetition_limit = 3; 109 | app_cfg.silent_mode = 0; 110 | 111 | // parse arguments 112 | if (argc > 1) 113 | { 114 | int arg; 115 | for( arg = 1; arg < argc; arg+=2 ) 116 | { 117 | // check if usage info needs to be displayed 118 | if (!strcasecmp(argv[arg], "--help")) 119 | { 120 | // display usage info and exit app 121 | usage(0); 122 | exit(0); 123 | } 124 | 125 | // check for sip domain 126 | if (try_get_argument(arg, "-sd", &app_cfg.sip_domain, argc, argv) == 1) 127 | { 128 | continue; 129 | } 130 | 131 | // check for sip user 132 | if (try_get_argument(arg, "-su", &app_cfg.sip_user, argc, argv) == 1) 133 | { 134 | continue; 135 | } 136 | 137 | // check for sip password 138 | if (try_get_argument(arg, "-sp", &app_cfg.sip_password, argc, argv) == 1) 139 | { 140 | continue; 141 | } 142 | 143 | // check for target phone number 144 | if (try_get_argument(arg, "-pn", &app_cfg.phone_number, argc, argv) == 1) 145 | { 146 | continue; 147 | } 148 | 149 | // check for text to speak 150 | if (try_get_argument(arg, "-tts", &app_cfg.tts, argc, argv) == 1) 151 | { 152 | continue; 153 | } 154 | 155 | // check for record call option 156 | if (try_get_argument(arg, "-ttsf", &app_cfg.tts_file, argc, argv) == 1) 157 | { 158 | continue; 159 | } 160 | 161 | // check for record call option 162 | if (try_get_argument(arg, "-rcf", &app_cfg.record_file, argc, argv) == 1) 163 | { 164 | app_cfg.record_call = 1; 165 | continue; 166 | } 167 | 168 | // check for message repetition option 169 | char *mr; 170 | if (try_get_argument(arg, "-mr", &mr, argc, argv) == 1) 171 | { 172 | app_cfg.repetition_limit = atoi(mr); 173 | continue; 174 | } 175 | 176 | // check for silent mode option 177 | char *s; 178 | try_get_argument(arg, "-s", &s, argc, argv); 179 | if (!strcasecmp(s, "1")) 180 | { 181 | app_cfg.silent_mode = 1; 182 | continue; 183 | } 184 | } 185 | } 186 | else 187 | { 188 | // no arguments specified - display usage info and exit app 189 | usage(1); 190 | exit(1); 191 | } 192 | 193 | if (!app_cfg.sip_domain || !app_cfg.sip_user || !app_cfg.sip_password || !app_cfg.phone_number || !app_cfg.tts) 194 | { 195 | // too few arguments specified - display usage info and exit app 196 | usage(1); 197 | exit(1); 198 | } 199 | 200 | // print infos 201 | log_message("SIP Call - Simple TTS-based Automated Calls\n"); 202 | log_message("===========================================\n"); 203 | 204 | // register signal handler for break-in-keys (e.g. ctrl+c) 205 | signal(SIGINT, signal_handler); 206 | signal(SIGKILL, signal_handler); 207 | 208 | // synthesize speech 209 | synthesize_speech(app_cfg.tts_file); 210 | 211 | // setup up sip library pjsua 212 | setup_sip(); 213 | 214 | // create account and register to sip server 215 | register_sip(); 216 | 217 | // initiate call 218 | make_sip_call(); 219 | 220 | // app loop 221 | for (;;) { } 222 | 223 | // exit app 224 | app_exit(); 225 | 226 | return 0; 227 | } 228 | 229 | // helper for displaying usage infos 230 | static void usage(int error) 231 | { 232 | if (error == 1) 233 | { 234 | puts("Error, to few arguments."); 235 | puts (""); 236 | } 237 | puts ("Usage:"); 238 | puts (" sipcall [options]"); 239 | puts (""); 240 | puts ("Mandatory options:"); 241 | puts (" -sd=string Set sip provider domain."); 242 | puts (" -su=string Set sip username."); 243 | puts (" -sp=string Set sip password."); 244 | puts (" -pn=string Set target phone number to call"); 245 | puts (" -tts=string Text to speak"); 246 | puts (""); 247 | puts ("Optional options:"); 248 | puts (" -ttsf=string TTS speech file name to save text"); 249 | puts (" -rcf=string Record call file name to save answer"); 250 | puts (" -mr=int Repeat message x-times"); 251 | puts (" -s=int Silent mode (hide info messages) (0/1)"); 252 | puts (""); 253 | 254 | fflush(stdout); 255 | } 256 | 257 | // helper for parsing command-line-argument 258 | static int try_get_argument(int arg, char *arg_id, char **arg_val, int argc, char *argv[]) 259 | { 260 | int found = 0; 261 | 262 | // check if actual argument is searched argument 263 | if (!strcasecmp(argv[arg], arg_id)) 264 | { 265 | // check if actual argument has a value 266 | if (argc >= (arg+1)) 267 | { 268 | // set value 269 | *arg_val = argv[arg+1]; 270 | found = 1; 271 | } 272 | } 273 | return found; 274 | } 275 | 276 | // helper for logging messages to console (disabled if silent mode is active) 277 | static void log_message(char *message) 278 | { 279 | if (!app_cfg.silent_mode) 280 | { 281 | fprintf(stderr, message); 282 | } 283 | } 284 | 285 | // helper for setting up sip library pjsua 286 | static void setup_sip(void) 287 | { 288 | pj_status_t status; 289 | 290 | log_message("Setting up pjsua ... "); 291 | 292 | // create pjsua 293 | status = pjsua_create(); 294 | if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status); 295 | 296 | // configure pjsua 297 | pjsua_config cfg; 298 | pjsua_config_default(&cfg); 299 | 300 | // enable just 1 simultaneous call 301 | cfg.max_calls = 1; 302 | 303 | // callback configuration 304 | cfg.cb.on_call_media_state = &on_call_media_state; 305 | cfg.cb.on_call_state = &on_call_state; 306 | 307 | // logging configuration 308 | pjsua_logging_config log_cfg; 309 | pjsua_logging_config_default(&log_cfg); 310 | log_cfg.console_level = PJSUA_LOG_LEVEL; 311 | 312 | // initialize pjsua 313 | status = pjsua_init(&cfg, &log_cfg, NULL); 314 | if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status); 315 | 316 | // add udp transport 317 | pjsua_transport_config udpcfg; 318 | pjsua_transport_config_default(&udpcfg); 319 | 320 | udpcfg.port = 5060; 321 | status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &udpcfg, NULL); 322 | if (status != PJ_SUCCESS) error_exit("Error creating transport", status); 323 | 324 | // initialization is done, start pjsua 325 | status = pjsua_start(); 326 | if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status); 327 | 328 | // disable sound - use null sound device 329 | status = pjsua_set_null_snd_dev(); 330 | if (status != PJ_SUCCESS) error_exit("Error disabling audio", status); 331 | 332 | log_message("Done.\n"); 333 | } 334 | 335 | // helper for creating and registering sip-account 336 | static void register_sip(void) 337 | { 338 | pj_status_t status; 339 | 340 | log_message("Registering account ... "); 341 | 342 | // prepare account configuration 343 | pjsua_acc_config cfg; 344 | pjsua_acc_config_default(&cfg); 345 | 346 | // build sip-user-url 347 | char sip_user_url[40]; 348 | sprintf(sip_user_url, "sip:%s@%s", app_cfg.sip_user, app_cfg.sip_domain); 349 | 350 | // build sip-provder-url 351 | char sip_provider_url[40]; 352 | sprintf(sip_provider_url, "sip:%s", app_cfg.sip_domain); 353 | 354 | // create and define account 355 | cfg.id = pj_str(sip_user_url); 356 | cfg.reg_uri = pj_str(sip_provider_url); 357 | cfg.cred_count = 1; 358 | cfg.cred_info[0].realm = pj_str(app_cfg.sip_domain); 359 | cfg.cred_info[0].scheme = pj_str("digest"); 360 | cfg.cred_info[0].username = pj_str(app_cfg.sip_user); 361 | cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; 362 | cfg.cred_info[0].data = pj_str(app_cfg.sip_password); 363 | 364 | // add account 365 | status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id); 366 | if (status != PJ_SUCCESS) error_exit("Error adding account", status); 367 | 368 | log_message("Done.\n"); 369 | } 370 | 371 | // helper for making calls over sip-account 372 | static void make_sip_call() 373 | { 374 | pj_status_t status; 375 | 376 | log_message("Starting call ... "); 377 | 378 | // build target sip-url 379 | char sip_target_url[40]; 380 | sprintf(sip_target_url, "sip:%s@%s", app_cfg.phone_number, app_cfg.sip_domain); 381 | 382 | // start call with sip-url 383 | pj_str_t uri = pj_str(sip_target_url); 384 | status = pjsua_call_make_call(acc_id, &uri, 0, NULL, NULL, NULL); 385 | if (status != PJ_SUCCESS) error_exit("Error making call", status); 386 | 387 | log_message("Done.\n"); 388 | } 389 | 390 | // helper for creating call-media-player 391 | static void create_player(pjsua_call_id call_id) 392 | { 393 | // get call infos 394 | pjsua_call_info ci; 395 | pjsua_call_get_info(call_id, &ci); 396 | 397 | pj_str_t name; 398 | pj_status_t status = PJ_ENOTFOUND; 399 | 400 | log_message("Creating player ... "); 401 | 402 | // create player for playback media 403 | status = pjsua_player_create(pj_cstr(&name, app_cfg.tts_file), 0, &play_id); 404 | if (status != PJ_SUCCESS) error_exit("Error playing sound-playback", status); 405 | 406 | // connect active call to media player 407 | pjsua_conf_connect(pjsua_player_get_conf_port(play_id), ci.conf_slot); 408 | 409 | // get media port (play_port) from play_id 410 | status = pjsua_player_get_port(play_id, &play_port); 411 | if (status != PJ_SUCCESS) error_exit("Error getting sound player port", status); 412 | 413 | // register media finished callback 414 | status = pjmedia_wav_player_set_eof_cb(play_port, NULL, &on_media_finished); 415 | if (status != PJ_SUCCESS) error_exit("Error adding sound-playback callback", status); 416 | 417 | log_message("Done.\n"); 418 | } 419 | 420 | // helper for creating call-recorder 421 | static void create_recorder(pjsua_call_info ci) 422 | { 423 | // specify target file 424 | pj_str_t rec_file = pj_str(app_cfg.record_file); 425 | pj_status_t status = PJ_ENOTFOUND; 426 | 427 | log_message("Creating recorder ... "); 428 | 429 | // Create recorder for call 430 | status = pjsua_recorder_create(&rec_file, 0, NULL, 0, 0, &rec_id); 431 | if (status != PJ_SUCCESS) error_exit("Error recording answer", status); 432 | 433 | // connect active call to call recorder 434 | pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(rec_id); 435 | pjsua_conf_connect(ci.conf_slot, rec_port); 436 | 437 | log_message("Done.\n"); 438 | } 439 | 440 | // synthesize speech / create message via espeak 441 | static void synthesize_speech(char *file) 442 | { 443 | log_message("Synthesizing speech ... "); 444 | 445 | int speech_status = -1; 446 | char speech_command[200]; 447 | 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); 448 | speech_status = system(speech_command); 449 | if (speech_status != 0) error_exit("Error while creating phone text", speech_status); 450 | 451 | log_message("Done.\n"); 452 | } 453 | 454 | // handler for call-media-state-change-events 455 | static void on_call_media_state(pjsua_call_id call_id) 456 | { 457 | // get call infos 458 | pjsua_call_info ci; 459 | pjsua_call_get_info(call_id, &ci); 460 | 461 | pj_status_t status = PJ_ENOTFOUND; 462 | 463 | // check state if call is established/active 464 | if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) { 465 | 466 | log_message("Call media activated.\n"); 467 | 468 | // create and start media player 469 | create_player(call_id); 470 | 471 | // create and start call recorder 472 | if (app_cfg.record_call) 473 | { 474 | create_recorder(ci); 475 | } 476 | } 477 | } 478 | 479 | // handler for call-state-change-events 480 | static void on_call_state(pjsua_call_id call_id, pjsip_event *e) 481 | { 482 | // get call infos 483 | pjsua_call_info ci; 484 | pjsua_call_get_info(call_id, &ci); 485 | 486 | // prevent warning about unused argument e 487 | PJ_UNUSED_ARG(e); 488 | 489 | // check call state 490 | if (ci.state == PJSIP_INV_STATE_CONFIRMED) 491 | { 492 | log_message("Call confirmed.\n"); 493 | 494 | call_confirmed = 1; 495 | 496 | // ensure that message is played from start 497 | if (play_id != PJSUA_INVALID_ID) 498 | { 499 | pjmedia_wav_player_port_set_pos(play_port, 0); 500 | } 501 | } 502 | if (ci.state == PJSIP_INV_STATE_DISCONNECTED) 503 | { 504 | log_message("Call disconnected.\n"); 505 | 506 | // exit app if call is finished/disconnected 507 | app_exit(); 508 | } 509 | } 510 | 511 | // handler for media-finished-events 512 | static pj_status_t on_media_finished(pjmedia_port *media_port, void *user_data) 513 | { 514 | PJ_UNUSED_ARG(media_port); 515 | PJ_UNUSED_ARG(user_data); 516 | 517 | if (call_confirmed) 518 | { 519 | // count repetition 520 | media_counter++; 521 | 522 | // exit app if repetition limit is reached 523 | if (app_cfg.repetition_limit <= media_counter) 524 | { 525 | app_exit(); 526 | } 527 | } 528 | 529 | pj_status_t status; 530 | return status; 531 | } 532 | 533 | // handler for "break-in-key"-events (e.g. ctrl+c) 534 | static void signal_handler(int signal) 535 | { 536 | // exit app 537 | app_exit(); 538 | } 539 | 540 | // clean application exit 541 | static void app_exit() 542 | { 543 | if (!app_exiting) 544 | { 545 | app_exiting = 1; 546 | log_message("Stopping application ... "); 547 | 548 | // check if player/recorder is active and stop them 549 | if (play_id != -1) pjsua_player_destroy(play_id); 550 | if (rec_id != -1) pjsua_recorder_destroy(rec_id); 551 | 552 | // hangup open calls and stop pjsua 553 | pjsua_call_hangup_all(); 554 | pjsua_destroy(); 555 | 556 | log_message("Done.\n"); 557 | 558 | exit(0); 559 | } 560 | } 561 | 562 | // display error and exit application 563 | static void error_exit(const char *title, pj_status_t status) 564 | { 565 | if (!app_exiting) 566 | { 567 | app_exiting = 1; 568 | 569 | pjsua_perror("SIP Call", title, status); 570 | 571 | // check if player/recorder is active and stop them 572 | if (play_id != -1) pjsua_player_destroy(play_id); 573 | if (rec_id != -1) pjsua_recorder_destroy(rec_id); 574 | 575 | // hangup open calls and stop pjsua 576 | pjsua_call_hangup_all(); 577 | pjsua_destroy(); 578 | 579 | exit(1); 580 | } 581 | } -------------------------------------------------------------------------------- /tools/c/sip-tools/sipserv-ctrl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | #================================================================================= 4 | # Name : sipserv-ctrl.sh 5 | # Version : 0.1 6 | # 7 | # Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 8 | # 9 | # Description : 10 | # Sample Script for controlling sipserv. 11 | # 12 | # Dependencies: 13 | # - sipcall 14 | # 15 | # References : 16 | # http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine 17 | # 18 | #================================================================================ 19 | #This script is free software; you can redistribute it and/or 20 | #modify it under the terms of the GNU Lesser General Public 21 | #License as published by the Free Software Foundation; either 22 | #version 2.1 of the License, or (at your option) any later version. 23 | # 24 | #This script is distributed in the hope that it will be useful, 25 | #but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 27 | #Lesser General Public License for more details. 28 | #================================================================================ 29 | 30 | # define config-file 31 | serv_cfg="sipserv.cfg"; 32 | 33 | if [ $1 = "start" ]; then 34 | # start sipserv in background 35 | $(./sipserv -s 1 --config-file $serv_cfg > /dev/null &); 36 | echo "sipserv started."; 37 | fi 38 | 39 | if [ $1 = "stop" ]; then 40 | # stop sipserv 41 | pid="$(ps aux | awk '/[s]ipserv/ {print $2}' | head -1)"; 42 | $(kill $pid > /dev/null); 43 | echo "sipserv stopped."; 44 | fi -------------------------------------------------------------------------------- /tools/c/sip-tools/sipserv-sample.cfg: -------------------------------------------------------------------------------- 1 | # SIP account data 2 | sd=samplesip.com 3 | su=12345678 4 | sp=XXXXXX 5 | 6 | # disable call recording 7 | rc=0 8 | 9 | # intro message 10 | tts=Hello, this is raspberry pi and this are your options: 11 | 12 | # dtmf configuration 13 | dtmf.1.active=1 14 | dtmf.1.description=Get average load 15 | dtmf.1.tts-intro=Press 1 to get the average system load within last 5 minutes. 16 | dtmf.1.tts-answer=The average load within last 5 minutes is %s. 17 | dtmf.1.cmd=uptime |awk -F'average: ' '{print $2}' |awk -F', ' '{print $2}' 18 | 19 | dtmf.2.active=1 20 | dtmf.2.description=Get free memory 21 | dtmf.2.tts-intro=Press 2 to get the actual free memory. 22 | dtmf.2.tts-answer=The currently free memory is %s megabytes. 23 | dtmf.2.cmd=free |awk '/^Mem:/{print ($2/1024)}' 24 | 25 | dtmf.3.active=0 26 | dtmf.3.description= 27 | dtmf.3.tts-intro= 28 | dtmf.3.tts-answer= 29 | dtmf.3.cmd= 30 | 31 | dtmf.4.active=0 32 | dtmf.4.description= 33 | dtmf.4.tts-intro= 34 | dtmf.4.tts-answer= 35 | dtmf.4.cmd= 36 | 37 | dtmf.5.active=0 38 | dtmf.5.description= 39 | dtmf.5.tts-intro= 40 | dtmf.5.tts-answer= 41 | dtmf.5.cmd= 42 | 43 | dtmf.6.active=0 44 | dtmf.6.description= 45 | dtmf.6.tts-intro= 46 | dtmf.6.tts-answer= 47 | dtmf.6.cmd= 48 | 49 | dtmf.7.active=0 50 | dtmf.7.description= 51 | dtmf.7.tts-intro= 52 | dtmf.7.tts-answer= 53 | dtmf.7.cmd= 54 | 55 | dtmf.8.active=0 56 | dtmf.8.description= 57 | dtmf.8.tts-intro= 58 | dtmf.8.tts-answer= 59 | dtmf.8.cmd= 60 | 61 | dtmf.9.active=0 62 | dtmf.9.description= 63 | dtmf.9.tts-intro= 64 | dtmf.9.tts-answer= 65 | dtmf.9.cmd= -------------------------------------------------------------------------------- /tools/c/sip-tools/sipserv.c: -------------------------------------------------------------------------------- 1 | /* 2 | ================================================================================= 3 | Name : sipserv.c 4 | Version : 0.1 5 | 6 | Copyright (C) 2012 by Andre Wussow, 2012, desk@binerry.de 7 | 8 | Description : 9 | Tool for automated, flexible answered calls over SIP/VOIP with PJSUA library and eSpeak. 10 | 11 | Dependencies: 12 | - PJSUA API (PJSIP) 13 | - eSpeak 14 | 15 | References : 16 | http://www.pjsip.org/ 17 | http://www.pjsip.org/docs/latest/pjsip/docs/html/group__PJSUA__LIB.htm 18 | http://espeak.sourceforge.net/ 19 | http://binerry.de/post/29180946733/raspberry-pi-caller-and-answering-machine 20 | 21 | ================================================================================ 22 | This tool is free software; you can redistribute it and/or 23 | modify it under the terms of the GNU Lesser General Public 24 | License as published by the Free Software Foundation; either 25 | version 2.1 of the License, or (at your option) any later version. 26 | 27 | This tool is distributed in the hope that it will be useful, 28 | but WITHOUT ANY WARRANTY; without even the implied warranty of 29 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 30 | Lesser General Public License for more details. 31 | ================================================================================ 32 | */ 33 | 34 | // definition of endianess (e.g. needed on raspberry pi) 35 | #define PJ_IS_LITTLE_ENDIAN 1 36 | #define PJ_IS_BIG_ENDIAN 0 37 | 38 | // includes 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | // some espeak options 47 | #define ESPEAK_LANGUAGE "en" 48 | #define ESPEAK_AMPLITUDE 100 49 | #define ESPEAK_CAPITALS_PITCH 20 50 | #define ESPEAK_SPEED 125 51 | #define ESPEAK_PITCH 75 52 | 53 | // disable pjsua logging 54 | #define PJSUA_LOG_LEVEL 0 55 | 56 | // define max supported dtmf settings 57 | #define MAX_DTMF_SETTINGS 9 58 | 59 | // struct for app dtmf settings 60 | struct dtmf_config { 61 | int id; 62 | int active; 63 | int processing_active; 64 | char *description; 65 | char *tts_intro; 66 | char *tts_answer; 67 | char *cmd; 68 | }; 69 | 70 | // struct for app configuration settings 71 | struct app_config { 72 | char *sip_domain; 73 | char *sip_user; 74 | char *sip_password; 75 | int record_calls; 76 | int silent_mode; 77 | char *tts; 78 | char *log_file; 79 | struct dtmf_config dtmf_cfg[MAX_DTMF_SETTINGS]; 80 | } app_cfg; 81 | 82 | // global holder vars for further app arguments 83 | char *tts_file = "play.wav"; 84 | char *tts_answer_file = "ans.wav"; 85 | char *rec_ans_file = "rec.wav"; 86 | 87 | // global helper vars 88 | int call_confirmed = 0; 89 | int media_counter = 0; 90 | int app_exiting = 0; 91 | 92 | // global vars for pjsua 93 | pjsua_acc_id acc_id; 94 | pjsua_player_id play_id = PJSUA_INVALID_ID; 95 | pjmedia_port *play_port; 96 | pjsua_recorder_id rec_id = PJSUA_INVALID_ID; 97 | pjsua_call_id current_call = PJSUA_INVALID_ID; 98 | 99 | // header of helper-methods 100 | static void create_player(pjsua_call_id, char *); 101 | static void create_recorder(pjsua_call_info); 102 | static void log_message(char *); 103 | static void parse_config_file(char *); 104 | static void register_sip(void); 105 | static void setup_sip(void); 106 | static int synthesize_speech(char *, char *); 107 | static void usage(int); 108 | static int try_get_argument(int, char *, char **, int, char *[]); 109 | 110 | // header of callback-methods 111 | static void on_incoming_call(pjsua_acc_id, pjsua_call_id, pjsip_rx_data *); 112 | static void on_call_media_state(pjsua_call_id); 113 | static void on_call_state(pjsua_call_id, pjsip_event *); 114 | static void on_dtmf_digit(pjsua_call_id, int); 115 | static void signal_handler(int); 116 | static char *trim_string(char *); 117 | 118 | // header of app-control-methods 119 | static void app_exit(); 120 | static void error_exit(const char *, pj_status_t); 121 | 122 | // main application 123 | int main(int argc, char *argv[]) 124 | { 125 | // first set some default values 126 | app_cfg.record_calls = 0; 127 | app_cfg.silent_mode = 0; 128 | 129 | // init dtmf settings (dtmf 0 is reserved for exit call) 130 | int i; 131 | for (i = 0; i < MAX_DTMF_SETTINGS; i++) 132 | { 133 | struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[i]; 134 | d_cfg->id = i+1; 135 | d_cfg->active = 0; 136 | d_cfg->processing_active = 0; 137 | } 138 | 139 | // parse arguments 140 | if (argc > 1) 141 | { 142 | int arg; 143 | for( arg = 1; arg < argc; arg+=2 ) 144 | { 145 | // check if usage info needs to be displayed 146 | if (!strcasecmp(argv[arg], "--help")) 147 | { 148 | // display usage info and exit app 149 | usage(0); 150 | exit(0); 151 | } 152 | 153 | // check for config file location 154 | if (!strcasecmp(argv[arg], "--config-file")) 155 | { 156 | if (argc >= (arg+1)) 157 | { 158 | app_cfg.log_file = argv[arg+1]; 159 | } 160 | continue; 161 | } 162 | 163 | // check for silent mode option 164 | char *s; 165 | try_get_argument(arg, "-s", &s, argc, argv); 166 | if (!strcasecmp(s, "1")) 167 | { 168 | app_cfg.silent_mode = 1; 169 | continue; 170 | } 171 | } 172 | } 173 | 174 | if (!app_cfg.log_file) 175 | { 176 | // too few arguments specified - display usage info and exit app 177 | usage(1); 178 | exit(1); 179 | } 180 | 181 | // read app configuration from config file 182 | parse_config_file(app_cfg.log_file); 183 | 184 | if (!app_cfg.sip_domain || !app_cfg.sip_user || !app_cfg.sip_password) 185 | { 186 | // too few arguments specified - display usage info and exit app 187 | usage(1); 188 | exit(1); 189 | } 190 | 191 | // print infos 192 | log_message("SIP Call - Simple TTS/DTMF-based answering machine\n"); 193 | log_message("==================================================\n"); 194 | 195 | // register signal handler for break-in-keys (e.g. ctrl+c) 196 | signal(SIGINT, signal_handler); 197 | signal(SIGKILL, signal_handler); 198 | 199 | // generate texts 200 | log_message("Generating texts ... "); 201 | 202 | char tts_buffer[1024]; 203 | strcpy(tts_buffer, app_cfg.tts); 204 | strcat(tts_buffer, " "); 205 | 206 | for (i = 0; i < MAX_DTMF_SETTINGS; i++) 207 | { 208 | struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[i]; 209 | 210 | if (d_cfg->active == 1) 211 | { 212 | strcat(tts_buffer, d_cfg->tts_intro); 213 | strcat(tts_buffer, " "); 214 | } 215 | } 216 | 217 | log_message("Done.\n"); 218 | 219 | // synthesizing speech 220 | log_message("Synthesizing speech ... "); 221 | 222 | int synth_status = -1; 223 | synth_status = synthesize_speech(tts_buffer, tts_file); 224 | if (synth_status != 0) error_exit("Error while creating phone text", synth_status); 225 | log_message("Done.\n"); 226 | 227 | // setup up sip library pjsua 228 | setup_sip(); 229 | 230 | // create account and register to sip server 231 | register_sip(); 232 | 233 | // app loop 234 | for (;;) { } 235 | 236 | // exit app 237 | app_exit(); 238 | 239 | return 0; 240 | } 241 | 242 | // helper for displaying usage infos 243 | static void usage(int error) 244 | { 245 | if (error == 1) 246 | { 247 | puts("Error, to few arguments."); 248 | puts (""); 249 | } 250 | puts ("Usage:"); 251 | puts (" sipserv [options]"); 252 | puts (""); 253 | puts ("Commandline:"); 254 | puts ("Mandatory options:"); 255 | puts (" --config-file=string Set config file"); 256 | puts (""); 257 | puts ("Optional options:"); 258 | puts (" -s=int Silent mode (hide info messages) (0/1)"); 259 | puts (""); 260 | puts (""); 261 | puts ("Config file:"); 262 | puts ("Mandatory options:"); 263 | puts (" sd=string Set sip provider domain."); 264 | puts (" su=string Set sip username."); 265 | puts (" sp=string Set sip password."); 266 | puts (""); 267 | puts (" and at least one dtmf configuration (X = dtmf-key index):"); 268 | puts (" dtmf.X.active=int Set dtmf-setting active (0/1)."); 269 | puts (" dtmf.X.description=string Set description."); 270 | puts (" dtmf.X.tts-intro=string Set tts intro."); 271 | puts (" dtmf.X.tts-answer=string Set tts answer."); 272 | puts (" dtmf.X.cmd=string Set dtmf command."); 273 | puts (""); 274 | puts ("Optional options:"); 275 | puts (" rc=int Record call (0/1)"); 276 | puts (""); 277 | 278 | fflush(stdout); 279 | } 280 | 281 | // helper for parsing command-line-argument 282 | static int try_get_argument(int arg, char *arg_id, char **arg_val, int argc, char *argv[]) 283 | { 284 | int found = 0; 285 | 286 | // check if actual argument is searched argument 287 | if (!strcasecmp(argv[arg], arg_id)) 288 | { 289 | // check if actual argument has a value 290 | if (argc >= (arg+1)) 291 | { 292 | // set value 293 | *arg_val = argv[arg+1]; 294 | found = 1; 295 | } 296 | } 297 | return found; 298 | } 299 | 300 | // helper for parsing config file 301 | static void parse_config_file(char *cfg_file) 302 | { 303 | // open config file 304 | char line[200]; 305 | FILE *file = fopen(cfg_file, "r"); 306 | 307 | if (file!=NULL) 308 | { 309 | // start parsing file 310 | while(fgets(line, 200, file) != NULL) 311 | { 312 | char *arg, *val; 313 | 314 | // ignore comments and just new lines 315 | if(line[0] == '#') continue; 316 | if(line[0] == '\n') continue; 317 | 318 | // split string at '='-char 319 | arg = strtok(line, "="); 320 | if (arg == NULL) continue; 321 | val = strtok(NULL, "="); 322 | 323 | // check for new line char and remove it 324 | char *nl_check; 325 | nl_check = strstr (val, "\n"); 326 | if (nl_check != NULL) strncpy(nl_check, " ", 1); 327 | 328 | // remove trailing spaces 329 | 330 | 331 | // duplicate string for having own instance of it 332 | char *arg_val = strdup(val); 333 | 334 | // check for sip domain argument 335 | if (!strcasecmp(arg, "sd")) 336 | { 337 | app_cfg.sip_domain = trim_string(arg_val); 338 | continue; 339 | } 340 | 341 | // check for sip user argument 342 | if (!strcasecmp(arg, "su")) 343 | { 344 | app_cfg.sip_user = trim_string(arg_val); 345 | continue; 346 | } 347 | 348 | // check for sip domain argument 349 | if (!strcasecmp(arg, "sp")) 350 | { 351 | app_cfg.sip_password = trim_string(arg_val); 352 | continue; 353 | } 354 | 355 | // check for record calls argument 356 | if (!strcasecmp(arg, "rc")) 357 | { 358 | app_cfg.record_calls = atoi(val); 359 | continue; 360 | } 361 | 362 | // check for silent mode argument 363 | if (!strcasecmp(arg, "s")) 364 | { 365 | app_cfg.silent_mode = atoi(val); 366 | continue; 367 | } 368 | 369 | // check for tts intro 370 | if (!strcasecmp(arg, "tts")) 371 | { 372 | app_cfg.tts = arg_val; 373 | continue; 374 | } 375 | 376 | // check for a dtmf argument 377 | char dtmf_id[1]; 378 | char dtmf_setting[25]; 379 | if(sscanf(arg, "dtmf.%1[^.].%s", dtmf_id, dtmf_setting) == 2) 380 | { 381 | // parse dtmf id (key) 382 | int d_id; 383 | d_id = atoi(dtmf_id); 384 | 385 | // check if actual dtmf id blasts maxium settings 386 | if (d_id >= MAX_DTMF_SETTINGS) continue; 387 | 388 | // get pointer to actual dtmf_cfg entry 389 | struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[d_id-1]; 390 | 391 | // check for dtmf active setting 392 | if (!strcasecmp(dtmf_setting, "active")) 393 | { 394 | d_cfg->active = atoi(val); 395 | continue; 396 | } 397 | 398 | // check for dtmf description setting 399 | if (!strcasecmp(dtmf_setting, "description")) 400 | { 401 | d_cfg->description = arg_val; 402 | continue; 403 | } 404 | 405 | // check for dtmf tts intro setting 406 | if (!strcasecmp(dtmf_setting, "tts-intro")) 407 | { 408 | d_cfg->tts_intro = arg_val; 409 | continue; 410 | } 411 | 412 | // check for dtmf tts answer setting 413 | if (!strcasecmp(dtmf_setting, "tts-answer")) 414 | { 415 | d_cfg->tts_answer = arg_val; 416 | continue; 417 | } 418 | 419 | // check for dtmf cmd setting 420 | if (!strcasecmp(dtmf_setting, "cmd")) 421 | { 422 | d_cfg->cmd = arg_val; 423 | continue; 424 | } 425 | } 426 | 427 | // write warning if unknown configuration setting is found 428 | char warning[200]; 429 | sprintf(warning, "Warning: Unknown configuration with arg '%s' and val '%s'\n", arg, val); 430 | log_message(warning); 431 | } 432 | } 433 | else 434 | { 435 | // return if config file not found 436 | log_message("Error while parsing config file: Not found.\n"); 437 | exit(1); 438 | } 439 | } 440 | 441 | // helper for removing leading and trailing strings (source taken from kernel source, lib/string.c) 442 | static char *trim_string(char *str) 443 | { 444 | while (isspace(*str)) ++str; 445 | 446 | char *s = (char *)str; 447 | 448 | size_t size; 449 | char *end; 450 | 451 | size = strlen(s); 452 | if (!size) return s; 453 | 454 | end = s + size - 1; 455 | while (end >= s && isspace(*end)) end--; 456 | *(end + 1) = '\0'; 457 | 458 | return s; 459 | } 460 | 461 | 462 | // helper for logging messages to console (disabled if silent mode is active) 463 | static void log_message(char *message) 464 | { 465 | if (!app_cfg.silent_mode) 466 | { 467 | fprintf(stderr, message); 468 | } 469 | } 470 | 471 | // helper for setting up sip library pjsua 472 | static void setup_sip(void) 473 | { 474 | pj_status_t status; 475 | 476 | log_message("Setting up pjsua ... "); 477 | 478 | // create pjsua 479 | status = pjsua_create(); 480 | if (status != PJ_SUCCESS) error_exit("Error in pjsua_create()", status); 481 | 482 | // configure pjsua 483 | pjsua_config cfg; 484 | pjsua_config_default(&cfg); 485 | 486 | // enable just 1 simultaneous call 487 | cfg.max_calls = 1; 488 | 489 | // callback configuration 490 | cfg.cb.on_incoming_call = &on_incoming_call; 491 | cfg.cb.on_call_media_state = &on_call_media_state; 492 | cfg.cb.on_call_state = &on_call_state; 493 | cfg.cb.on_dtmf_digit = &on_dtmf_digit; 494 | 495 | // logging configuration 496 | pjsua_logging_config log_cfg; 497 | pjsua_logging_config_default(&log_cfg); 498 | log_cfg.console_level = PJSUA_LOG_LEVEL; 499 | 500 | // media configuration 501 | pjsua_media_config media_cfg; 502 | pjsua_media_config_default(&media_cfg); 503 | media_cfg.snd_play_latency = 100; 504 | media_cfg.clock_rate = 8000; 505 | media_cfg.snd_clock_rate = 8000; 506 | media_cfg.quality = 10; 507 | 508 | // initialize pjsua 509 | status = pjsua_init(&cfg, &log_cfg, &media_cfg); 510 | if (status != PJ_SUCCESS) error_exit("Error in pjsua_init()", status); 511 | 512 | // add udp transport 513 | pjsua_transport_config udpcfg; 514 | pjsua_transport_config_default(&udpcfg); 515 | 516 | udpcfg.port = 5060; 517 | status = pjsua_transport_create(PJSIP_TRANSPORT_UDP, &udpcfg, NULL); 518 | if (status != PJ_SUCCESS) error_exit("Error creating transport", status); 519 | 520 | // initialization is done, start pjsua 521 | status = pjsua_start(); 522 | if (status != PJ_SUCCESS) error_exit("Error starting pjsua", status); 523 | 524 | // disable sound - use null sound device 525 | status = pjsua_set_null_snd_dev(); 526 | if (status != PJ_SUCCESS) error_exit("Error disabling audio", status); 527 | 528 | log_message("Done.\n"); 529 | } 530 | 531 | // helper for creating and registering sip-account 532 | static void register_sip(void) 533 | { 534 | pj_status_t status; 535 | 536 | log_message("Registering account ... "); 537 | 538 | // prepare account configuration 539 | pjsua_acc_config cfg; 540 | pjsua_acc_config_default(&cfg); 541 | 542 | // build sip-user-url 543 | char sip_user_url[40]; 544 | sprintf(sip_user_url, "sip:%s@%s", app_cfg.sip_user, app_cfg.sip_domain); 545 | 546 | // build sip-provder-url 547 | char sip_provider_url[40]; 548 | sprintf(sip_provider_url, "sip:%s", app_cfg.sip_domain); 549 | 550 | // create and define account 551 | cfg.id = pj_str(sip_user_url); 552 | cfg.reg_uri = pj_str(sip_provider_url); 553 | cfg.cred_count = 1; 554 | cfg.cred_info[0].realm = pj_str(app_cfg.sip_domain); 555 | cfg.cred_info[0].scheme = pj_str("digest"); 556 | cfg.cred_info[0].username = pj_str(app_cfg.sip_user); 557 | cfg.cred_info[0].data_type = PJSIP_CRED_DATA_PLAIN_PASSWD; 558 | cfg.cred_info[0].data = pj_str(app_cfg.sip_password); 559 | 560 | // add account 561 | status = pjsua_acc_add(&cfg, PJ_TRUE, &acc_id); 562 | if (status != PJ_SUCCESS) error_exit("Error adding account", status); 563 | 564 | log_message("Done.\n"); 565 | } 566 | 567 | // helper for creating call-media-player 568 | static void create_player(pjsua_call_id call_id, char *file) 569 | { 570 | // get call infos 571 | pjsua_call_info ci; 572 | pjsua_call_get_info(call_id, &ci); 573 | 574 | pj_str_t name; 575 | pj_status_t status = PJ_ENOTFOUND; 576 | 577 | log_message("Creating player ... "); 578 | 579 | // create player for playback media 580 | status = pjsua_player_create(pj_cstr(&name, file), PJMEDIA_FILE_NO_LOOP, &play_id); 581 | if (status != PJ_SUCCESS) error_exit("Error playing sound-playback", status); 582 | 583 | // connect active call to media player 584 | pjsua_conf_connect(pjsua_player_get_conf_port(play_id), ci.conf_slot); 585 | 586 | // get media port (play_port) from play_id 587 | status = pjsua_player_get_port(play_id, &play_port); 588 | if (status != PJ_SUCCESS) error_exit("Error getting sound player port", status); 589 | 590 | log_message("Done.\n"); 591 | } 592 | 593 | // helper for creating call-recorder 594 | static void create_recorder(pjsua_call_info ci) 595 | { 596 | // specify target file 597 | pj_str_t rec_file = pj_str(rec_ans_file); 598 | pj_status_t status = PJ_ENOTFOUND; 599 | 600 | log_message("Creating recorder ... "); 601 | 602 | // Create recorder for call 603 | status = pjsua_recorder_create(&rec_file, 0, NULL, 0, 0, &rec_id); 604 | if (status != PJ_SUCCESS) error_exit("Error recording answer", status); 605 | 606 | // connect active call to call recorder 607 | pjsua_conf_port_id rec_port = pjsua_recorder_get_conf_port(rec_id); 608 | pjsua_conf_connect(ci.conf_slot, rec_port); 609 | 610 | log_message("Done.\n"); 611 | } 612 | 613 | // synthesize speech / create message via espeak 614 | static int synthesize_speech(char *speech, char *file) 615 | { 616 | int speech_status = -1; 617 | 618 | char speech_command[1024]; 619 | 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); 620 | speech_status = system(speech_command); 621 | 622 | return speech_status; 623 | } 624 | 625 | // handler for incoming-call-events 626 | static void on_incoming_call(pjsua_acc_id acc_id, pjsua_call_id call_id, pjsip_rx_data *rdata) 627 | { 628 | // get call infos 629 | pjsua_call_info ci; 630 | pjsua_call_get_info(call_id, &ci); 631 | 632 | PJ_UNUSED_ARG(acc_id); 633 | PJ_UNUSED_ARG(rdata); 634 | 635 | current_call = call_id; 636 | 637 | // log call info 638 | char info[100]; 639 | sprintf(info, "Incoming call from %s\n", ci.remote_info.ptr); 640 | log_message(info); 641 | 642 | // automatically answer incoming call with 200 status/OK 643 | pjsua_call_answer(call_id, 200, NULL, NULL); 644 | } 645 | 646 | // handler for call-media-state-change-events 647 | static void on_call_media_state(pjsua_call_id call_id) 648 | { 649 | // get call infos 650 | pjsua_call_info ci; 651 | pjsua_call_get_info(call_id, &ci); 652 | 653 | pj_status_t status = PJ_ENOTFOUND; 654 | 655 | // check state if call is established/active 656 | if (ci.media_status == PJSUA_CALL_MEDIA_ACTIVE) { 657 | 658 | log_message("Call media activated.\n"); 659 | 660 | // create and start media player 661 | create_player(call_id, tts_file); 662 | 663 | // create and start call recorder 664 | if (app_cfg.record_calls) 665 | { 666 | create_recorder(ci); 667 | } 668 | } 669 | } 670 | 671 | // handler for call-state-change-events 672 | static void on_call_state(pjsua_call_id call_id, pjsip_event *e) 673 | { 674 | // get call infos 675 | pjsua_call_info ci; 676 | pjsua_call_get_info(call_id, &ci); 677 | 678 | // prevent warning about unused argument e 679 | PJ_UNUSED_ARG(e); 680 | 681 | // check call state 682 | if (ci.state == PJSIP_INV_STATE_CONFIRMED) 683 | { 684 | log_message("Call confirmed.\n"); 685 | 686 | call_confirmed = 1; 687 | 688 | // ensure that message is played from start 689 | if (play_id != PJSUA_INVALID_ID) 690 | { 691 | pjmedia_wav_player_port_set_pos(play_port, 0); 692 | } 693 | } 694 | if (ci.state == PJSIP_INV_STATE_DISCONNECTED) 695 | { 696 | log_message("Call disconnected.\n"); 697 | 698 | // disable player 699 | if (play_id != -1) pjsua_player_destroy(play_id); 700 | } 701 | } 702 | 703 | // handler for dtmf-events 704 | static void on_dtmf_digit(pjsua_call_id call_id, int digit) 705 | { 706 | // get call infos 707 | pjsua_call_info ci; 708 | pjsua_call_get_info(call_id, &ci); 709 | 710 | // work on detected dtmf digit 711 | int dtmf_key = digit - 48; 712 | 713 | char info[100]; 714 | sprintf(info, "DTMF command detected: %i\n", dtmf_key); 715 | log_message(info); 716 | 717 | struct dtmf_config *d_cfg = &app_cfg.dtmf_cfg[dtmf_key-1]; 718 | if (d_cfg->processing_active == 0) 719 | { 720 | d_cfg->processing_active = 1; 721 | 722 | if (d_cfg->active == 1) 723 | { 724 | log_message("Active DTMF command found for received digit.\n"); 725 | log_message("Creating answer ... "); 726 | 727 | int error = 0; 728 | FILE *fp; 729 | 730 | fp = popen(d_cfg->cmd, "r"); 731 | if (fp == NULL) { 732 | error = 1; 733 | log_message(" (Failed to run command) "); 734 | } 735 | 736 | char result[20]; 737 | if (!error) 738 | { 739 | if (fgets(result, sizeof(result)-1, fp) == NULL) 740 | { 741 | error = 1; 742 | log_message(" (Failed to read result) "); 743 | } 744 | } 745 | 746 | if (!error) 747 | { 748 | if (play_id != -1) pjsua_player_destroy(play_id); 749 | 750 | char tts_buffer[200]; 751 | sprintf(tts_buffer, d_cfg->tts_answer, result); 752 | 753 | int synth_status = -1; 754 | synth_status = synthesize_speech(tts_buffer, tts_answer_file); 755 | if (synth_status != 0) log_message(" (Failed to synthesize speech) "); 756 | 757 | create_player(call_id, tts_answer_file); 758 | } 759 | 760 | log_message("Done.\n"); 761 | } 762 | else 763 | { 764 | log_message("No active DTMF command found for received digit.\n"); 765 | } 766 | 767 | d_cfg->processing_active = 0; 768 | } 769 | else 770 | { 771 | log_message("DTMF command dropped - state is actual processing.\n"); 772 | } 773 | } 774 | 775 | // handler for "break-in-key"-events (e.g. ctrl+c) 776 | static void signal_handler(int signal) 777 | { 778 | // exit app 779 | app_exit(); 780 | } 781 | 782 | // clean application exit 783 | static void app_exit() 784 | { 785 | if (!app_exiting) 786 | { 787 | app_exiting = 1; 788 | log_message("Stopping application ... "); 789 | 790 | // check if player/recorder is active and stop them 791 | if (play_id != -1) pjsua_player_destroy(play_id); 792 | if (rec_id != -1) pjsua_recorder_destroy(rec_id); 793 | 794 | // hangup open calls and stop pjsua 795 | pjsua_call_hangup_all(); 796 | pjsua_destroy(); 797 | 798 | log_message("Done.\n"); 799 | 800 | exit(0); 801 | } 802 | } 803 | 804 | // display error and exit application 805 | static void error_exit(const char *title, pj_status_t status) 806 | { 807 | if (!app_exiting) 808 | { 809 | app_exiting = 1; 810 | 811 | pjsua_perror("SIP Call", title, status); 812 | 813 | // check if player/recorder is active and stop them 814 | if (play_id != -1) pjsua_player_destroy(play_id); 815 | if (rec_id != -1) pjsua_recorder_destroy(rec_id); 816 | 817 | // hangup open calls and stop pjsua 818 | pjsua_call_hangup_all(); 819 | pjsua_destroy(); 820 | 821 | exit(1); 822 | } 823 | } --------------------------------------------------------------------------------