Embedded System CW2

Dependencies:   Crypto_light mbed-rtos mbed

Fork of ES_CW2_Starter by Edward Stott

Files at this revision

API Documentation at this revision

Comitter:
ylx15
Date:
Fri Mar 23 20:39:06 2018 +0000
Parent:
3:569b35e2a602
Commit message:

Changed in this revision

Crypto_light.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Crypto_light.lib	Fri Mar 23 20:39:06 2018 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/users/estott/code/Crypto_light/#634f9c4cbab1
--- a/main.cpp	Thu Mar 01 09:41:46 2018 +0000
+++ b/main.cpp	Fri Mar 23 20:39:06 2018 +0000
@@ -1,4 +1,7 @@
 #include "mbed.h"
+#include "SHA256.h"
+#include "rtos.h"
+#include <algorithm>
 
 //Photointerrupter input pins
 #define I1pin D2
@@ -37,44 +40,167 @@
 //const int8_t stateMap[] = {0x07,0x01,0x03,0x02,0x05,0x00,0x04,0x07}; //Alternative if phase order of input or drive is reversed
 
 //Phase lead to make motor spin
-const int8_t lead = 2;  //2 for forwards, -2 for backwards
+int8_t lead = 2;  //2 for forwards, -2 for backwards. (used to be const)
 
 //Status LED
 DigitalOut led1(LED1);
 
 //Photointerrupter inputs
-DigitalIn I1(I1pin);
-DigitalIn I2(I2pin);
-DigitalIn I3(I3pin);
+InterruptIn I1(I1pin);
+InterruptIn I2(I2pin);
+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);
 
+
+////////////////////////////////////////////////////////// Print to serial port
+
+//Class Mail
+typedef struct{
+    char label1;
+    char label2;
+    uint8_t code;
+    uint32_t data;
+}   message_t;
+Mail<message_t, 16> outMessages;
+
+//Add message to the queue
+void putMessage(char label1, char label2, uint8_t code, uint32_t data) {
+    message_t *pMessage = outMessages.alloc();
+    pMessage->label1 = label1;
+    pMessage->label2 = label2;
+    pMessage->code = code;
+    pMessage->data = data;
+    outMessages.put(pMessage);
+}
+
+//Initialise the serial port
+RawSerial pc(SERIAL_TX, SERIAL_RX);
+
+Thread commOutT(osPriorityHigh,1024);
+
+void commOutFn(){
+    while (1){
+        // wait for a message to be available in the queue from outmessage
+        osEvent newEvent = outMessages.get();   
+        message_t *pMessage= (message_t*)newEvent.value.p;
+        if ((pMessage -> code == 2) || (pMessage -> code == 9)){
+            // output hex values only for bitcoin key and nonce
+            pc.printf("Message %d with data 0x%016x\n\r", pMessage -> code, pMessage -> data);
+        }else{
+            pc.printf("Message %d : %c - %c with data %i\n\r", pMessage -> code, pMessage ->label1, pMessage->label2, pMessage -> data);
+        }
+        outMessages.free(pMessage); // empty previously allocated memory
+    }
+}
+
+////////////////////////////////////////////////////////////////////// Decoding
+//Initialize variables
+Mutex newKey_mutex;
+volatile uint64_t newKey = 0;
+// where possible make integers of size less than 32 to assure atomic access
+volatile uint32_t motorPower = 1000; 
+volatile int32_t newVelocity = 0;
+volatile int32_t desiredPosition = 0;
+volatile int32_t desiredRotations = 0;
+
+Queue<void, 8> inCharQ; 
+
+int32_t motorPosition;
+
+// serialISR receive each incoming byte and place it in the queue
+void serialISR(){
+    // receive incoming byte. called to prevent the interrupt from retriggering
+    uint8_t newChar = pc.getc();    
+    inCharQ.put((void*)newChar); // place it in a queue
+}
+
+// Code for the decoding thread
+const uint8_t arr_size = 25;
+char newCmd [arr_size]; // create array large enough -> depends on commands
+uint8_t buffPosition = 0;
+
+Thread ReceiveBytesT(osPriorityNormal,1024);
+
+void ReceiveBytesFn(){
+    pc.attach(&serialISR);
+    while(1) {
+        osEvent newEvent = inCharQ.get();
+        uint8_t newChar = (uint8_t)newEvent.value.p;
+        
+        if (buffPosition < arr_size) {
+            // determine when the command is finished
+            if (newChar == '\r'){   // equivalent of the enter key
+                newCmd[buffPosition] = '\0';    // signs the end for sscanf
+                
+                //Bitcoin Key
+                if (newCmd[0]=='K'){
+                    newKey_mutex.lock();
+                    //decode the command and set the new key value 
+                    sscanf(newCmd, "K%x", &newKey); 
+                    newKey_mutex.unlock();
+                }
+                
+                //Set motor Torque/ motorPwer
+                if (newCmd[0]=='T'){          
+                    // no need for mutex because uint32_t access is atomic
+                    sscanf(newCmd, "T%i", &motorPower);  
+                }
+                
+                //Set rotational speed
+                if (newCmd[0]=='V'){        
+                    sscanf(newCmd, "V%i", &newVelocity);
+                }   
+                
+                //Set Position Control
+                if (newCmd[0]=='P'){        
+                    sscanf(newCmd, "P%i", &desiredPosition);
+                } 
+                
+                //Set Rotation Control
+                if (newCmd[0]=='R'){        
+                    sscanf(newCmd, "R%i", &desiredRotations);
+                    desiredPosition = motorPosition + desiredRotations*6;
+                } 
+                
+                buffPosition = 0;   // reset the buff position
+            }
+            else{
+                newCmd[buffPosition] = newChar;
+                buffPosition++;
+            }
+        }  
+    }
+}
+
+///////////////////////////////////////////////////////////////// Motor Control
+
 //Set a given drive state
-void motorOut(int8_t driveState){
+void motorOut(int8_t driveState, uint32_t motor_torque){
     
     //Lookup the output byte from the drive state.
     int8_t driveOut = driveTable[driveState & 0x07];
       
     //Turn off first
-    if (~driveOut & 0x01) L1L = 0;
+    if (~driveOut & 0x01) L1L.pulsewidth_us(0);
     if (~driveOut & 0x02) L1H = 1;
-    if (~driveOut & 0x04) L2L = 0;
+    if (~driveOut & 0x04) L2L.pulsewidth_us(0);
     if (~driveOut & 0x08) L2H = 1;
-    if (~driveOut & 0x10) L3L = 0;
+    if (~driveOut & 0x10) L3L.pulsewidth_us(0);
     if (~driveOut & 0x20) L3H = 1;
     
     //Then turn on
-    if (driveOut & 0x01) L1L = 1;
+    if (driveOut & 0x01) L1L.pulsewidth_us(motor_torque);
     if (driveOut & 0x02) L1H = 0;
-    if (driveOut & 0x04) L2L = 1;
+    if (driveOut & 0x04) L2L.pulsewidth_us(motor_torque);
     if (driveOut & 0x08) L2H = 0;
-    if (driveOut & 0x10) L3L = 1;
+    if (driveOut & 0x10) L3L.pulsewidth_us(motor_torque);
     if (driveOut & 0x20) L3H = 0;
     }
     
@@ -86,21 +212,139 @@
 //Basic synchronisation routine    
 int8_t motorHome() {
     //Put the motor in drive state 0 and wait for it to stabilise
-    motorOut(0);
+    motorOut(0, 1000);
     wait(2.0);
     
     //Get the rotor state
     return readRotorState();
 }
+int8_t orState = 0;    //Rotot offset at motor state 0 
+
+volatile float ys = 0;
+volatile float yr = 0;
+volatile float y_tmp = 0;
+volatile int32_t v = 0;
+
+void motorISR(){
     
+    // choose between ys and yr according to the positions
+    if (v>=0){
+        if(min(ys,yr)==yr){
+            y_tmp = yr;
+        }else{
+            y_tmp = ys;
+        }
+    }else{
+        if(max(ys,yr)==yr){
+            y_tmp = yr;
+        }else{
+            y_tmp = ys;
+        }
+    }
+    
+    
+    // V0 overrides everything
+    if ((abs(y_tmp) > 1000)||(newVelocity == 0)){
+        motorPower = 1000;    
+    }else{
+        motorPower = abs(y_tmp);
+    }
+    if ((y_tmp>=0)||(newVelocity ==0)){
+        lead = 2;
+    }
+    else {
+        lead = -2;
+    }
+    
+    
+    // a count of 6 will equal one revolution
+    static int8_t oldRotorState;
+    int8_t rotorState = readRotorState();
+    motorOut((rotorState-orState+lead+6)%6, motorPower);
+    if (rotorState - oldRotorState == 5) motorPosition--;
+    else if (rotorState - oldRotorState == -5) motorPosition++;
+    else motorPosition += (rotorState - oldRotorState);
+    oldRotorState = rotorState;
+
+}
+
+
+
+Thread motorCtrlT (osPriorityNormal,512);   // 1024 too big 
+
+void motorCtrlTick(){
+    motorCtrlT.signal_set(0x1); 
+}
+    
+void motorCtrlFn(){
+    int32_t motorposition_old = 0;
+    int32_t v_calc_counter = 0;
+    int32_t kp = 23;
+    int32_t kd = 18;
+    int32_t localMotorPosition = 0;
+    int32_t localDesiredPosition = 0;
+    int32_t local_s = 0;
+    int32_t Er = 0;
+    int32_t Er_old = 0;
+    int32_t dErdt = 0;
+    
+    Ticker motorCtrlTicker; 
+    motorCtrlTicker.attach_us(&motorCtrlTick,100000);   // 100ms = 100000us
+    while(1){
+        Timer t;
+        t.start();
+        motorCtrlT.signal_wait(0x1); // from here onward it executes once 0.1s
+        
+        // make local copies to compute computation 
+        // becasue these variables can be updated at anytime
+        localDesiredPosition = desiredPosition;
+        localMotorPosition = motorPosition; 
+        local_s = newVelocity;
+        Er = localDesiredPosition-localMotorPosition;
+        
+        // below is the velocity per second since this runs every 0.1s
+        v = (localMotorPosition-motorposition_old)/(6*t.read());
+        dErdt = (Er-Er_old)/t.read(); 
+        t.reset();
+        
+        motorposition_old = localMotorPosition;
+        Er_old = Er;
+        
+        v_calc_counter ++;
+
+        if (v_calc_counter >= 10){
+            //putMessage('c','v',3, v);   //current velocity
+            v_calc_counter = 0;
+        }
+        
+        yr = kp*Er + kd*dErdt;
+        
+        // there were problems with the function abs(). use if-else instead
+        if (v>=0){
+            if (Er >= 0){
+                ys = kp*(local_s - v);
+            }else{
+                ys = -1*kp*(local_s - v);
+            }
+        }else{
+            if (Er >= 0){
+                ys = kp*(local_s + v);
+            }else{
+                ys = -1*kp*(local_s + v);
+            }
+        }
+
+    }
+}
+
+
 //Main
 int main() {
-    int8_t orState = 0;    //Rotot offset at motor state 0
-    int8_t intState = 0;
-    int8_t intStateOld = 0;
     
-    //Initialise the serial port
-    Serial pc(SERIAL_TX, SERIAL_RX);
+    L1L.period_us(2000);
+    L2L.period_us(2000);
+    L3L.period_us(2000);
+    
     pc.printf("Hello\n\r");
     
     //Run the motor synchronisation
@@ -108,13 +352,56 @@
     pc.printf("Rotor origin: %x\n\r",orState);
     //orState is subtracted from future rotor state inputs to align rotor and motor states
     
+    I1.rise(&motorISR);
+    I1.fall(&motorISR);
+    I2.rise(&motorISR);
+    I2.fall(&motorISR);
+    I3.rise(&motorISR);
+    I3.fall(&motorISR);
+    
+    commOutT.start(commOutFn); 
+    ReceiveBytesT.start(ReceiveBytesFn);
+    motorCtrlT.start(motorCtrlFn);
+    
+    SHA256 tmp;
+      
+    uint8_t sequence[] = {0x45,0x6D,0x62,0x65,0x64,0x64,0x65,0x64,0x20,0x53,0x79,0x73,0x74,0x65,0x6D,0x73,0x20,0x61,0x72,0x65,0x20,0x66,0x75,0x6E,0x20,0x61,0x6E,0x64,0x20,0x64,0x6F,0x20,0x61,0x77,0x65,0x73,0x6F,0x6D,0x65,0x20,0x74,0x68,0x69,0x6E,0x67,0x73,0x21,0x20,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint64_t* key = (uint64_t*)((int)sequence + 48);
+    uint64_t* nonce = (uint64_t*)((int)sequence + 56);
+    uint8_t hash[32];
+    
+    Timer t;
+    t.start();
+    uint32_t hashcount = 0;
+    
     //Poll the rotor state and set the motor outputs accordingly to spin the motor
     while (1) {
-        intState = readRotorState();
-        if (intState != intStateOld) {
-            intStateOld = intState;
-            motorOut((intState-orState+lead+6)%6); //+6 to make sure the remainder is positive
+        newKey_mutex.lock();
+        *key = newKey;
+        newKey_mutex.unlock();
+        
+        tmp.computeHash(hash, sequence, 64);
+        *nonce = *nonce + 1;
+        // increase the hashcount after every computeHash
+        hashcount ++;
+
+                 
+        if (t.read()>=1){
+            putMessage('H','R',1, hashcount);   // hash rate per second
+            hashcount = 0;
+            t.reset();
+            putMessage('c','v',3, v);   //current velocity in rotation per second
+            putMessage('T','V',4, newVelocity); // Target Velocity in rotation per second
+            putMessage('c','p',5, motorPosition);   // current position 
+            putMessage('T','P',6, desiredPosition); // Target Position
+            //putMessage('K','K',9, *key);
         }
+        
+        if ((hash[0]==0)&&(hash[1]==0)){
+            putMessage('B','N',2,*nonce);   // Bitcoin Nonce 
+        }
+
+        
     }
-}
-
+    
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Fri Mar 23 20:39:06 2018 +0000
@@ -0,0 +1,1 @@
+http://os.mbed.com/users/mbed_official/code/mbed-rtos/#5713cbbdb706
--- a/mbed.bld	Thu Mar 01 09:41:46 2018 +0000
+++ b/mbed.bld	Fri Mar 23 20:39:06 2018 +0000
@@ -1,1 +1,1 @@
-https://os.mbed.com/users/mbed_official/code/mbed/builds/7130f322cb7e
\ No newline at end of file
+https://os.mbed.com/users/mbed_official/code/mbed/builds/5571c4ff569f
\ No newline at end of file