andrewm@268: /* andrewm@268: * render.cpp andrewm@268: * andrewm@268: * Created on: Oct 24, 2014 andrewm@268: * Author: parallels andrewm@268: */ andrewm@268: andrewm@268: giuliomoro@301: #include andrewm@268: #include andrewm@268: andrewm@268: const int kStepLengthSlow = 1000; andrewm@268: const int kStepLengthFast = 500; andrewm@268: andrewm@268: int gStepLengthSamples = kStepLengthSlow; andrewm@268: andrewm@268: const int gPinA1 = P8_27; andrewm@268: const int gPinA2 = P8_28; andrewm@268: const int gPinB1 = P8_29; andrewm@268: const int gPinB2 = P8_30; andrewm@268: const int gPinServo = P9_16; andrewm@268: andrewm@268: int gStepCounter = 0; andrewm@268: int gPhase = 0; andrewm@268: andrewm@268: int gServoCounter = 0; andrewm@268: andrewm@268: andrewm@268: enum { andrewm@268: kStateMoveRight1 = 0, andrewm@268: kStateMoveLeft1, andrewm@268: kStateMoveRight2, andrewm@268: kStateMoveLeft2, andrewm@268: kStateMoveRight3, andrewm@268: kStateMoveLeft3, andrewm@268: kStateSpin, andrewm@268: kStateMax andrewm@268: }; andrewm@268: andrewm@268: int gState = 0; andrewm@268: int gStateCounter = 0; andrewm@268: andrewm@268: // setup() is called once before the audio rendering starts. andrewm@268: // Use it to perform any initialisation and allocation which is dependent andrewm@268: // on the period size or sample rate. andrewm@268: // andrewm@268: // userData holds an opaque pointer to a data structure that was passed andrewm@268: // in from the call to initAudio(). andrewm@268: // andrewm@268: // Return true on success; returning false halts the program. andrewm@268: giuliomoro@301: bool setup(BelaContext *context, void *userData) andrewm@268: { andrewm@268: // This project makes the assumption that the audio and digital andrewm@268: // sample rates are the same. But check it to be sure! andrewm@268: if(context->audioFrames != context->digitalFrames) { andrewm@268: rt_printf("Error: this project needs the audio and digital sample rates to be the same.\n"); andrewm@268: return false; andrewm@268: } andrewm@268: andrewm@268: pinModeFrame(context, 0, gPinA1, OUTPUT); andrewm@268: pinModeFrame(context, 0, gPinA2, OUTPUT); andrewm@268: pinModeFrame(context, 0, gPinB1, OUTPUT); andrewm@268: pinModeFrame(context, 0, gPinB2, OUTPUT); andrewm@268: pinModeFrame(context, 0, gPinServo, OUTPUT); andrewm@268: andrewm@268: return true; andrewm@268: } andrewm@268: andrewm@268: // render() is called regularly at the highest priority by the audio engine. andrewm@268: // Input and output are given from the audio hardware and the other andrewm@268: // ADCs and DACs (if available). If only audio is available, numMatrixFrames andrewm@268: // will be 0. andrewm@268: giuliomoro@301: void render(BelaContext *context, void *userData) andrewm@268: { andrewm@268: for(unsigned int n = 0; n < context->audioFrames; n++) { andrewm@268: if(gPhase == 0 || gPhase == 1) { andrewm@268: digitalWriteFrameOnce(context, n, gPinB1, HIGH); andrewm@268: digitalWriteFrameOnce(context, n, gPinB2, LOW); andrewm@268: } andrewm@268: else { andrewm@268: digitalWriteFrameOnce(context, n, gPinB1, LOW); andrewm@268: digitalWriteFrameOnce(context, n, gPinB2, HIGH); andrewm@268: } andrewm@268: andrewm@268: if(gPhase == 1 || gPhase == 2) { andrewm@268: digitalWriteFrameOnce(context, n, gPinA1, HIGH); andrewm@268: digitalWriteFrameOnce(context, n, gPinA2, LOW); andrewm@268: } andrewm@268: else { andrewm@268: digitalWriteFrameOnce(context, n, gPinA1, LOW); andrewm@268: digitalWriteFrameOnce(context, n, gPinA2, HIGH); andrewm@268: } andrewm@268: andrewm@268: if(--gServoCounter > 0) andrewm@268: digitalWriteFrameOnce(context, n, gPinServo, HIGH); andrewm@268: else andrewm@268: digitalWriteFrameOnce(context, n, gPinServo, LOW); andrewm@268: andrewm@268: if(++gStepCounter >= gStepLengthSamples) { andrewm@268: gStateCounter++; andrewm@268: andrewm@268: switch(gState) { andrewm@268: case kStateMoveRight1: andrewm@268: case kStateMoveRight2: andrewm@268: case kStateMoveRight3: andrewm@268: gPhase = (gPhase + 1) & 3; andrewm@268: break; andrewm@268: case kStateMoveLeft1: andrewm@268: case kStateMoveLeft2: andrewm@268: case kStateMoveLeft3: andrewm@268: gPhase = (gPhase + 3) & 3; andrewm@268: break; andrewm@268: case kStateSpin: andrewm@268: gPhase = (gPhase + 1) & 3; andrewm@268: break; andrewm@268: } andrewm@268: andrewm@268: if(gState == kStateSpin) { andrewm@268: if(gStateCounter >= 48) { andrewm@268: gStateCounter = 0; andrewm@268: gState = 0; andrewm@268: gStepLengthSamples = kStepLengthSlow; andrewm@268: } andrewm@268: } andrewm@268: else { andrewm@268: if(gStateCounter >= 16) { andrewm@268: gStateCounter = 0; andrewm@268: gState++; andrewm@268: if(gState & 1) andrewm@268: gServoCounter = 120; andrewm@268: else andrewm@268: gServoCounter = 80; andrewm@268: if(gState == kStateSpin) andrewm@268: gStepLengthSamples = kStepLengthFast; andrewm@268: } andrewm@268: } andrewm@268: andrewm@268: gStepCounter = 0; andrewm@268: } andrewm@268: } andrewm@268: } andrewm@268: andrewm@268: // cleanup() is called once at the end, after the audio has stopped. andrewm@268: // Release any resources that were allocated in setup(). andrewm@268: giuliomoro@301: void cleanup(BelaContext *context, void *userData) andrewm@268: { andrewm@268: andrewm@268: }