![](/media/cache/group/default_image.jpg.50x50_q85.jpg)
Callum and Adel's changes on 12/02/19
Dependencies: Crypto
Diff: main.cpp
- 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] = ¤tState; 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