Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "SCM.h"
- SCM g_cSCM;
- ISR(SPI_STC_vect) {
- g_cSCM.ManageSlaveSPIInterrupt();
- }
- ISR(TIMER1_COMPA_vect) {
- g_cSCM.ManagePCAEnable();
- }
- volatile bool OutputSelector(uint8_t nSelect) {
- return g_cSCM.OutputSelector(nSelect);
- }
- volatile void InputSelector(uint8_t nSelect) {
- g_cSCM.InputSelector(nSelect);
- }
- int main(void) {
- g_cSCM.SetOutputSelectorCallback(&OutputSelector);
- g_cSCM.SetInputSelectorCallback(&InputSelector);
- sei();
- g_cSCM.Run();
- }
- —————————————————————————————
- SCM:
- #ifndef SCM_H_
- #define SCM_H_
- #include "ModuleCapacityOptions.h"
- #include "ModuleSelectOptions.h"
- #include "AVRBase.h"
- #include "Blink.h"
- #include "SPIProtocol.h"
- #define BOARD_BUILD BUILD_NUMBER_STR
- #include "PCA9685.h"
- #define SERVO_TIMING_RANGE 4096
- #define SERVOMIN_TIMING 150
- #define SERVOMAX_TIMING 3500
- #define SERVO_COMMAND_MAX 10000
- #define SERVO_COMMAND_MIN -10000
- #define SERVO_COMMAND_RANGE 20000 //SERVO_COMMAND_MAX-SERVO_COMMAND_MIN
- #define NUM_SERVO_CHANNELS 16
- class SCM : public AVRBase {
- public:
- SCM();
- ~SCM();
- void ManageSlaveSPIInterrupt();
- void SetOutputSelectorCallback(volatile bool (* pCallback)(uint8_t)) { m_cSPIProtocol.SetOutputSelectorCallback(pCallback); }
- void SetInputSelectorCallback(volatile void (pCallback)(uint8_t)) { m_cSPIProtocol.SetInputSelectorCallback(pCallback); }
- void Run();
- void CustomSetup();
- void CustomLoop();
- bool OutputSelector(uint8_t);
- void InputSelector(uint8_t);
- void SetServoPos(uint8_t, float);
- private:
- SPIProtocol m_cSPIProtocol;
- Blink m_cBlink;
- volatile uint8_t m_nModuleStatus;
- volatile uint32_t m_nModuleCapacities;
- volatile uint8_t m_eSystemStatus;
- volatile uint8_t m_eMissionStage;
- PCA9685 * m_pcPCA9685;
- // System data
- int8_t m_nNumServoChannels;
- volatile int16_t m_anServoPos[NUMSERVOS];
- volatile int16_t m_anServoZero[NUMSERVOS];
- volatile int16_t m_anServoMax[NUMSERVOS];
- volatile int16_t m_anServoMin[NUMSERVOS];
- volatile bool m_abServoEnable[NUMSERVOS];
- volatile bool m_abServoChanged[NUMSERVOS];
- // volatile uint8_t m_anServoFrequency[NUMSERVOS];
- int16_t m_fServoRange;
- uint8_t m_nSelectedServo;
- volatile bool m_bPCAOutputEnabled;
- volatile uint8_t m_nPCAEnableWindowCountdown;
- };
- #endif
- SCM::SCM() {
- m_nNumServoChannels = 16;
- m_nModuleCapacities = BIT17_SERVO_CONTROLER;
- m_nModuleStatus = 0;
- // sbi(m_nModuleStatus, MODULE_STATUS_BIT_NONZERO);
- m_nSelectedServo = 0;
- m_bPCAOutputEnabled = false;
- m_nPCAEnableWindowCountdown = 3;
- GPIO1_IS_OUTPUT;
- GPIO1_HIGH;
- m_pcPCA9685 = new(PCA9685);
- m_pcPCA9685->Reset();
- m_pcPCA9685->SetPWMFreq(500);
- for (uint8_t nIndex = 0; nIndex < NUMSERVOS; nIndex++) {
- m_anServoZero[nIndex] = 0;
- m_anServoMax[nIndex] = SERVO_COMMAND_MAX;
- m_anServoMin[nIndex] = SERVO_COMMAND_MIN;
- m_anServoPos[nIndex] = SERVO_COMMAND_MIN;
- m_abServoEnable[nIndex] = false;
- m_abServoChanged[nIndex] = true;
- }
- GPIO1_LOW; // PWM OUTPUT ENABLE
- m_cBlink.SetLEDGPIO(7);
- m_cBlink.SetLEDOnCount(50000);
- m_cBlink.SetLEDOffCount(50000);
- m_cBlink.BlinkLED();
- }
- SCM::~SCM() {
- }
- void SCM::ManageSlaveSPIInterrupt() {
- m_cSPIProtocol.ManageSlaveSPIInterrupt();
- }
- void SCM::Run() {
- CustomSetup();
- while(1) {
- m_cBlink.ManageLED();
- CustomLoop();
- }
- }
- void SCM::CustomSetup() {
- m_cSPIProtocol.RunAsSlave();
- m_cSPIProtocol.InitSPI();
- TCCR1B |= (1 << WGM12); // Configure timer 1 for CTC mode
- TIMSK |= (1 << OCIE1A); // Enable CTC interrupt
- OCR1A = 155;
- TCCR1B |= ((1 << CS10) | (1 << CS12)); // Start timer at Fcpu/1024
- }
- void SCM::CustomLoop() {
- uint8_t nServoNum;
- for (nServoNum = 0; nServoNum < NUM_SERVO_CHANNELS; nServoNum++) {
- if (m_abServoChanged[nServoNum]) {
- if (m_abServoEnable[nServoNum]) {
- SetServoPos(nServoNum);
- }
- else {
- m_anServoPos[nServoNum] = SERVO_COMMAND_MIN;
- SetServoPos(nServoNum);
- }
- m_abServoChanged[nServoNum] = false;
- }
- }
- }
- void SCM::ManagePCAEnable() {
- if (m_bPCAOutputEnabled) {
- GPIO1_HIGH;
- m_bPCAOutputEnabled = false;
- OCR1A = 155;
- }
- else {
- m_nPCAEnableWindowCountdown--;
- // Protection against loss of communication from COM module.
- if (m_nPCAEnableWindowCountdown > 0) {
- GPIO1_LOW;
- m_bPCAOutputEnabled = true;
- }
- OCR1A = 15;
- }
- }
- bool SCM::OutputSelector(uint8_t nSelect) {
- switch (nSelect) {
- case B00_MODULE_STATUS: m_cSPIProtocol.SendByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE, (uint8_t) m_nModuleStatus); break;
- case B00_SYSTEM_STATUS: m_cSPIProtocol.ExpectByte(); break;
- case B00_MISSION_STAGE: m_cSPIProtocol.ExpectByte(); break;
- case B17_NUM_SERVO_CHANNELS: m_cSPIProtocol.SendByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE, m_nNumServoChannels); break;
- case B17_SERVO_SELECT: m_cSPIProtocol.ExpectByte(); break;
- case B17_SERVO_MIN: m_cSPIProtocol.ExpectInt(); break;
- case B17_SERVO_MAX: m_cSPIProtocol.ExpectInt(); break;
- case B17_SERVO_ZERO: m_cSPIProtocol.ExpectInt(); break;
- case B17_SERVO_POS: m_cSPIProtocol.ExpectInt(); break;
- case B17_SERVO_ENABLE: m_cSPIProtocol.ExpectByte(); break;
- default: SPDR = NOT_UNDERSTOOD; return false;
- }
- return true;
- }
- void SCM::InputSelector(uint8_t nSelect) {
- switch (nSelect) {
- case B00_SYSTEM_STATUS: m_eSystemStatus = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE); break;
- case B00_MISSION_STAGE: m_eMissionStage = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE); break;
- case B17_SERVO_SELECT: m_nSelectedServo = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
- m_nPCAEnableWindowCountdown = 3;
- break;
- case B17_SERVO_MIN: m_nServoMin[m_nSelectedServo] = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
- m_abServoChanged[m_nSelectedServo] = true;
- break;
- case B17_SERVO_MAX: m_nServoMax[m_nSelectedServo] = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
- m_abServoChanged[m_nSelectedServo] = true;
- break;
- case B17_SERVO_ZERO: m_nServoZero[m_nSelectedServo] = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
- m_abServoChanged[m_nSelectedServo] = true;
- break;
- case B17_SERVO_POS: m_nServoPos[m_nSelectedServo] = m_cSPIProtocol.ReadLongViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
- m_abServoChanged[m_nSelectedServo] = true;
- break;
- case B17_SERVO_ENABLE: m_nServoEnable[m_nSelectedServo] = m_cSPIProtocol.ReadByteViaSPI(NOT_APPLICABLE, NOT_APPLICABLE);
- m_abServoChanged[m_nSelectedServo] = true;
- break;
- default: SPDR = NOT_UNDERSTOOD;
- }
- }
- void SCM::SetServoPos(uint8_t nServoNum) {
- if (nServoNum < NUMSERVOS) {
- if (m_abServoEnable[nServoNum]) {
- uint16_t nServoPos = m_anServoPos[nServoNum];
- uint16_t nServoOffTime;
- if (nServoPos < m_anServoMin[nServoNum]) {
- nServoPos = m_anServoMin[nServoNum];
- }
- if (nServoPos > m_anServoMax[nServoNum]) {
- nServoPos = m_anServoMax[nServoNum];
- }
- nServoOffTime = ((-1 * SERVO_COMMAND_MIN) + nServoPos) * (SERVO_TIMING_RANGE / SERVO_COMMAND_RANGE); // make the second term a constant!
- m_pcPCA9685->SetPWM(nServoNum, 0, nServoOffTime);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment