Hello!
Consider the rest of this article a Spoiler for the up coming Pokitto Magazine #2. So if you’d like to keep that a surprise, or don’t mind spoilers (like me) then please continue
I am pretty new to C++. I’ve dabbled for a while but never really took on any actual completable project. Until now! (And, I dare say, much more in the future!)
The reason for this post is I’d like some a code review of my project before I write it up in article format forever (ominous hehe). Since I am new to C++, I’d like to make sure that the code is “clean” and suitable for new folks and experienced alike. So! That long-winded explanation out of the way, to the code!
First Draft
#include "Pokitto.h"
#include <IRremote/IRremote.h>
IRsend irsend(EXT0); // PWM output for IR blaster
IRrecv irrecv(EXT3); //currently only 3+ works for the receiver.
// Storage for the recorded code
decode_results results; // results of reading an incoming signal
int codeType = -1; // The type of code
unsigned int rawCodes[RAWBUF]; // The durations if raw
int codeLen; // The length of the code
int readmode = 0; //read mode toggle. 0 = false, 1 = true
using PC=Pokitto::Core;
using PD=Pokitto::Display;
// Stores the code for later playback
// Most of this code is just logging
void storeCode(decode_results *results) {
PD::print("Received code, saving as raw\n");
codeType = results->decode_type;
codeLen = results->rawlen - 1;
// To store raw codes:
// Drop first value (gap)
// Convert from ticks to microseconds
for (int i = 1; i <= codeLen; i++) {
rawCodes[i - 1] = results->rawbuf[i]*USECPERTICK;
PD::print(rawCodes[i - 1]);
}
PD::print("");
}
int main(){
PC::begin();
PD::persistence=true;
PD::invisiblecolor = 0;
PD::setFont(font5x7);
PD::print("PEX IR test\nPress B to scan or A to send.");
PD::update();
irrecv.enableIRIn();
while( PC::isRunning() ){
if(PC::buttons.bBtn()){
PD::clear();
PD::print("Entered scan mode...\n");
PD::update();
readmode = 1;
}
if(PC::buttons.aBtn()){
PD::clear();
PD::print("Sending signal\n");
readmode = 0;
int count = results.rawlen;
for (int i = 1; i < count; i++) {
if (i & 1) {
PD::print(results.rawbuf[i]*USECPERTICK);
} else {
PD::print('-');
PD::print((unsigned long) results.rawbuf[i]*USECPERTICK);
}
PD::print(" ");
}
PD::update();
irsend.sendRaw(rawCodes, codeLen, 38);
PD::print("\nWaiting for signal to finish...");
PD::update();
wait(1);//Give time to send result without receiving at the same time
} else if (irrecv.decode(&results) && readmode == 1) {
PD::clear();
PD::printf("IR Received type = %d, code = %x\n", results.decode_type, results.value);
storeCode(&results);
PD::update();//storeCode uses print()
irrecv.resume(); // resume receiver
PD::print("Waiting for input or command.");
PD::update();
}
}
return 0;
}
After some great help, I have a second draft for review!
Second Draft
#include <Pokitto.h>
#include <IRremote/IRremote.h>
// PWM output for IR blaster
IRsend irSender(EXT0);
// Currently only 3+ works for the receiver.
IRrecv irReceiver(EXT3);
// results of reading an incoming signal
decode_results results;
// The durations if raw
unsigned int rawCodes[RAWBUF];
// The length of the code
int codeLen;
enum class Mode
{
Send,
Scan,
};
Mode mode = Mode::Send;
// Stores the signal for later sending
void storeCode(decode_results results)
{
using Pokitto::Display;
// Used again when sending the signal
codeLen = results.rawlen - 1;
// To store raw codes:
// Drop first value (gap)
// Convert from ticks to microseconds
for (int i = 1; i <= codeLen; i++)
{
rawCodes[i - 1] = results.rawbuf[i] * USECPERTICK;
Display::print(rawCodes[i - 1]);
Display::print(" ");
}
Display::print("\n");
}
// Prints the code benig sent to the screen
void printSentCode()
{
using Pokitto::Display;
for (int i = 1; i < results.rawlen; i++)
{
if ((i % 2) != 0)
{
Display::print(results.rawbuf[i] * USECPERTICK);
}
else
{
Display::print('-');
Display::print((unsigned long) results.rawbuf[i] * USECPERTICK);
}
Display::print(" ");
}
}
int main()
{
using Pokitto::Core;
using Pokitto::Display;
Core::begin();
Display::persistence = true;
Display::invisiblecolor = 0;
Display::setFont(font5x7);
Display::print("PEX IR test\nPress B to scan or A to send.\nC to open this menu.");
irReceiver.enableIRIn();
while(Core::isRunning())
{
if (Core::buttons.cBtn())
{
Display::clear();
Display::print("Press B to scan or A to send.");
mode = Mode::Send;
}
if (Core::buttons.bBtn())
{
Display::clear();
Display::print("Entered scan mode...\n");
mode = Mode::Scan;
}
if (Core::buttons.aBtn())
{
Display::clear();
Display::print("Sending signal:\n");
printSentCode();
// Actually send code
irSender.sendRaw(rawCodes, codeLen, 38);
Display::print("\nWaiting for signal to finish...");
Display::update();
//Give time to send result without receiving at the same time
wait(1);
}
else if ((mode == Mode::Scan) && (irReceiver.decode(&results)))
{
// Enter Send mode to prevent capturing sent code
mode = Mode::Send;
Display::clear();
Display::print("IR Received type = ");
Display::print(results.decode_type);
Display::print("\ncode = ");
Display::print(results.value);
storeCode(results);
// Resume receiver for next time we enter Scan mode
irReceiver.resume();
Display::print("\n\nWaiting for input or command.");
}
Display::update();
}
return 0;
}
I definitely intend to clean up the comments and some coding style, so no worries about that part too much.
Third Draft
#include <Pokitto.h>
#include <IRremote/IRremote.h>
// PWM output for IR blaster
IRsend irSender(EXT0);
// Currently only 3+ works for the receiver.
IRrecv irReceiver(EXT3);
// Results of reading an incoming code
decode_results results;
// The durations if raw
unsigned int rawCode[RAWBUF];
// The length of the code
std::size_t codeLength;
// The type denoting the current operation modes
enum class Mode
{
Send,
Scan,
};
// The variable containing the currently set opreation mode, defaulting to Send
Mode mode = Mode::Send;
// Stores the code for later sending
void storeCode(decode_results results)
{
using Pokitto::Display;
// codeLength is used again when sending the code, so we set it here
codeLength = results.rawlen - 1;
// To store raw codes:
// Drop first value (gap)
// Convert from ticks to microseconds
for (int i = 1; i <= codeLength; ++i)
{
rawCode[i - 1] = results.rawbuf[i] * USECPERTICK;
Display::print(rawCode[i - 1]);
Display::print(" ");
}
Display::print("\n");
}
// Prints the code being sent to the screen
void printSentCode()
{
using Pokitto::Display;
for (int i = 1; i < results.rawlen; ++i)
{
if ((i % 2) != 0)
{
Display::print(results.rawbuf[i] * USECPERTICK);
}
else
{
Display::print('-');
Display::print((unsigned long) results.rawbuf[i] * USECPERTICK);
}
Display::print(" ");
}
}
int main()
{
using Pokitto::Core;
using Pokitto::Display;
using Pokitto::Buttons;
Core::begin();
Display::persistence = true;
Display::invisiblecolor = 0;
Display::setFont(font5x7);
Display::print("PEX IR test\nPress B to scan or A to send.\nC to open this menu.");
// Enable IR In on the receiver so it is ready to scan for IR codes.
irReceiver.enableIRIn();
while (Core::isRunning())
{
if (Buttons::cBtn())
{
Display::clear();
Display::print("Press B to scan or A to send.");
mode = Mode::Send;
}
if (Buttons::bBtn())
{
Display::clear();
Display::print("Entered scan mode...\n");
mode = Mode::Scan;
}
if (Buttons::aBtn())
{
// Immediately set mode to Send to prevent scanning the sent code
mode = Mode::Send;
Display::clear();
Display::print("Sending signal:\n");
printSentCode();
// Send the currently stored code
irSender.sendRaw(rawCode, codeLength, 38);
}
else if ((mode == Mode::Scan) && (irReceiver.decode(&results)))
{
// Enter Send mode to prevent Scanning the code during Send
mode = Mode::Send;
Display::clear();
Display::print("IR Received type = ");
Display::print(results.decode_type);
Display::print("\ncode = ");
Display::print(results.value);
Display::print("\n");
storeCode(results);
// Resume receiver for next time we enter Scan mode
irReceiver.resume();
Display::print("\n\nWaiting for input or command.");
}
Display::update();
}
return 0;
}
I am open to any and all criticism! I’d like this to be as perfect as possible Thanks in advance!