Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quick and dirty tool to decode GC codes #308

Merged
merged 9 commits into from
Oct 2, 2017
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 104 additions & 0 deletions tool/IRsend_test.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2017 David Conran

#ifndef TEST_IRSEND_TEST_H_
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you reference the canonical file instead of making essentially a copy of it here? It would be better if you just included the "real" IRsend_test.h file instead of making a copy which we need to keep in sync etc.

#define TEST_IRSEND_TEST_H_

#define __STDC_LIMIT_MACROS
#include <stdint.h>
#include <iostream>
#include <sstream>
#include <string>
#include "IRrecv.h"
#include "IRsend.h"

#define OUTPUT_BUF 1000U
#define RAW_BUF 1000U
class IRsendTest: public IRsend {
public:
uint32_t output[OUTPUT_BUF];
uint16_t last;
uint16_t rawbuf[RAW_BUF];
decode_results capture;

explicit IRsendTest(uint16_t x, bool i = false) : IRsend(x, i) {
reset();
}

void reset() {
last = 0;
output[last] = 0;
}

std::string outputStr() {
std::stringstream result;
if (last == 0 && output[0] == 0)
return "";
for (uint16_t i = 0; i <= last; i++) {
if ((i & 1) != outputOff ) // Odd XOR outputOff
result << "s";
else
result << "m";
result << output[i];
}
reset();
return result.str();
}

void makeDecodeResult(uint16_t offset = 0) {
capture.decode_type = UNKNOWN;
capture.bits = 0;
capture.rawlen = last + 1 - offset;
capture.overflow = (last - offset >= (int16_t) RAW_BUF);
capture.repeat = false;
capture.address = 0;
capture.command = 0;
capture.value = 0;
capture.rawbuf = rawbuf;
for (uint16_t i = 0;
(i < RAW_BUF - 1) && (offset < OUTPUT_BUF);
i++, offset++)
if (output[offset] / RAWTICK > UINT16_MAX)
rawbuf[i + 1] = UINT16_MAX;
else
rawbuf[i + 1] = output[offset] / RAWTICK;
}

void dumpRawResult() {
std::cout << "uint16_t rawbuf["<< capture.rawlen << "] =\n";
for (uint16_t i = 0; i < capture.rawlen; i++) {
std::cout << (capture.rawbuf[i] * RAWTICK);
std::cout << "(";
std::cout << capture.rawbuf[i];
std::cout << "), ";
if (i % 8 == 7)
std::cout << "\n";
}
std::cout << "\n";
}

void addGap(uint32_t usecs) {
space(usecs);
}

protected:
uint16_t mark(uint16_t usec) {
if (last >= OUTPUT_BUF)
return 0;
if (last & 1) // Is odd? (i.e. last call was a space())
output[++last] = usec;
else
output[last] += usec;
return 0;
}

void space(uint32_t time) {
if (last >= OUTPUT_BUF)
return;
if (last & 1) { // Is odd? (i.e. last call was a space())
output[last] += time;
} else {
output[++last] = time;
}
}
};
#endif // TEST_IRSEND_TEST_H_
130 changes: 130 additions & 0 deletions tool/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
# SYNOPSIS:
#
# make [all] - makes everything.
# make TARGET - makes the given target.
# make clean - removes all files generated by make.

# Please tweak the following variable definitions as needed by your
# project, except GTEST_HEADERS, which you can use in your own targets
# but shouldn't modify.


# Where to find user code.
USER_DIR = ../src

# Flags passed to the preprocessor.
# Set Google Test's header directory as a system directory, such that
# the compiler doesn't generate warnings in Google Test headers.
CPPFLAGS += -DUNIT_TEST

# Flags passed to the C++ compiler.
CXXFLAGS += -g -Wall -Wextra -pthread

all : gc_decode

clean :
rm -f *.o gc_decode


# All the IR protocol object files.
PROTOCOLS = ir_NEC.o ir_Sony.o ir_Samsung.o ir_JVC.o ir_RCMM.o ir_RC5_RC6.o \
ir_LG.o ir_Mitsubishi.o ir_Fujitsu.o ir_Sharp.o ir_Sanyo.o ir_Denon.o ir_Dish.o \
ir_Panasonic.o ir_Whynter.o ir_Coolix.o ir_Aiwa.o ir_Sherwood.o \
ir_Kelvinator.o ir_Daikin.o ir_Gree.o ir_Pronto.o ir_GlobalCache.o
# Common object files
COMMON_OBJ = IRutils.o IRtimer.o IRsend.o IRrecv.o $(PROTOCOLS)

# Common dependencies
COMMON_DEPS = $(USER_DIR)/IRrecv.h $(USER_DIR)/IRsend.h $(USER_DIR)/IRtimer.h \
$(USER_DIR)/IRutils.h $(USER_DIR)/IRremoteESP8266.h
# Common test dependencies
COMMON_TEST_DEPS = $(COMMON_DEPS) IRsend_test.h
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per the other comment, perhaps ../test/IRsend_test.h instead? or what ever makes it use the original file.


gc_decode.o : gc_decode.cpp $(COMMON_TEST_DEPS) $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -I$(USER_DIR) -c gc_decode.cpp

gc_decode : $(COMMON_OBJ) gc_decode.o
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -lpthread $^ -o $@


IRutils.o : $(USER_DIR)/IRutils.cpp $(USER_DIR)/IRutils.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRutils.cpp

IRtimer.o : $(USER_DIR)/IRtimer.cpp $(USER_DIR)/IRtimer.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRtimer.cpp

IRsend.o : $(USER_DIR)/IRsend.cpp $(USER_DIR)/IRsend.h $(USER_DIR)/IRremoteESP8266.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRsend.cpp

IRrecv.o : $(USER_DIR)/IRrecv.cpp $(USER_DIR)/IRrecv.h $(USER_DIR)/IRremoteESP8266.h $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/IRrecv.cpp


ir_NEC.o : $(USER_DIR)/ir_NEC.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_NEC.cpp

ir_GlobalCache.o : $(USER_DIR)/ir_GlobalCache.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_GlobalCache.cpp

ir_Sherwood.o : $(USER_DIR)/ir_Sherwood.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sherwood.cpp

ir_Sony.o : $(USER_DIR)/ir_Sony.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sony.cpp

ir_Samsung.o : $(USER_DIR)/ir_Samsung.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Samsung.cpp

ir_Kelvinator.o : $(USER_DIR)/ir_Kelvinator.cpp $(USER_DIR)/ir_Kelvinator.h $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Kelvinator.cpp

ir_JVC.o : $(USER_DIR)/ir_JVC.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_JVC.cpp

ir_RCMM.o : $(USER_DIR)/ir_RCMM.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RCMM.cpp

ir_LG.o : $(USER_DIR)/ir_LG.h $(USER_DIR)/ir_LG.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_LG.cpp

ir_Mitsubishi.o : $(USER_DIR)/ir_Mitsubishi.h $(USER_DIR)/ir_Mitsubishi.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Mitsubishi.cpp

ir_Fujitsu.o : $(USER_DIR)/ir_Fujitsu.h $(USER_DIR)/ir_Fujitsu.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Fujitsu.cpp

ir_Sharp.o : $(USER_DIR)/ir_Sharp.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sharp.cpp

ir_RC5_RC6.o : $(USER_DIR)/ir_RC5_RC6.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_RC5_RC6.cpp

ir_Panasonic.o : $(USER_DIR)/ir_Panasonic.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Panasonic.cpp

ir_Dish.o : $(USER_DIR)/ir_Dish.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Dish.cpp

ir_Whynter.o : $(USER_DIR)/ir_Whynter.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Whynter.cpp

ir_Coolix.o : $(USER_DIR)/ir_Coolix.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Coolix.cpp

ir_Aiwa.o : $(USER_DIR)/ir_Aiwa.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Aiwa.cpp

ir_Denon.o : $(USER_DIR)/ir_Denon.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Denon.cpp

ir_Sanyo.o : $(USER_DIR)/ir_Sanyo.cpp $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Sanyo.cpp

ir_Daikin.o : $(USER_DIR)/ir_Daikin.cpp $(USER_DIR)/ir_Daikin.h $(COMMON_DEPS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Daikin.cpp

ir_Gree.o : $(USER_DIR)/ir_Gree.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Gree.cpp

ir_Pronto.o : $(USER_DIR)/ir_Pronto.cpp $(GTEST_HEADERS)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $(USER_DIR)/ir_Pronto.cpp
62 changes: 62 additions & 0 deletions tool/gc_decode.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "IRsend.h"
#include "IRsend_test.h"
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per other comments. Lets use the original file.

Also, the ordering of the headers I think needs to be different per styleguide.
https://google.github.io/styleguide/cppguide.html#Names_and_Order_of_Includes

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <inttypes.h> /* strtoumax */
#include <stdbool.h>


using namespace std;


void str_to_uint16(char *str, uint16_t *res)
{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<style> Move the '{' to the end of the previous line.

char *end;
errno = 0;
intmax_t val = strtoimax(str, &end, 10);
if (errno == ERANGE || val < 0 || val > UINT16_MAX || end == str || *end != '\0')
return;
*res = (uint16_t) val;
}


int main (int argc, char * argv[]) {

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


if (argc != 2) {
cout << "Use gc_decode [global_code]" << endl;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indenting misaligned. pls fix.

return 0;
}

uint16_t gc_test[250];
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick/suggestion: Probably best to put the 250 value into a #define etc, and make it larger. e.g. 512 or something. Some GC codes can be very long.

int index = 0;

char * pch;
pch = strtok (argv[1],",");
while (pch != NULL)
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need a bounds check on the size of gc_test so you don't go writing data outside the array.
e.g.
while (pch != NULL && index < 250) {

{
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bracer to the end of the previous line. (style guide thing)

str_to_uint16(pch, &gc_test[index]);
pch = strtok (NULL, " ,");
index++;
}

IRsendTest irsend(4);
IRrecv irrecv(4);
irsend.begin();
irsend.reset();

irsend.sendGC(gc_test, index);
irsend.makeDecodeResult();
irrecv.decode(&irsend.capture);

cout << "Code GC length " << index << endl;
cout << "Code type " << irsend.capture.decode_type << endl;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably also print out the common name for the type. e.g. See the switch statement in the dumpV2 example code.

cout << "Code bits " << irsend.capture.bits << endl;
cout << "Code value " << std::hex << irsend.capture.value << endl;
cout << "Code address " << std::hex << irsend.capture.address << endl;
cout << "Code command " << std::hex << irsend.capture.command << endl;

return 0;
}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please run the Google cpplint.py over this code? https://github.com/cpplint/cpplint
Also, can you please add it to the travis.yaml file so a) it gets a "does it compile" check, and b) update the cpplint.py call/args in the travis.yaml file to also cover code in this directory, so it gets linted etc. ;-)