Created
August 5, 2023 08:52
-
-
Save gabonator/7f4f7247f6c47fd8c7ccdfed3b432ccb to your computer and use it in GitHub Desktop.
hcs200 decoder test for la104/rftool
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include "Types.h" | |
class CPoint { | |
public: | |
int x, y; // TODO: !!! | |
CPoint() | |
{ | |
} | |
CPoint(int _x, int _y) : | |
x(_x), y(_y) | |
{ | |
} | |
CPoint operator +(const CPoint& cp) | |
{ | |
return CPoint( x + cp.x, y + cp.y ); | |
} | |
bool operator !=(const CPoint& cp) | |
{ | |
return cp.x != x || cp.y != y; | |
} | |
}; | |
class CRect { | |
public: | |
CRect() : | |
left(0), top(0), right(0), bottom(0) | |
{ | |
} | |
CRect( int _left, int _top, int _right, int _bottom ) : | |
left(_left), top(_top), right(_right), bottom(_bottom) | |
{ | |
} | |
int CenterX() | |
{ | |
return (left+right)>>1; | |
} | |
CPoint Center() | |
{ | |
return CPoint( (left+right) >> 1, (top+bottom) >> 1 ); | |
} | |
void Deflate(int l, int t, int r, int b) | |
{ | |
left += l; | |
top += t; | |
right -= r; | |
bottom -= b; | |
} | |
void Inflate(int l, int t, int r, int b) | |
{ | |
left -= l; | |
top -= t; | |
right += r; | |
bottom += b; | |
} | |
int Width() const | |
{ | |
return right - left; | |
} | |
int Height() const | |
{ | |
return bottom - top; | |
} | |
const CPoint& TopLeft() const | |
{ | |
return *((CPoint*)this); | |
} | |
void Offset(int x, int y) | |
{ | |
left += x; | |
right += x; | |
top += y; | |
bottom += y; | |
} | |
void Invalidate() | |
{ | |
left = 0; | |
top = 0; | |
right = 0; | |
bottom = 0; | |
} | |
bool IsValid() const | |
{ | |
return right > left; | |
} | |
void operator |= (const CRect& rcUnion) | |
{ | |
if ( !IsValid() ) | |
{ | |
*this = rcUnion; | |
return; | |
} | |
left = min(left, rcUnion.left); | |
top = min(top, rcUnion.top); | |
right = max(right, rcUnion.right); | |
bottom = max(bottom, rcUnion.bottom); | |
} | |
CRect operator +(const CPoint& cp) | |
{ | |
CRect rcNew( *this ); | |
rcNew.left += cp.x; | |
rcNew.right += cp.x; | |
rcNew.top += cp.y; | |
rcNew.bottom += cp.y; | |
return rcNew; | |
} | |
bool IsInside( int x, int y ) | |
{ | |
if ( x < left || x >= right || y < top || y >= bottom ) | |
return false; | |
return true; | |
} | |
bool operator == (const CRect& rcTest) | |
{ | |
return left == rcTest.left && | |
right == rcTest.right && | |
top == rcTest.top && | |
bottom == rcTest.bottom; | |
} | |
int left, top, right, bottom; | |
}; | |
template <class TYPE> | |
class CArray | |
{ | |
TYPE *m_arrElements; | |
ui16 m_nCount; | |
ui16 m_nMaxCount; | |
typedef int (*TCompareFunction)(TYPE&, TYPE&); | |
public: | |
CArray() | |
{ | |
} | |
CArray( TYPE *pSource, int nLength, int nCount = 0 ) | |
{ | |
m_arrElements = pSource; | |
m_nCount = nCount; | |
m_nMaxCount = nLength; | |
} | |
void Init( TYPE *pSource, int nLength, int nCount = 0 ) | |
{ | |
m_arrElements = pSource; | |
m_nCount = nCount; | |
m_nMaxCount = nLength; | |
} | |
BOOL IsEmpty() | |
{ | |
_ASSERT( m_arrElements ); | |
return m_nCount == 0; | |
} | |
void Add(TYPE t) | |
{ | |
_ASSERT( m_nCount < m_nMaxCount ); | |
m_arrElements[m_nCount++] = t; | |
} | |
TYPE &GetLast() | |
{ | |
_ASSERT( m_nCount > 0 ); | |
return m_arrElements[m_nCount-1]; | |
} | |
const TYPE &GetLast() const | |
{ | |
_ASSERT( m_nCount > 0 ); | |
return m_arrElements[m_nCount-1]; | |
} | |
// returns pointer to existing element | |
TYPE& RemoveLast() | |
{ | |
_ASSERT( m_nCount > 0 ); | |
return m_arrElements[--m_nCount]; | |
} | |
void Resize( int nDif ) | |
{ | |
m_nCount += nDif; | |
_ASSERT( m_nCount >= 0 && m_nCount <= m_nMaxCount ); | |
} | |
int GetSize() const | |
{ | |
return m_nCount; | |
} | |
int GetMaxSize() | |
{ | |
return m_nMaxCount; | |
} | |
void SetSize( int nSize ) | |
{ | |
m_nCount = nSize; | |
} | |
TYPE& operator []( int i) | |
{ | |
if ( i < 0 ) | |
i += m_nCount; | |
_ASSERT( i >= 0 && i < GetSize() ); | |
return m_arrElements[i]; | |
} | |
const TYPE& operator []( int i) const | |
{ | |
if ( i < 0 ) | |
i += m_nCount; | |
_ASSERT( i >= 0 && i < GetSize() ); | |
return m_arrElements[i]; | |
} | |
void RemoveAt( int i ) | |
{ | |
_ASSERT( i < GetSize() ); | |
for ( ; i < GetSize()-1; i++ ) | |
m_arrElements[i] = m_arrElements[i+1]; | |
Resize(-1); | |
} | |
void InsertAt( int i, const TYPE& element ) | |
{ | |
int nSize = GetSize(); | |
_ASSERT( i <= nSize ); | |
Resize(+1); | |
for ( int j = nSize-1; j >= i; j-- ) | |
m_arrElements[j+1] = m_arrElements[j]; | |
m_arrElements[i] = element; | |
} | |
void RemoveAll() | |
{ | |
m_nCount = 0; | |
} | |
void Sort(TCompareFunction fCompare) | |
{ | |
for ( int i=0; i<m_nCount; i++) | |
for ( int j=i+1; j<m_nCount; j++) | |
if ( fCompare( m_arrElements[i], m_arrElements[j] ) < 0 ) | |
{ | |
TYPE tTemp = m_arrElements[i]; | |
m_arrElements[i] = m_arrElements[j]; | |
m_arrElements[j] = tTemp; | |
} | |
} | |
int Find(TYPE& value) | |
{ | |
for (int i=0; i<m_nCount; i++) | |
if (m_arrElements[i] == value) | |
return i; | |
return -1; | |
} | |
TYPE* GetData() | |
{ | |
return m_arrElements; | |
} | |
void Copy(const CArray<TYPE>& source) | |
{ | |
SetSize(source.GetSize()); | |
for (int i=0; i<source.GetSize(); i++) | |
m_arrElements[i] = source.m_arrElements[i]; | |
} | |
bool operator ==(const CArray<TYPE>& other) | |
{ | |
if (GetSize() != other.GetSize()) | |
return false; | |
for (int i=0; i<GetSize(); i++) | |
if (m_arrElements[i] != other.m_arrElements[i]) | |
return false; | |
return true; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Date: 2023-08-03 | |
// Created by: Grzegorz Rajtar, grzegorz@rajtar.info | |
/* | |
Microchip HCS200/HCS300 KeeLoq Code Hopping Encoder based remotes. | |
66 bits transmitted, LSB first. | |
| 0-31 | Encrypted Portion | |
| 32-59 | Serial Number | |
| 60-63 | Button Status (S3, S0, S1, S2) | |
| 64 | Battery Low | |
| 65 | Fixed 1 | |
*/ | |
class CHcs200 : public CProtocol | |
{ | |
public: | |
virtual int Frequency() override | |
{ | |
return 433920000; | |
} | |
virtual void Example(CAttributes& attributes) override | |
{ | |
attributes["length"] = 66; | |
attributes["data_0"] = 0x40a444d8; | |
attributes["data_1"] = 0x27131efc; | |
attributes["data_2"] = 0x3; | |
} | |
virtual bool Demodulate(const CArray<uint16_t>& pulse, CAttributes& attributes) override | |
{ | |
uint8_t nibblesData[20]; | |
CArray<uint8_t> b(nibblesData, COUNT(nibblesData)); | |
int length = 0; | |
if (!PulseToBytes(pulse, b, length)) | |
return false; | |
BitstreamToAttributes(b, length, attributes); | |
Analyse(attributes, b, length); | |
return true; | |
} | |
void Analyse(CAttributes& attributes, CArray<uint8_t>& b, int length) | |
{ | |
int btn; | |
if (length < 66) | |
return; | |
if (b.GetSize() < 9) /*66 bit-s, 8bytes and a bit more*/ | |
{ | |
_ASSERT(0); | |
return; | |
} | |
} | |
void BitstreamToAttributes(CArray<uint8_t>& b, int bitLength, CAttributes& attributes) | |
{ | |
int btn; | |
if (bitLength < 66) | |
{ | |
BIOS::DBG::Print("\nbitLength: %d", bitLength); | |
_ASSERT(0); | |
return; | |
} | |
if (b.GetSize() < 9) | |
{ | |
BIOS::DBG::Print("\nbSize: %d", b.GetSize()); | |
_ASSERT(0); | |
return; | |
} | |
attributes["length"] = bitLength; // count of bits | |
attributes["encrypted"] = ((unsigned)(reverse8(b[3]) << 24) | (reverse8(b[2]) << 16) | (reverse8(b[1]) << 8) | (reverse8(b[0]))); | |
attributes["serial"] = (reverse8(b[7] & 0xf0) << 24) | (reverse8(b[6]) << 16) | (reverse8(b[5]) << 8) | (reverse8(b[4])); | |
btn = (b[7] & 0x0f); | |
attributes["btn"] = btn; | |
attributes["btn_num"] = (btn & 0x08) | ((btn & 0x01) << 2) | (btn & 0x02) | ((btn & 0x04) >> 2); // S3, S0, S1, S2 | |
attributes["learn"] = (b[7] & 0x0f) == 0x0f; | |
attributes["battery_low"] = (b[8] & 0x80) == 0x80; | |
attributes["repeat"] = (b[8] & 0x40) == 0x40; | |
/* | |
attributes["data_0"] = attributes["encrypted"]; | |
attributes["data_1"] = attributes["serial"]; | |
attributes["data_2"] = b[8] & 0xC0;*/ | |
} | |
void AttributesToBitstream(const CAttributes& attributes, CArray<uint8_t>& b, int& bitLength) | |
{ | |
bitLength = attributes["length"]; | |
// TE = 400us | |
//todo preamble 23-pulses 12-high,11-low 23 * TE | |
//todo header 10 * TE | |
uint32_t encrypted = attributes["encrypted"]; | |
int serial = attributes["serial"]; | |
int btn = attributes["btn"]; | |
int btn_num = attributes["btn_num"]; | |
int learn = attributes["learn"]; | |
int battery_low = attributes["battery_low"]; | |
int repeat = attributes["repeat"]; | |
int status; | |
//encrypted | |
b.Add(reverse8((encrypted >> 24) && 0xff)); //0 | |
b.Add(reverse8(encrypted >> 16) && 0xff); | |
b.Add(reverse8(encrypted >> 8) && 0xff); | |
b.Add(reverse8(encrypted & 0xff)); //3 | |
//serial | |
b.Add(reverse8(serial & 0xff)); //4 | |
b.Add(reverse8((serial >> 8) & 0xff)); | |
b.Add(reverse8((serial >> 16) & 0xff)); //6 | |
//serial-msb + btn | |
if (learn) | |
btn = 0x0f; | |
b.Add(reverse8( ((serial >> 24) & 0xf0)) | (btn & 0x0f)); //7 | |
status = 0; | |
if (battery_low) | |
status |= 0x80; | |
if (repeat) | |
status |= 0x40; | |
b.Add(reverse8(status & 0xff)); //8 | |
} | |
virtual bool Modulate(const CAttributes& attr, CArray<uint16_t>& pulse) override | |
{ | |
uint8_t nibblesData[9]; | |
CArray<uint8_t> b(nibblesData, COUNT(nibblesData)); | |
int length = 0; | |
AttributesToBitstream(attr, b, length); | |
return BytesToPulse(b, length, pulse); | |
} | |
virtual int PulseDivisor() override { return 370; } | |
private: | |
unsigned char reverse8(unsigned char b) { | |
b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; | |
b = (b & 0xCC) >> 2 | (b & 0x33) << 2; | |
b = (b & 0xAA) >> 1 | (b & 0x55) << 1; | |
return b; | |
} | |
int PulseLen(int microseconds) | |
{ | |
return (microseconds+100)/370; | |
} | |
int PulseDuration(int ticks) | |
{ | |
return ticks*370; | |
} | |
bool PulseToBytes(const CArray<uint16_t>& pulse, CArray<uint8_t>& bytes, int& length) | |
{ | |
int i; | |
int preambule = 0; | |
for (i=0; i<pulse.GetSize()-33; i++) | |
{ | |
int t = PulseLen(pulse[i]); | |
if (t >= 1 && t <=2) | |
{ | |
preambule++; | |
if (preambule == 23) | |
{ | |
i++; | |
break; | |
} | |
} | |
else { | |
preambule = 0; | |
} | |
} | |
if (preambule < 23) // should be 23*Te | |
return false; | |
//should be 10*Te | |
if (PulseLen(pulse[i]) >=9 && PulseLen(pulse[i]) <=11) | |
i++; | |
else | |
return false; | |
length = 0; | |
int bits = 0; | |
bool buffer_fix = false; | |
for (; i<pulse.GetSize()-1; i+=2) | |
{ | |
int p0 = PulseLen(pulse[i]); | |
int p1 = PulseLen(pulse[i+1]); | |
if (p0==2 && p1==1) | |
{ | |
length++; | |
bits <<= 1; | |
bits |= 0; | |
} | |
else if (p0==1 && p1==2) | |
{ | |
length++; | |
bits <<= 1; | |
bits |= 1; | |
} | |
else | |
{ | |
return false; | |
} | |
if ((length & 7) == 0) | |
{ | |
// swap nibbles | |
bits = reverse8(bits); | |
bytes.Add(bits); | |
bits = 0; | |
} | |
//next item is last, final zero not in buffer ? | |
if (pulse.GetSize() - i == 3) | |
buffer_fix = true; | |
} | |
if (buffer_fix) | |
{ | |
int p0 = PulseLen(pulse[i]); | |
if (p0==2 /*&& p1==1*/) | |
{ | |
length++; | |
bits <<= 1; | |
bits |= 0; | |
} | |
else if (p0==1 /*&& p1==2*/) | |
{ | |
length++; | |
bits <<= 1; | |
bits |= 1; | |
} | |
else | |
{ | |
return false; | |
} | |
if ((length & 7) == 0) | |
{ | |
// swap nibbles | |
bits = reverse8(bits); | |
bytes.Add(bits); | |
bits = 0; | |
} | |
} | |
if ((length & 7) != 0) | |
{ | |
bits = reverse8(bits); | |
bytes.Add(bits); | |
} | |
return true; | |
} | |
bool BytesToPulse(const CArray<uint8_t>& bytes, int length, CArray<uint16_t>& pulse) | |
{ | |
const int preambule = 23; // 23 * TE = 400us 101010.....? | |
for (int i=0; i <preambule; i++) | |
pulse.Add(PulseDuration(1)); | |
pulse.Add(PulseDuration(10)); | |
for (int i=0; i<length; i++) | |
{ | |
int bit = (bytes[i/8] >> (i&7)) & 1; | |
if (bit) | |
{ | |
pulse.Add(PulseDuration(1)); | |
pulse.Add(PulseDuration(2)); | |
} else | |
{ | |
pulse.Add(PulseDuration(2)); | |
pulse.Add(PulseDuration(1)); | |
} | |
} | |
return true; | |
} | |
virtual void GetName(char* name) override | |
{ | |
strcpy(name, "Keeloq HCS200/300"); | |
} | |
virtual void GetDescription(CAttributes& attributes, char* desc) override | |
{ | |
/* | |
attributes["length"] = bitLength; // count of bits | |
attributes["encrypted"] = ((unsigned)(reverse8(b[3]) << 24) | (reverse8(b[2]) << 16) | (reverse8(b[1]) << 8) | (reverse8(b[0]))); | |
attributes["serial"] = (reverse8(b[7] & 0xf0) << 24) | (reverse8(b[6]) << 16) | (reverse8(b[5]) << 8) | (reverse8(b[4])); | |
btn = (b[7] & 0x0f); | |
attributes["btn"] = btn; | |
attributes["btn_num"] = (btn & 0x08) | ((btn & 0x01) << 2) | (btn & 0x02) | ((btn & 0x04) >> 2); // S3, S0, S1, S2 | |
attributes["learn"] = (b[7] & 0x0f) == 0x0f; | |
attributes["battery_low"] = (b[8] & 0x80) == 0x80; | |
attributes["repeat"] = (b[8] & 0x40) == 0x40; | |
*//* | |
if (attributes.indexOf("encrypted") != -1) | |
sprintf(desc, "encrypted: <%08x>", (int)attributes["encrypted"]); | |
if (attributes.indexOf("serial") != -1) | |
sprintf(desc, "serial: <%07x>", (int)attributes["serial"]); | |
else*/ | |
sprintf(desc, "%d bits: <%08x %07x %04x %01x %01x>", | |
(int)attributes["length"], (int)attributes["encrypted"], (int)attributes["serial"], | |
((uint16_t)attributes["btn"]), ((uint8_t)attributes["battery_low"]), ((uint8_t)attributes["repeat"])); | |
} | |
virtual const char* GetString(int i) override | |
{ | |
return nullptr; | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace BIOS | |
{ | |
namespace DBG | |
{ | |
void Print(const char * format, ...) | |
{ | |
char buf[1024]; | |
va_list args; | |
va_start( args, format ); | |
vsprintf( buf, format, args ); | |
printf("%s", buf); | |
va_end(args); | |
} | |
} | |
} | |
extern "C" { | |
void _HandleAssertion(const char* file, int line, const char* cond) | |
{ | |
BIOS::DBG::Print("Assertion failed in "); | |
BIOS::DBG::Print(file); | |
BIOS::DBG::Print(" [%d]: %s\n", line, cond); | |
#ifdef __APPLE__ | |
//kill(getpid(), SIGSTOP); | |
#endif | |
while (1); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
struct TKeyValue | |
{ | |
char* key; | |
uintptr_t value; | |
}; | |
class CAttributes : public CArray<TKeyValue> | |
{ | |
public: | |
typedef TKeyValue TAttribute; | |
public: | |
CAttributes(TAttribute* attr, int count) : CArray<TKeyValue>(attr, count) | |
{ | |
} | |
uintptr_t& operator[](const char* key) | |
{ | |
for (int i=0; i<GetSize(); i++) | |
if (strcmp(CArray<TKeyValue>::operator[](i).key, key) == 0) | |
return CArray<TKeyValue>::operator[](i).value; | |
Add(TKeyValue{(char*)key, 0}); | |
return GetLast().value; | |
} | |
int operator[](const char* key) const | |
{ | |
for (int i=0; i<GetSize(); i++) | |
if (strcmp(CArray<TKeyValue>::operator[](i).key, key) == 0) | |
return CArray<TKeyValue>::operator[](i).value; | |
_ASSERT(0); | |
return 0; | |
} | |
const TKeyValue& operator[](int i) const | |
{ | |
return CArray<TKeyValue>::operator[](i); | |
} | |
TKeyValue& operator[](int i) | |
{ | |
return CArray<TKeyValue>::operator[](i); | |
} | |
int indexOf(const char* key) | |
{ | |
for (int i=0; i<GetSize(); i++) | |
if (strcmp(CArray<TKeyValue>::operator[](i).key, key) == 0) | |
return i; | |
return -1; | |
} | |
}; | |
class CProtocol | |
{ | |
public: | |
virtual int Frequency() = 0; | |
/* | |
// TODO: remove | |
virtual int MinIndentifyCount() { return 0; } | |
virtual int MinDemodulateCount() { return 0; } | |
virtual int AttackPoint(CArray<int>& pulse) { return 0; } | |
virtual bool Identify(CArray<int>& pulse) { return false; } | |
*/ | |
virtual void Example(CAttributes& attributes) = 0; | |
virtual bool Demodulate(const CArray<uint16_t>& pulse, CAttributes& attributes) = 0; | |
virtual bool Modulate(const CAttributes& attr, CArray<uint16_t>& pulse) = 0; | |
virtual void Synthesize(CAttributes& attr) {} | |
virtual void GetName(char*) = 0; | |
virtual void GetDescription(CAttributes& attributes, char* desc) = 0; | |
virtual const char* GetString(int i) = 0; | |
virtual int PulseDivisor() = 0; | |
void PulseToBitstream(const CArray<uint16_t>& pulse, CArray<uint8_t>& bitstream, int interval) | |
{ | |
int n = 0; | |
for (int i=0; i<pulse.GetSize(); i++) | |
{ | |
for (int j=0; j<pulse[i]; j+=interval, n++) | |
{ | |
int bit = 1-(i&1); | |
int byteIndex = n >> 3; | |
int bitIndex = n & 7; | |
if (bitIndex == 0) | |
bitstream.Add(0); | |
bitstream[byteIndex] |= bit << (7-bitIndex); | |
} | |
} | |
} | |
void BitstreamToAttributes(CArray<uint8_t>& b, int bitLength, CAttributes& attributes) | |
{ | |
attributes["length"] = bitLength; // count of bits | |
uint32_t data=0; | |
int bytes = b.GetSize(); | |
for (int i=0; i<bytes; i++) // per each byte | |
{ | |
bool last = i==bytes-1; | |
data |= b[i] << (8*(3-(i&3))); | |
if ((i&3)==3 || last) | |
{ | |
switch (i/4) // store as dword | |
{ | |
case 0: attributes["data_0"] = data; break; | |
case 1: attributes["data_1"] = data; break; | |
case 2: attributes["data_2"] = data; break; | |
default: _ASSERT(0); | |
} | |
data = 0; | |
} | |
} | |
} | |
void AttributesToBitstream(const CAttributes& attributes, CArray<uint8_t>& b, int& bitLength) | |
{ | |
bitLength = attributes["length"]; | |
uint32_t data; | |
int bytes = (bitLength+7)/8; | |
for (int i=0; i<bytes; i++) | |
{ | |
if ((i&3) == 0) | |
{ | |
switch (i/4) | |
{ | |
case 0: data = attributes["data_0"]; break; | |
case 1: data = attributes["data_1"]; break; | |
case 2: data = attributes["data_2"]; break; | |
default: _ASSERT(0); | |
} | |
} | |
b.Add(data >> 24); | |
data <<= 8; | |
} | |
} | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
g++ -std=c++11 ./test.cpp -o test | |
./test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <stdio.h> | |
#include <stdarg.h> | |
#include "library.h" | |
#include "Classes.h" | |
#include "protocol.h" | |
#include "hcs.h" | |
int main(void) | |
{ | |
uint16_t pulses[] = { 360,380,340,380,360,360,360,360,360,360,360,360,360,360,360,360,380,360,360,360,360,360,360,3820,360,780,360,760,740,380,740,380,740,380,360,760,380,760,740,380,360,760,740,380,360,760,740,400,360,760,740,380,360,760,740,400,720,400,340,780,360,760,360,760,360,760,380,760,360,760,360,760,360,780,720,400,740,380,360,760,360,760,740,380,760,380,360,760,740,380,360,780,340,780,360,760,740,380,740,400,720,400,740,380,740,380,740,400,720,400,340,780,740,380,740,380,740,380,360,760,760,380,360,760,740,380,360,760,360,780,740,380,740,380,740,380,740,380,760,380,740,380,740,380,740,380,360,780,740,380,740,380,740 }; | |
CArray<uint16_t> pulse(pulses, COUNT(pulses)); | |
CHcs200 hcs; | |
CAttributes::TAttribute attributesData[20]; | |
CAttributes attributes(attributesData, COUNT(attributesData)); | |
bool status = hcs.Demodulate(pulse, attributes); | |
printf("decode = %d\n", status); | |
for (int i=0; i<attributes.GetSize(); i++) | |
printf("%s = %x\n", attributes[i].key, attributes[i].value); | |
return 0; | |
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#pragma once | |
#include <assert.h> | |
#ifdef __cplusplus | |
#include <algorithm> | |
#endif | |
#include <string.h> | |
#include <stdint.h> | |
#include <stdbool.h> | |
#ifdef __cplusplus | |
extern "C" | |
#endif | |
void _HandleAssertion(const char*, int, const char*); | |
#define _STR(x) #x | |
#ifndef _ASSERT | |
#define _ASSERT(e) {if(!(e)) _HandleAssertion(__FILE__, __LINE__, _STR(e)); } | |
#endif | |
#define ToWord(a, b) (ui16)(((a)<<8)|(b)) | |
#define ToDword(a, b, c, d) (ui32)((ToWord(d, c)<<16)|ToWord(b,a)) | |
#ifdef __APPLE__ | |
#define min(a,b) std::min(a,b) | |
#define max(a,b) std::max(a,b) | |
#else | |
#define min(a,b) (((a)<(b))?(a):(b)) | |
#define max(a,b) (((a)>(b))?(a):(b)) | |
#endif | |
#define COUNT(arr) (int)(sizeof(arr)/sizeof(arr[0])) | |
#ifdef __APPLE__ | |
#define NATIVEENUM uint32_t | |
#elif WIN32 | |
#define NATIVEENUM uint32_t | |
#else | |
#define NATIVEENUM uint8_t | |
#endif | |
#define NATIVEPTR uintptr_t | |
// TODO: remove these types | |
typedef unsigned char ui8; | |
typedef unsigned short ui16; | |
typedef void* PVOID; | |
#ifdef WIN32 | |
typedef int BOOL; | |
#else | |
typedef bool BOOL; | |
#endif | |
typedef const char * PCSTR; | |
typedef char * PSTR; | |
#ifndef WIN32 | |
typedef uint32_t UINT; | |
#endif | |
#define EVERY(ms) static long dwTick##__LINE__ = 0; bool bDo##__LINE__ = BIOS::SYS::GetTick() - dwTick##__LINE__ > ms; if (bDo##__LINE__) dwTick##__LINE__ = BIOS::SYS::GetTick(); if (bDo##__LINE__) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment