Callum and Adel's changes on 12/02/19

Dependencies:   Crypto

Revision:
19:805c87360b55
Parent:
18:7ee632098fd4
Child:
20:c60f4785b556
--- a/main.cpp	Wed Mar 06 11:26:27 2019 +0000
+++ b/main.cpp	Thu Mar 14 16:08:50 2019 +0000
@@ -1,7 +1,14 @@
 #include "SHA256.h"
 #include "mbed.h"
-//#include <iostream>
+#include <iostream>
+#include "rtos.h"
 
+/*TODO:
+Change 
+Indx
+newCmd
+MAXCMDLENGTH
+*/
 
 //Photointerrupter input pins
 #define I1pin D3
@@ -57,67 +64,310 @@
 InterruptIn I3(I3pin);
 
 //Motor Drive outputs
-DigitalOut L1L(L1Lpin);
+PwmOut     L1L(L1Lpin);
 DigitalOut L1H(L1Hpin);
-DigitalOut L2L(L2Lpin);
+PwmOut     L2L(L2Lpin);
 DigitalOut L2H(L2Hpin);
-DigitalOut L3L(L3Lpin);
+PwmOut     L3L(L3Lpin);
 DigitalOut L3H(L3Hpin);
 
-//Set a given drive state
-void motorOut(int8_t driveState){
+
+//Declare and start threads
+class T_{
     
-    //Lookup the output byte from the drive state.
-    int8_t driveOut = driveTable[driveState & 0x07];
-      
-    //Turn off first
-    if (~driveOut & 0x01) L1L = 0;
-    if (~driveOut & 0x02) L1H = 1;
-    if (~driveOut & 0x04) L2L = 0;
-    if (~driveOut & 0x08) L2H = 1;
-    if (~driveOut & 0x10) L3L = 0;
-    if (~driveOut & 0x20) L3H = 1;
+    protected:
+
+        uint32_t motorPower; // motor toque
+        float targetVel;
+        float targetRot;
+
+        Thread *p_comm_in;
+        Thread *p_comm_out;
+        Thread *p_motor_ctrl;
     
-    //Then turn on
-    if (driveOut & 0x01) L1L = 1;
-    if (driveOut & 0x02) L1H = 0;
-    if (driveOut & 0x04) L2L = 1;
-    if (driveOut & 0x08) L2H = 0;
-    if (driveOut & 0x10) L3L = 1;
-    if (driveOut & 0x20) L3H = 0;
-    }
+    public:
+        
+        T_(){
+            //(priority, stack size, 
+            Thread comm_in(osPriorityAboveNormal, 1024);
+            Thread comm_out(osPriorityAboveNormal, 1024);
+            Thread motor_ctrl(osPriorityAboveNormal, 1024);
+            
+            p_comm_in = &comm_in;
+            p_comm_out = &comm_out;
+            p_motor_ctrl = &motor_ctrl;
+
+            motorPower = 300;
+            targetVel = 45.0;
+            targetRot = 459.0;
+            
+        }
+
+        ~T_(){
+            if (p_comm_in->get_state() == 2)
+                p_comm_in->terminate();
+            if (p_comm_out->get_state() == 2)
+                p_comm_out->terminate();
+            if (p_motor_ctrl->get_state() == 2)
+                p_motor_ctrl->terminate();
+        }
+};
+
+
+class Motor : public T_{
+
+    private:
+            int32_t MAXPWM;
+            int8_t orState;              // Rotor offset at motor state 0 
+            int8_t intStateOld;          // Motor old state, may change in ISR 
+
+            int32_t motorPos;
+
+
+    public:
+
+        Motor(){
+            MAXPWM = 1000;
+            orState = 0;    
+            intStateOld = 0;
+        }
+
+
+        //~~~~~~~~~~~~Set a given drive state~~~~~~~~~~~~
+        void motorOut(int8_t driveState, uint32_t pw){
+
+            //Lookup the output byte from the drive state.
+            int8_t driveOut = driveTable[driveState & 0x07];
+              
+            //Turn off first
+            if (~driveOut & 0x01) L1L.pulsewidth_us(0);
+            if (~driveOut & 0x02) L1H = 1;
+            if (~driveOut & 0x04) L2L.pulsewidth_us(0);
+            if (~driveOut & 0x08) L2H = 1;
+            if (~driveOut & 0x10) L3L.pulsewidth_us(0);
+            if (~driveOut & 0x20) L3H = 1;
+            
+            //Then turn on
+            if (driveOut & 0x01) L1L.pulsewidth_us(pw);
+            if (driveOut & 0x02) L1H = 0;
+            if (driveOut & 0x04) L2L.pulsewidth_us(pw);
+            if (driveOut & 0x08) L2H = 0;
+            if (driveOut & 0x10) L3L.pulsewidth_us(pw);
+            if (driveOut & 0x20) L3H = 0;
+        }
+
+        inline int8_t readRotorState(){
+            return stateMap[I1 + 2*I2 + 4*I3];
+        }
+
+        int8_t motorHome() {
+            //Put the motor in drive state 0 and wait for it to stabilise
+            motorOut(0, MAXPWM); // set to max PWM
+            wait(2.0);
+            
+            //Get the rotor state
+            return readRotorState();
+        }
+
+        void motorISR() {
+            static int8_t oldRotorState;
+            int8_t rotorState = readRotorState();
+            
+            motorOut((rotorState-orState+lead+6)%6,motorPower);
+            
+            // update motorPosition and oldRotorState
+            if (rotorState - oldRotorState == 5) motorPos--;
+            else if (rotorState - oldRotorState == -5) motorPos++;
+            else motorPos += (rotorState - oldRotorState);
+            oldRotorState = rotorState;
+        }
+
+        void stateUpdate(int8_t *params[]) { // () { // **params
+            *params[0] = readRotorState(); 
+            int8_t currentState = *params[0];
+            int8_t offset = *params[1];
+            
+            motorOut((currentState - offset + lead + 6) % 6, MAXPWM);
+        }
+};
+
+
+class Comm : public T_{
     
-    //Convert photointerrupter inputs to a rotor state
-inline int8_t readRotorState(){
-    return stateMap[I1 + 2*I2 + 4*I3];
-    }
+    private:
+        bool _RUN;
+
+        RawSerial pc;
+        Queue<void, 8> inCharQ;  // Input Character Queue
 
-//Basic synchronisation routine    
-int8_t motorHome() {
-    //Put the motor in drive state 0 and wait for it to stabilise
-    motorOut(0);
-    wait(2.0);
-    
-    //Get the rotor state
-    return readRotorState();
-}
+        volatile uint64_t newKey;   // hash key
+        Mutex newKey_mutex;         // Restrict access to prevent deadlock.
+
+        static const char MsgChar[11];
+        
+        uint8_t MAXCMDLENGTH;
+        char newCmd[]; 
+        uint8_t cmdIndx;
+
 
 
-void stateUpdate(int8_t *params[]) { // () { // **params
-    *params[0] = readRotorState(); 
-    int8_t currentState = *params[0];
-    int8_t offset = *params[1];
+        enum msgType {motorState, posIn, velIn, posOut, velOut, 
+        
+                      hashRate, keyAdded, nonceMatch,
+                       
+                      torque, rotations, 
+                      
+                      error};
+
+
+        typedef struct {
+            msgType type;
+            uint32_t message;
+        } msg;
+        
+        Mail<msg, 32> mailStack;
+        
+        void serialISR(){ 
+            uint8_t newChar = pc.getc(); 
+            inCharQ.put((void*)newChar); 
+        } 
+
+        void commInFn() {
+            if (_RUN)
+                pc.attach(callback(this, &Comm::serialISR));
+            while (_RUN) {
+                osEvent newEvent = inCharQ.get();
+                uint8_t newChar = ((uint8_t)(&newEvent.value.p));
+                pc.putc(newChar);
+                if(cmdIndx >= MAXCMDLENGTH){            //Make sure there is no overflow in comand.
+                    cmdIndx = 0;
+                    putMessage(error, 1);
+                }
+                else{
+                    if(newChar != '\r'){                //While the command is not over, 
+                        newCmd[cmdIndx] = newChar;      //save input character and
+                        cmdIndx++;                      //advance index
+                    } 
+                    else{
+                        newCmd[cmdIndx] = '\0';         //When the command is finally over,
+                        cmdIndx = 0;                    //reset index and
+                        cmdParser();                    //parse the command for decoding.
+                    }
+                }
+            }
+        }
+        
+        void cmdParser(){
+            switch(newCmd[0]) {
+                case 'K':
+                        newKey_mutex.lock();                        //Ensure there is no deadlock
+                        sscanf(newCmd, "K%x", &newKey);             //Find desired the Key code
+                        putMessage(keyAdded, newKey);           //Print it out
+                        newKey_mutex.unlock();                      
+                        break;
+                case 'V':
+                        sscanf(newCmd, "V%f", &targetVel);          //Find desired the target velocity
+                        putMessage(velIn, targetVel);      //Print it out
+                        break;
+                case 'R':
+                        sscanf(newCmd, "R%f", &targetRot);          //Find desired target rotation
+                        putMessage(posIn, targetRot);      //Print it out
+                        break;
+                case 'T':
+                        sscanf(newCmd, "T%d", &motorPower);         //Find desired target torque
+                        putMessage(torque, motorPower);         //Print it out
+                        break;
+                default: break;
+            }
+        }
+
+        //~~~~~Decode messages to print on serial port~~~~~
+        void commOutFn() {
+            while (_RUN) {
+                osEvent newEvent = mailStack.get();
+                msg *pMessage = (msg*)newEvent.value.p; // ADEL ??
+
+                //Case switch to choose serial output based on incoming message
+                switch(pMessage->type) {
+                    case motorState:
+                        pc.printf("The motor is currently in state %x\n\r", pMessage->message);
+                        break;
+                    case hashRate:
+                        pc.printf("Mining at a rate of %.2f Hash/s\n\r", (int32_t)pMessage->message);
+                        break;
+                    case nonceMatch:
+                        pc.printf("Nonce found: %x\n\r", pMessage->message);
+                        break;
+                    case keyAdded:
+                        pc.printf("New key added:\t0x%016x\n\r", pMessage->message);
+                        break;
+                    case torque:
+                        pc.printf("Motor torque set to:\t%d\n\r", pMessage->message);
+                        break;
+                    case velIn:
+                        pc.printf("Target velocity set to:\t%.2f\n\r", targetVel);
+                        break;
+                    case velOut:
+                        pc.printf("Current Velocity:\t%.2f\n\r", \
+                            (float)((int32_t)pMessage->message / 6));
+                        break;
+                    case posIn:
+                        pc.printf("Target rotation set to:\t%.2f\n\r", \
+                            (float)((int32_t)pMessage->message / 6));
+                        break;
+                    case posOut:
+                        pc.printf("Current position:\t%.2f\n\r", \
+                            (float)((int32_t)pMessage->message / 6));
+                        break;
+                    case error:
+                        pc.printf("Debugging position:%x\n\r", pMessage->message);
+                        break;
+                    default:
+                        pc.printf("Unknown Error. Message: %x\n\r", pMessage->message);
+                        break;
+                }
+                mailStack.free(pMessage);
+            }
+        } 
+
+        
+        //TODO: stop function, maybe use parent deconstructor
+        //void stop_comm{}
+
+    public: 
     
-    motorOut((currentState - offset + lead + 6) % 6);
-}
+        Comm(): pc(SERIAL_TX, SERIAL_RX), T_(){ // inherit from the RawSerial constructor
+            
+            MAXCMDLENGTH = 18;
+            newCmd[MAXCMDLENGTH] = '0';
+            cmdIndx = 0;
+
+            motorPower = 300;
+            targetVel = 45.0;
+            targetRot = 459.0;
+        }
+        
+        
+        void putMessage(msgType type, uint32_t message){
+            msg *p_msg = mailStack.alloc();
+            p_msg->type = type;
+            p_msg->message = message;
+            mailStack.put(p_msg);
+        }
+        
+       void start_comm(){
+            p_comm_in->start(callback(this, &Comm::commInFn));
+            p_comm_out->start(callback(this, &Comm::commOutFn));
+
+            _RUN = true;
+        }
+};
+
 
 //Main
 int main() {
-    //Initialise the serial port
-     Serial pc(SERIAL_TX, SERIAL_RX);
-     pc.printf("Hello\n\r");
-    
-//    std::ios::sync_with_stdio(false);
+
+   // std::ios::sync_with_stdio(false);
     SHA256::SHA256 Miner;
     
     uint8_t sequence[] = {0x45,0x6D,0x62,0x65,0x64,0x64,0x65,0x64,
@@ -140,17 +390,21 @@
     int8_t currentState = 0;    //Rotot offset at motor state 0
     int8_t stateList[6];    //Rotot offset at motor state 0
     //Run the motor synchronisation
-    orState = motorHome();
+
+
+    Motor motor;
+    Motor* p_motor = &motor;
+    orState = p_motor->motorHome();
     
     // Add callbacks
-//    I1.fall(&stateUpdate);
-//    I2.fall(&stateUpdate);
-//    I3.fall(&stateUpdate);
+   // I1.fall(&stateUpdate);
+   // I2.fall(&stateUpdate);
+   // I3.fall(&stateUpdate);
     int8_t* params[2];
     params[0] = &currentState;
     params[1] = &orState;
     
-    I1.fall(callback(&stateUpdate,params));
+    I1.fall(callback(*(p_motor->stateUpdate),params));
     I2.fall(callback(&stateUpdate,params));
     I3.fall(callback(&stateUpdate,params));
     
@@ -162,31 +416,31 @@
     currentState = readRotorState();
     motorOut((currentState-orState+lead+6)%6); // We push it digitally
     
-    // pc.printf("Rotor origin: %x\n\r",orState);
-    // orState is subtracted from future rotor state inputs to align rotor and motor states
-    // intState = readRotorState();
-    //if (intState != intStateOld) {
-//        pc.printf("old:%d \t new:%d \t next:%d \n\r",intStateOld, intState, (intState-orState+lead+6)%6);
-//        intStateOld = intState;
-//        motorOut((intState-orState+lead+6)%6); //+6 to make sure the remainder is positive
-//    }
+    pc.printf("Rotor origin: %x\n\r",orState);
+    orState is subtracted from future rotor state inputs to align rotor and motor states
+    intState = readRotorState();
+    if (intState != intStateOld) {
+       pc.printf("old:%d \t new:%d \t next:%d \n\r",intStateOld, intState, (intState-orState+lead+6)%6);
+       intStateOld = intState;
+       motorOut((intState-orState+lead+6)%6); //+6 to make sure the remainder is positive
+   }
 
 
     // Keep the program running indefinitely
     timer.start();          // start timer
     int stateCount = 0;
     while (1) {
-//        pc.printf("Current:%d \t Next:%d \n\r", currentState, (currentState-orState+lead+6)%6);
+       pc.printf("Current:%d \t Next:%d \n\r", currentState, (currentState-orState+lead+6)%6);
         Miner.computeHash(hash, sequence, length64);
         hashCounter++;
         if ((hash[0]==0) && (hash[1]==0)){
-            pc.printf("hash: ");
-            for(int i = 0; i < 32; ++i)
-                pc.printf("%02x", hash[i]);
-            pc.printf("\n\r");
+            //pc.printf("hash: ");
+            //for(int i = 0; i < 32; ++i)
+                //pc.printf("%02x", hash[i]);
+            //pc.printf("\n\r");
         }
 
-        // Try a new nonce
+        // // Try a new nonce
         (*nonce)++;
 
         if (stateCount<6){
@@ -194,23 +448,19 @@
             stateCount++;
         }
         else {
-            pc.printf("states");
-            for(int i = 0; i < 6; ++i)
-                pc.printf("%02i,", stateList[i]);
-            pc.printf("\n\r");    
+            //pc.printf("states");
+            //for(int i = 0; i < 6; ++i)
+                //pc.printf("%02i,", stateList[i]);
+            //pc.printf("\n\r");    
             stateCount = 0;        
         }
 
-        // Per Second i.e. when greater or equal to 1
+        // // Per Second i.e. when greater or equal to 1
         if (timer.read() >= 1){
-            pc.printf("HashRate = %02u \n\r",hashCounter);
+            //pc.printf("HashRate = %02u \n\r",hashCounter);
             hashCounter=0;
             timer.reset();
         }
     }
   
-}
-
-
-
-
+}
\ No newline at end of file