Skip to content

Instantly share code, notes, and snippets.

@notpike
Last active September 30, 2019 03:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save notpike/177dddae91b2237dfc75ba810d04a641 to your computer and use it in GitHub Desktop.
Save notpike/177dddae91b2237dfc75ba810d04a641 to your computer and use it in GitHub Desktop.
NEC Encoder in C
// By: NotPike
// NEC Encoding
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
// Varibals
#define LEN 16 //Bytes
// Commands
const uint8_t commands[32] = {
0x32, // Pause
0x78, // On/Off
0x70, // P1
0x60, // P2
0xCA, // P3 SKIP
0x20, // F1
0xF2, // Up
0xA0, // F2
0x84, // Left
0x44, // OK
0xC4, // Right
0x30, // F3
0x80, // Down
0xB0, // F4
0xF0, // 1
0x08, // 2
0x88, // 3
0x48, // 4
0xC8, // 5
0x28, // 6
0xA8, // 7
0x68, // 8
0xE8, // 9
0x18, // Music_Karaoke
0x98, // 0
0x58, // Lock_Queue
0xD0, // Zone 1 Vol+
0x90, // Zone 2 Vol+
0xC0, // Zone 3 Vol+
0x50, // Zone 1 Vol-
0x10, // Zone 2 Vol-
0x40, // Zone 3 Vol-
};
// Function Refered From Furrtek's Havoc Port
// https://github.com/furrtek/portapack-havoc/blob/master/firmware/application/apps/ui_touchtunes.cpp#L75
void encode(char *out, uint8_t command, int pin) {
// Variables
size_t bit; // Bit counter
uint64_t decodeMsg = 0x5D; // Sync Word + decoded value
uint8_t encodeMsg; // Bit holder before encoded values are moved to *out
// Preamble 0xFFFF00
out[0] = 0xFF;
out[1] = 0xFF;
out[2] = 0x00;
// PIN, LSB First
for (bit = 0; bit < 8; bit++) {
decodeMsg <<= 1; // Shift left 1 bit
if(pin & (1 << bit)) { // If both bits line up add 1
decodeMsg |= 1;
}
}
// Command and it's complement
decodeMsg <<= 16; // Shift left 16 bits
decodeMsg |= (command << 8); // Add command shift left 8 bits
decodeMsg |= (command ^ 0xff); // Add command's complement
// NEC Encode
size_t bitSize = 0; // Size counter for encodeMsg
int arrayPos = 3; // Pointer counter for *out
for(bit = 0; bit < (8 + 8 + 16); bit++) { // Sync + Pin + Command == 32bit
if(decodeMsg & 0x80000000UL) { // If 1
if(bitSize <= 4) {
encodeMsg <<= 4;
encodeMsg |= 0x8; // 1000
decodeMsg <<= 1;
bitSize += 4;
} else if(bitSize == 6) { // Split the Byte
encodeMsg <<= 2;
encodeMsg |= 0x2;
out[arrayPos] = encodeMsg; // Add Byte to char array
arrayPos++;
encodeMsg <<= 8; // Wipe the stack
decodeMsg <<= 1;
bitSize = 2;
} else if(bitSize == 8) {
out[arrayPos] = encodeMsg; // Add Byte to char array
arrayPos++;
encodeMsg <<= 8; // Wipe the stack
encodeMsg |= 0x8; // 1000
decodeMsg <<= 1;
bitSize = 4;
}
} else { // Else 0
if(bitSize <=6) {
encodeMsg <<= 2;
encodeMsg |= 0x2; // 10
decodeMsg <<= 1;
bitSize += 2;
} else if(bitSize == 8) {
out[arrayPos] = encodeMsg; // Add Byte to char array
arrayPos++;
encodeMsg <<= 8; // Wipe the stack
encodeMsg |= 0x2; // 10
decodeMsg <<= 1;
bitSize = 2;
}
}
}
// Add Tail
if(bitSize == 2) {
encodeMsg <<= 4;
encodeMsg |= 0x8; // 1000
encodeMsg <<= 2;
} else if(bitSize == 4) {
encodeMsg <<= 4;
encodeMsg |= 0x8; // 1000
} else if(bitSize == 6) { // Split the Byte
encodeMsg <<= 2;
encodeMsg |= 0x2; // 10
out[arrayPos] = encodeMsg; // Add Byte to char array
arrayPos++;
encodeMsg <<= 8; // Wipe the stack
} else if(bitSize == 8) {
out[arrayPos] = encodeMsg; // Add Byte to char array
arrayPos++;
encodeMsg <<= 8; // Wipe the stack
}
// Pad with 0x00 if msg length is not 16 Bytes
if(arrayPos == 14) {
out[14] = encodeMsg;
out[15] = 0x00;
out[16] = '\0';
} else {
out[15] = 0x00;
out[16] = '\0';
}
}
// Known values for PIN 000
static const char * const button_array[] = {
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa2\x2a\x28\xaa\x22\x8a\x20\x00",// Skip
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xaa\x22\xa2\x88\xa8\x8a\x20\x00",// Pause
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa2\xaa\xaa\x22\x22\x22\x20\x00",// Down Arrow
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa8\xa2\x2a\x8a\x2a\x22\x20\x00",// Lock Queue
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa2\xaa\x2a\x88\x88\xa2\x20\x00",// Left Arrow
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa8\xaa\x2a\x28\x88\xa2\x20\x00",// OK
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa2\x2a\x8a\xa8\x88\xa2\x20\x00",// Right Arrow
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa8\x88\x8a\xa2\xaa\x22\x20\x00",// Power
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa2\x22\x2a\x2a\xa8\x8a\x20\x00",// Up Arrow
"\xff\xff\x00\xa2\x88\x8a\x2a\xaa\xa8\x8a\xaa\x2a\x22\x22\x20\x00" // Edit Queue
};
void main() {
// Variables
static char *list[32];
unsigned char returnValue[17];
uint8_t msg[16] = {0xFF, 0xFF, 0x00, 0xa2, 0x88, 0x8a, 0x2a, 0xaa, // Skip
0xa2, 0x2a, 0x28, 0xaa, 0x22, 0x8a, 0x20, 0x00};
uint8_t msg2[16] = {0xFF, 0xFF, 0x00, 0xa2, 0x88, 0x8a, 0x2a, 0xaa, // Edit Queue
0xa8, 0x8a, 0xaa, 0x2a, 0x22, 0x22, 0x20, 0x00};
// TEST 1
printf("===Test 1 Skip for PIN 000===\n");
encode(returnValue, commands[4], 0);
// Step each char and cmp to msg
int ji;
for(ji =0; ji < 16; ji++) {
if(msg[ji] == returnValue[ji]) {
printf("char %i pass\n",ji);
} else {
printf("char %i fail\n",ji);
}
}
// TEST 2
printf("\n===Test 2 Edit Que for PIN 000===\n");
encode(returnValue, commands[3], 0);
// Step each char and cmp to msg2
for(ji =0; ji < 16; ji++) {
if(msg2[ji] == returnValue[ji]) {
printf("char %i pass\n",ji);
} else {
printf("char %i fail\n",ji);
}
}
// TEST 3
// Encode all 32 Commands and 256 PINs
printf("\n==Test 3 Encode All 32 Commands and 256 PINs==\n");
int xx;
for(xx=0; xx < 255; xx++) {
int j;
for(j = 0; j < 32; j +=1) {
encode(returnValue, commands[j], xx);
//printf("Command:%i PIN:%i pass\n", j,xx);
}
}
printf("Complete\n");
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment