Skip to content

Commit

Permalink
Added Fsm and GlobalFsm classes.
Browse files Browse the repository at this point in the history
  • Loading branch information
t0mpr1c3 committed Aug 23, 2020
1 parent 72fef24 commit a1ce5d2
Show file tree
Hide file tree
Showing 29 changed files with 996 additions and 648 deletions.
93 changes: 60 additions & 33 deletions src/ayab/com.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,64 @@ void Com::init() {
#endif // AYAB_TESTS
}

void Com::update() {
m_packetSerial.update();
}

void Com::send(uint8_t *payload, size_t length) {
// TODO(TP): insert a workaround for hardware test code
/*
#ifdef AYAB_HW_TEST
Serial.print("Sent: ");
for (uint8_t i = 0; i < length; ++i) {
Serial.print(payload[i]);
}
Serial.print(", Encoded as: ");
#endif
*/
m_packetSerial.send(payload, length);
}

// send initial msgid followed by null-terminated string
void Com::sendMsg(AYAB_API_t id, const char *msg) {
uint8_t length = 0;
msgBuffer[length++] = static_cast<uint8_t>(id);
while (*msg) {
msgBuffer[length++] = static_cast<uint8_t>(*msg++);
}
m_packetSerial.send(msgBuffer, length);
}

void Com::sendMsg(AYAB_API_t id, char *msg) {
sendMsg(id, static_cast<const char *>(msg));
}

void Com::send_reqLine(const uint8_t lineNumber) {
uint8_t payload[REQLINE_LEN] = {
reqLine_msgid,
lineNumber,
};
send(static_cast<uint8_t *>(payload), REQLINE_LEN);
}

void Com::send_indState(Carriage_t carriage, uint8_t position,
const bool initState) {
uint16_t leftHallValue = GlobalEncoders::getHallValue(Left);
uint16_t rightHallValue = GlobalEncoders::getHallValue(Right);
uint8_t payload[INDSTATE_LEN] = {
indState_msgid,
static_cast<uint8_t>(initState),
highByte(leftHallValue),
lowByte(leftHallValue),
highByte(rightHallValue),
lowByte(rightHallValue),
static_cast<uint8_t>(carriage),
static_cast<uint8_t>(position),
static_cast<uint8_t>(GlobalEncoders::getDirection()),
};
GlobalCom::send(static_cast<uint8_t *>(payload), INDSTATE_LEN);
}

/*!
* \brief Callback for PacketSerial.
*/
Expand Down Expand Up @@ -135,38 +193,6 @@ void Com::onPacketReceived(const uint8_t *buffer, size_t size) {
}
}

void Com::update() {
m_packetSerial.update();
}

void Com::send(uint8_t *payload, size_t length) {
// TODO(TP): insert a workaround for hardware test code
/*
#ifdef AYAB_HW_TEST
Serial.print("Sent: ");
for (uint8_t i = 0; i < length; ++i) {
Serial.print(payload[i]);
}
Serial.print(", Encoded as: ");
#endif
*/
m_packetSerial.send(payload, length);
}

// send initial msgid followed by null-terminated string
void Com::sendMsg(AYAB_API_t id, const char *msg) {
uint8_t length = 0;
msgBuffer[length++] = static_cast<uint8_t>(id);
while (*msg) {
msgBuffer[length++] = static_cast<uint8_t>(*msg++);
}
m_packetSerial.send(msgBuffer, length);
}

void Com::sendMsg(AYAB_API_t id, char *msg) {
sendMsg(id, static_cast<const char *>(msg));
}

// Serial command handling

/*!
Expand Down Expand Up @@ -283,7 +309,7 @@ void Com::h_reqTest(const uint8_t *buffer, size_t size) {
}

Machine_t machineType = static_cast<Machine_t>(buffer[0]);
bool success = GlobalKnitter::startTest(machineType);
bool success = GlobalTester::startTest(machineType);

uint8_t payload[2];
payload[0] = cnfTest_msgid;
Expand All @@ -296,3 +322,4 @@ void Com::h_unrecognized() {
// do nothing
}
// GCOVR_EXCL_STOP
//
15 changes: 15 additions & 0 deletions src/ayab/com.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
#include <Arduino.h>
#include <PacketSerial.h>

#include "encoders.h"

constexpr uint8_t FW_VERSION_MAJ = 1U;
constexpr uint8_t FW_VERSION_MIN = 0U;
constexpr uint8_t FW_VERSION_PATCH = 0U;
Expand Down Expand Up @@ -64,6 +66,10 @@ enum AYAB_API {
};
using AYAB_API_t = enum AYAB_API;

// API constants
constexpr uint8_t INDSTATE_LEN = 9U;
constexpr uint8_t REQLINE_LEN = 2U;

class ComInterface {
public:
virtual ~ComInterface(){};
Expand All @@ -74,6 +80,9 @@ class ComInterface {
virtual void send(uint8_t *payload, size_t length) = 0;
virtual void sendMsg(AYAB_API_t id, const char *msg) = 0;
virtual void sendMsg(AYAB_API_t id, char *msg) = 0;
virtual void send_reqLine(const uint8_t lineNumber) = 0;
virtual void send_indState(Carriage_t carriage, uint8_t position,
const bool initState = false) = 0;
virtual void onPacketReceived(const uint8_t *buffer, size_t size) = 0;
};

Expand All @@ -96,6 +105,9 @@ class GlobalCom final {
static void send(uint8_t *payload, size_t length);
static void sendMsg(AYAB_API_t id, const char *msg);
static void sendMsg(AYAB_API_t id, char *msg);
static void send_reqLine(const uint8_t lineNumber);
static void send_indState(Carriage_t carriage, uint8_t position,
const bool initState = false);
static void onPacketReceived(const uint8_t *buffer, size_t size);

private:
Expand All @@ -109,6 +121,9 @@ class Com : public ComInterface {
void send(uint8_t *payload, size_t length);
void sendMsg(AYAB_API_t id, const char *msg);
void sendMsg(AYAB_API_t id, char *msg);
void send_reqLine(const uint8_t lineNumber);
void send_indState(Carriage_t carriage, uint8_t position,
const bool initState = false);
void onPacketReceived(const uint8_t *buffer, size_t size);

private:
Expand Down
99 changes: 99 additions & 0 deletions src/ayab/fsm.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
/*!
* \file fsm.cpp
* \brief Singleton class containing methods for the finite state machine
* that co-ordinates the AYAB firmware.
*
* This file is part of AYAB.
*
* AYAB 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 3 of the License, or
* (at your option) any later version.
*
* AYAB 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 AYAB. If not, see <http://www.gnu.org/licenses/>.
*
* Original Work Copyright 2013-2015 Christian Obersteiner, Andreas Müller
* Modified Work Copyright 2020 Sturla Lange, Tom Price
* http://ayab-knitting.com
*/

#include "board.h"
#include <Arduino.h>

#include "com.h"
#include "fsm.h"
#include "knitter.h"

// Public methods

void Fsm::init() {
m_opState = s_init;
}

OpState_t Fsm::getState() {
return m_opState;
}

void Fsm::setState(OpState_t state) {
m_opState = state;
}

/*!
* \brief Dispatch on machine state
*
* \todo TP: add error state(s)
*/
void Fsm::dispatch() {
switch (m_opState) {
case s_init:
state_init();
break;

case s_ready:
state_ready();
break;

case s_knit:
state_knit();
break;

case s_test:
state_test();
break;

default:
break;
}
GlobalCom::update();
}

// Private methods

void Fsm::state_init() {
if (GlobalKnitter::isReady()) {
setState(s_ready);
}
}

void Fsm::state_ready() {
digitalWrite(LED_PIN_A, 0); // green LED off
}

void Fsm::state_knit() {
digitalWrite(LED_PIN_A, 1); // green LED on
GlobalKnitter::knit();
}

void Fsm::state_test() {
GlobalKnitter::encodePosition();
GlobalTester::loop();
if (GlobalTester::getQuitFlag()) {
setState(s_ready);
}
}
82 changes: 82 additions & 0 deletions src/ayab/fsm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*!`
* \file fsm.h
*
* This file is part of AYAB.
*
* AYAB 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 3 of the License, or
* (at your option) any later version.
*
* AYAB 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 AYAB. If not, see <http://www.gnu.org/licenses/>.
*
* Original Work Copyright 2013 Christian Obersteiner, Andreas Müller
* Modified Work Copyright 2020 Sturla Lange, Tom Price
* http://ayab-knitting.com
*/

#ifndef FSM_H_
#define FSM_H_

enum OpState { s_init, s_ready, s_knit, s_test };
using OpState_t = enum OpState;

class FsmInterface {
public:
virtual ~FsmInterface(){};

// any methods that need to be mocked should go here
virtual void init() = 0;
virtual OpState_t getState() = 0;
virtual void setState(OpState_t state) = 0;
virtual void dispatch() = 0;
};

// Singleton container class for static methods.
// Dependency injection is enabled using a pointer
// to a global instance of either `Knitter` or `KnitterMock`
// both of which classes implement the pure virtual methods
// of the `KnitterInterface` class.

class GlobalFsm final {
private:
// singleton class so private constructor is appropriate
GlobalFsm() = default;

public:
// pointer to global instance whose methods are implemented
static FsmInterface *m_instance;

static void init();
static OpState_t getState();
static void setState(OpState_t state);
static void dispatch();
};

class Fsm : public FsmInterface {
#if AYAB_TESTS
#endif

public:
void init();
OpState_t getState();
void setState(OpState_t state);
void dispatch();

private:
void state_init();
void state_ready();
void state_knit();
void state_test();

// machine state
OpState_t m_opState;
};

#endif // FSM_H_
9 changes: 9 additions & 0 deletions src/ayab/global_com.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,12 @@ void GlobalCom::onPacketReceived(const uint8_t *buffer, size_t size) {
m_instance->onPacketReceived(buffer, size);
}
// GCOVR_EXCL_STOP

void GlobalCom::send_reqLine(const uint8_t lineNumber) {
m_instance->send_reqLine(lineNumber);
}

void GlobalCom::send_indState(Carriage_t carriage, uint8_t position,
const bool initState) {
m_instance->send_indState(carriage, position, initState);
}
Loading

0 comments on commit a1ce5d2

Please sign in to comment.