Wednesday, September 13, 2017

DTLS Reverse Proxy

Lightweight DTLS reverse proxy server based on tinydtls and libev.

https://github.com/julznc/dtlsproxy

Saturday, May 6, 2017

ATtiny IR Remote

ATtiny2313 Infrared Sender

parts:
  • ATtiny2313 @4MHz (internal oscillator)
  • IR LED (series with 220-ohm resistor)
  • Tact switches
  • 3.7V lithium ion battery & Capacitor




avr-gcc (main.c) code:
/*
* http://projectproto.blogspot.com/2017/05/attiny-ir-remote.html
*/
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
// led (OC0B) pin
#define IRLED_ENABLE() DDRD |= _BV(DDD5); PORTD &= ~_BV(PD5);
#define IRLED_DISABLE() DDRD &= ~_BV(DDD5);
// push buttons
#define POWER_BTN _BV(PB3)
#define FUNCTION_BTN _BV(PB2)
#define VOLUP_BTN _BV(PB4)
#define VOLDOWN_BTN _BV(PB5)
#define TUNEUP_BTN _BV(PB7)
#define TUNEDOWN_BTN _BV(PB6)
#define ALL_BTN (POWER_BTN|FUNCTION_BTN|VOLUP_BTN|VOLDOWN_BTN|TUNEUP_BTN|TUNEDOWN_BTN)
#define TIMER_ENABLE_PWM() (TCCR0A |= _BV(COM0B1))
#define TIMER_DISABLE_PWM() (TCCR0A &= ~(_BV(COM0B1)))
#define TIMER_CONFIG_KHZ(val) ({ \
const uint8_t pwmval = F_CPU / 2000 / (val); \
TCCR0A = _BV(WGM00); \
TCCR0B = _BV(WGM02) | _BV(CS00); \
OCR0A = pwmval; \
OCR0B = pwmval / 3; \
})
#define MARK(us) TIMER_ENABLE_PWM(); _delay_us(us)
#define SPACE(us) TIMER_DISABLE_PWM(); _delay_us(us)
#define SONY_HDR_MARK 2400
#define SONY_HDR_SPACE 600
#define SONY_ONE_MARK 1200
#define SONY_ZERO_MARK 600
//http://elektrolab.wz.cz/katalog/samsung_protocol.pdf
#define SAMSUNG_HDR_MARK 4500
#define SAMSUNG_HDR_SPACE 4500
#define SAMSUNG_BIT_MARK 560
#define SAMSUNG_ONE_SPACE 1690
#define SAMSUNG_ZERO_SPACE 560
void enableIROut (int khz)
{
IRLED_ENABLE();
TIMER_CONFIG_KHZ(khz);
}
uint32_t reverseBits(uint32_t input, uint8_t nbits) {
uint32_t output = input;
for (uint8_t i = 1; i < nbits; i++) {
output <<= 1;
input >>= 1;
output |= (input & 1);
}
return output;
}
uint32_t encodeSony (uint8_t nbits, uint8_t command,
uint8_t address, uint8_t extended)
{
uint32_t result = 0;
switch (nbits) {
case 12: // 5 address bits.
result = address & 0x1F;
break;
case 15: // 8 address bits.
result = address & 0xFF;
break;
case 20: // 5 address bits, 8 extended bits.
result = address & 0x1F;
result |= (extended & 0xFF) << 5;
break;
default:
return 0;
}
result = (result << 7) | (command & 0x7F);
return reverseBits(result, nbits);
}
void sendSony (uint32_t data, int nbits)
{
// Set IR carrier frequency
enableIROut(40);
// Header
MARK(SONY_HDR_MARK);
SPACE(SONY_HDR_SPACE);
// Data
for (uint32_t mask = 1UL << (nbits - 1); mask; mask >>= 1) {
if (data & mask) {
MARK(SONY_ONE_MARK);
SPACE(SONY_HDR_SPACE);
} else {
MARK(SONY_ZERO_MARK);
SPACE(SONY_HDR_SPACE);
}
}
}
void sendSamsung (uint32_t data, int nbits)
{
// Set IR carrier frequency
enableIROut(38);
// Header
MARK(SAMSUNG_HDR_MARK);
SPACE(SAMSUNG_HDR_SPACE);
// Data
for (uint32_t mask = 1UL << (nbits - 1); mask; mask >>= 1) {
if (data & mask) {
MARK(SAMSUNG_BIT_MARK);
SPACE(SAMSUNG_ONE_SPACE);
} else {
MARK(SAMSUNG_BIT_MARK);
SPACE(SAMSUNG_ZERO_SPACE);
}
}
// Footer
MARK(SAMSUNG_BIT_MARK);
SPACE(0); // Always end with the LED off
}
void enterSleep(void)
{
IRLED_DISABLE();
// Enable Pin Change Interrupts on all buttons
GIMSK |= _BV(PCIE);
PCMSK |= ALL_BTN;
sleep_enable();
sei(); // Enable interrupts
sleep_cpu();
}
ISR(PCINT_vect) {
cli(); // Disable interrupts
PCMSK &= ~ALL_BTN; // clear interrupt flags
sleep_disable();
_delay_ms(1);
switch ( (~PINB) & ALL_BTN )
{
#if 1 // sony dvd
case POWER_BTN:
sendSony(encodeSony(15, 21, 80, 0), 15); // on/off
break;
case FUNCTION_BTN:
sendSony(encodeSony(15, 105, 208, 0), 15); // source
break;
case VOLUP_BTN:
sendSony(encodeSony(15, 18, 80, 0), 15); // volume +
break;
case VOLDOWN_BTN:
sendSony(encodeSony(15, 19, 80, 0), 15); // volume -
break;
case TUNEUP_BTN:
sendSony(encodeSony(20, 52, 16, 16), 20); // tune +
break;
case TUNEDOWN_BTN:
sendSony(encodeSony(20, 51, 16, 16), 20); // tune -
break;
#else // samsung tv
// https://github.com/lepiaf/IR-Remote-Code
case POWER_BTN:
sendSamsung(0xE0E040BF, 32); // on/off
break;
case FUNCTION_BTN:
sendSamsung(0xE0E0807F, 32); // source
break;
case VOLUP_BTN:
sendSamsung(0xE0E0E01F, 32); // volume +
break;
case VOLDOWN_BTN:
sendSamsung(0xE0E0D02F, 32); // volume -
break;
case TUNEUP_BTN:
sendSamsung(0xE0E048B7, 32); // channel +
break;
case TUNEDOWN_BTN:
sendSamsung(0xE0E008F7, 32); // channel -
break;
#endif
}
}
int main(void)
{
// analog comparator off
ACSR &= ~_BV(ACD);
DIDR |= _BV(AIN1D) | _BV(AIN0D);
// initially all input pins with pull-up's
DDRA = DDRB = DDRD = 0;
PORTA = PORTB = PORTD = 0xFF;
IRLED_ENABLE();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
while(1) {
enterSleep();
}
}


References:
ESP8266 IR Remote
z3t0/Arduino-IRremote
ATtiny Low Power

Friday, May 5, 2017

ESP8266 IR Remote

Control your appliances (e.g. TV and AV systems) via WiFi+IR.




Arduino code:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <IRremoteESP8266.h>
IRsend irsend( 14 /*GPIO pin*/);
ESP8266WebServer server(80);
const char* ssid = "........";
const char* password = "........";
// soft access point (as backup)
static const char *softAPssid = "ir-remote";
static const char *softAPpassword = "12345678";
static const char *indexhtml = "<html>\n"
"<head>\n"
"<title>IR remote</title>\n"
"<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
"</head>\n"
"<style media=\"screen\" type=\"text/css\">\n"
"table{width:100%;}\n"
"button{display: block; width:96%; padding:12px; margin: 4px; font-weight:bold; font-size:1.5em;}\n"
"</style>\n"
"<body>\n"
"<script type=\"text/javascript\">\n"
"function req(cmd)\n"
"{ var xmlHttp = new XMLHttpRequest();\n"
"console.log(cmd);\n"
"xmlHttp.onreadystatechange = function(){}\n"
"xmlHttp.open(\"GET\", cmd, true);xmlHttp.send(null); }\n"
"var intervals = {};\n"
"function pressed(cmd){ req(cmd); intervals[cmd] = setInterval(function() { req(cmd); }, 250); }\n"
"function unpressed(){for (var cmd in intervals){ clearInterval(intervals[cmd]); } }\n"
"</script>\n"
"<h2>Sony AV System Remote</h2>\n"
"<table>\n"
"<tr><td><button onmousedown=\"req('power')\">POWER</button></td>\n"
"<td><button onmousedown=\"req('func')\">FUNC</button></td></tr>\n"
"<tr><td><button onmousedown=\"pressed('volup')\" ontouchstart=\"pressed('volup')\" onmouseup=\"unpressed()\" ontouchend=\"unpressed()\">VOL+</button></td>\n"
"<td><button onmousedown=\"pressed('tuneup')\" ontouchstart=\"pressed('tuneup')\" onmouseup=\"unpressed()\" ontouchend=\"unpressed()\">TUNE+</button></td></tr>\n"
"<tr><td><button onmousedown=\"pressed('voldown')\" ontouchstart=\"pressed('voldown')\" onmouseup=\"unpressed()\" ontouchend=\"unpressed()\">VOL-</button></td>\n"
"<td><button onmousedown=\"pressed('tunedown')\" ontouchstart=\"pressed('tunedown')\" onmouseup=\"unpressed()\" ontouchend=\"unpressed()\">TUNE-</button></td></tr>\n"
"</table>\n"
"</body>\n"
"</html>\n";
void handleRoot() {
server.send(200, "text/html", indexhtml);
}
void handlePower() {
Serial.println("power");
irsend.sendSony(irsend.encodeSony(15, 21, 80), 15, 2);
server.send(200, "text/plain", "power");
}
void handleFunc() {
Serial.println("func");
irsend.sendSony(irsend.encodeSony(15, 105, 208), 15, 2);
server.send(200, "text/plain", "func");
}
void handleVolup() {
Serial.println("volup");
irsend.sendSony(irsend.encodeSony(15, 18, 80), 15, 2);
server.send(200, "text/plain", "volup");
}
void handleVoldown() {
Serial.println("voldown");
irsend.sendSony(irsend.encodeSony(15, 19, 80), 15, 2);
server.send(200, "text/plain", "voldown");
}
void handleTuneup() {
Serial.println("tuneup");
irsend.sendSony(irsend.encodeSony(20, 52, 16, 16), 20, 2);
server.send(200, "text/plain", "tuneup");
}
void handleTunedown() {
Serial.println("tunedown");
irsend.sendSony(irsend.encodeSony(20, 51, 16, 16), 20, 2);
server.send(200, "text/plain", "down");
}
void handleNotFound(){
server.send(404, "text/plain", "Not Found");
}
void setup()
{
Serial.begin(115200);
WiFi.begin(ssid, password);
WiFi.softAP(softAPssid, softAPpassword);
irsend.begin();
// Wait for connection
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("Soft AP: ");
Serial.println(softAPssid);
Serial.print("IP address: ");
Serial.println(WiFi.softAPIP());
if (MDNS.begin("irremote")) {
Serial.println("MDNS responder started");
}
server.on("/", handleRoot);
server.on("/power", handlePower);
server.on("/func", handleFunc);
server.on("/volup", handleVolup);
server.on("/voldown", handleVoldown);
server.on("/tuneup", handleTuneup);
server.on("/tunedown", handleTunedown);
server.onNotFound(handleNotFound);
server.begin();
Serial.println("HTTP server started");
}
void loop(void){
server.handleClient();
}
view raw IRremote.ino hosted with ❤ by GitHub


References:
markszabo/IRremoteESP8266
Sony IR codes
Sony SIRC protocol





Sunday, January 29, 2017

WiFi RGB Matrix

Here's a DIY flexible 36x8 RGB-LED-matrix controlled via WiFi connection using an ESP8266 module.



Arduino Code: julznc/wifi_rgb_matrix


Assembly:

References:
NeoPixelBus - for interfacing WS2812 LEDs to ESP8266 controller
Adafruit-GFX-Library - with font library for displaying texts
LED Matrix Studio - for creating bitmap images