/*
 * Tool for generating Pronto codes for the Conrad 433 MHz RF system.
 *
 * Copyright (C) 2006 Bengt Martensson <barf@bengt-martensson.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

#define bit unsigned char

const char freq[] = "0000 0074";
const int repetitions = 1;
const int ent_per_line = 6;
char length[100];
char pcm_codes[2][10] = { "0032 0078", "0015 0078"};
char leadout_codes[2][10] = { "0032 0500", "0015 0500"};

bit bytecode[26];

void
do_bytecode(int address[4], int switchno, char function)
{
#define emit(c) bytecode[i++] = c; par = (par + c) % 2

  int i = 0;
  int par = 0;
  emit(0);			// Wakeup
  emit(1);

  emit(1);			// Device code
  emit(0);
  emit(0);
  emit(1);

  for (int j = 3; j >= 0; j--)
    switch (address[j]) {
    case 1:
      emit(0); emit(0);
      break;
    case 2:
      emit(0); emit(1);
      break;
    case 3:
      emit(1); emit(0);
      break;
    case 4:
      emit(1); emit(1);
      break;
    default:
      std::cerr << "Silly address\n";
      exit(2);
    }
  emit(7);			// Dummy
  par = 0;
  switch (switchno) {
    case 1:
      emit(0); emit(0); emit(0);
      break;
    case 2:
      emit(0); emit(0); emit(1);
      break;
    case 3:
      emit(0); emit(1); emit(0);
      break;
    case 4:
      emit(0); emit(1); emit(1);
      break;
    case 5:
      emit(1); emit(0); emit(0);
      break;
    case 6:
      emit(1); emit(0); emit(1);
      break;
    case 7:
      emit(1); emit(1); emit(0);
      break;
    case 8:
      emit(1); emit(1); emit(1);
      break;
    default:
      std::cerr << "Silly switchno\n";
      exit(2);
  }
  switch (function) {
    case '+':
      emit(0); emit(0); emit(0); emit(0);
      break;
    case '-':
      emit(0); emit(1); emit(0); emit(0);
      break;
    case 't':
      emit(1); emit(0); emit(0); emit(0);
      break;
    default:
      std::cerr << "Silly function\n";
      exit(2);
  }
  par = !par;
  bytecode[i-8] = par;

  int sum = 0;
  for (int j = 0; j < 5; j++) {
    sum +=
      8*bytecode[4*j + 0 + 2] +
      4*bytecode[4*j + 1 + 2] +
      2*bytecode[4*j + 2 + 2] +
      1*bytecode[4*j + 3 + 2];
  }
  sum %= 16;
  emit(sum/8); sum %= 8;
  emit(sum/4); sum %= 4;
  emit(sum/2); sum %= 2;
  emit(sum);
}

void
usage(std::string arg0)
{
  std::cerr << "Usage: " << arg0 << " code switchno function\n";
}

int
main(int argc, char *argv[])
{
  if (argc != 4) {
    usage(argv[0]);
    exit(1);
  }
  int address[4];
  int adr = atoi(argv[1]);
  int switchno = atoi(argv[2]);
  char function = argv[3][0];
  address[0] = adr/1000;
  address[1] = (adr % 1000)/100;
  address[2] = (adr % 100)/10;
  address[3] = adr % 10;
  do_bytecode(address, switchno, function);
#if 0
  for (int j = 2; j < 26; j++)
    cout << int(bytecode[j]) << (j % 4 == 1 ? "\n" : "");
#endif
  sprintf(length, "%.4x %.4x\n", 0, repetitions*26);
  std::cout << freq << " " << length;
   int pos = 0;
   for (int j = 0; j < repetitions; j++) {
     for (int k = 0; k < 25; k ++) {
       pos++;
       pos %= ent_per_line;
       std::cout << pcm_codes[bytecode[k]] << (pos == 0 ? "\n" : " ");
     }
     std::cout << leadout_codes[bytecode[25]] << "\n";
     pos = 0;
   }
}

