This project is the first winner on 2020 NXP Cup Electromaker Innovation Challenge contest.
This code should supply all functions to control all peripherals from main code and get all informations from all sensors.
Code:
#ifndef __TFC_H__ #define __TFC_H__ #include "fsl_ftm.h" #include "fsl_i2c.h" #include "fsl_adc16.h" #include "fsl_pit.h" #include "fsl_uart.h" #include "fsl_dspi.h" #define SERVO_MODULO 9375 // (ftmClock / pwmFreq_Hz) - 1 volatile unsigned int servoPos = 0; // access this variable to set servo pos volatile unsigned int laserPos = 655; void setupServo(int startupVal) { servoPos = 700 + startupVal; ftm_config_t ftmConfig; FTM_GetDefaultConfig(&ftmConfig); ftmConfig.prescale = kFTM_Prescale_Divide_128; FTM_Init(FTM0, &ftmConfig); FTM0->SC &= ~FTM_SC_CPWMS_MASK; FTM0->MOD = SERVO_MODULO; /* Clear the current mode and edge level bits */ uint32_t reg = FTM0->CONTROLS[1].CnSC; reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level */ reg |= (uint32_t)kFTM_HighTrue << FTM_CnSC_ELSA_SHIFT; /* Edge-aligned mode needs MSB to be 1, don't care for Center-aligned mode */ reg |= FTM_CnSC_MSB(1U); /* Update the mode and edge level */ FTM0->CONTROLS[1].CnSC = reg; FTM0->CONTROLS[1].CnV = servoPos; /* Clear the current mode and edge level bits */ reg = FTM0->CONTROLS[2].CnSC; reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level */ reg |= (uint32_t)kFTM_HighTrue << FTM_CnSC_ELSA_SHIFT; /* Edge-aligned mode needs MSB to be 1, don't care for Center-aligned mode */ reg |= FTM_CnSC_MSB(1U); /* Update the mode and edge level */ FTM0->CONTROLS[2].CnSC = reg; FTM0->CONTROLS[2].CnV = servoPos; FTM0->SC |= FTM_SC_TOIE_MASK; // enable FTM0 overflow iterrupt PORTC->PCR[2] = PORT_PCR_MUX(4); PORTC->PCR[3] = PORT_PCR_MUX(4); FTM_StartTimer(FTM0, kFTM_SystemClock); NVIC_EnableIRQ(FTM0_IRQn); FTM_EnableInterrupts(FTM0, kFTM_TimeOverflowInterruptEnable); } char getLaserState() { // TODO return 0; } void setServoPos(int pos) { servoPos = 700 + pos; } void setLaserPos(unsigned int pos) { laserPos = pos; } /*extern */volatile short noSee; char isLaserDecreasing = 0; char isLaserSearching = 0; volatile char isObstacleUpdated = 0; volatile int obstaclePos = 0; volatile int endObstaclePos = 0; volatile int obstacleSize = 0; volatile char isObtacleHere = 0; char __laserColisonStarted = 0; int __laserColisionBegin = 0; extern "C" { void FTM0_IRQHandler(void) { if(!(FTM0->SC&FTM_SC_TOF_MASK)) return; FTM0->SC &= ~(FTM_SC_TOF_MASK); FTM0->CONTROLS[1].CnV = servoPos; if(isLaserSearching) { char currentLaserState = getLaserState(); if(!__laserColisonStarted && currentLaserState) { __laserColisonStarted = 1; __laserColisionBegin = laserPos; isObtacleHere = 1; } else if(__laserColisonStarted && !currentLaserState) { __laserColisonStarted = 0; isLaserDecreasing = !isLaserDecreasing; isObstacleUpdated = 1; isObtacleHere = 1; obstacleSize = __laserColisionBegin - laserPos; if(obstacleSize<0) { obstacleSize = -obstacleSize; } obstacleSize >>= 1; //obstaclePos = __laserColisionBegin + laserPos; int middleDistanceOld = __laserColisionBegin - 543; int middleDistanceNew = laserPos - 543; if(middleDistanceOld<0) middleDistanceOld = -middleDistanceOld; if(middleDistanceNew<0) middleDistanceNew = -middleDistanceNew; if(middleDistanceOld<middleDistanceNew) { obstaclePos = __laserColisionBegin<<1; endObstaclePos = laserPos; } else { obstaclePos = laserPos<<1; endObstaclePos = __laserColisionBegin; } obstaclePos >>= 1; obstaclePos -= 543; // based on servo middle obstaclePos = -obstaclePos; endObstaclePos -= 543; // based on servo middle endObstaclePos = -obstaclePos; } if(!isLaserDecreasing) { if(__laserColisonStarted) { laserPos += 20; } else { laserPos += 3; //30; } } else { if(__laserColisonStarted) { laserPos -= 20; } else { laserPos -= 3; //30; } } // https://servodatabase.com/servo/towerpro/sg90 // 0,5ms to 2,5ms if(laserPos<=187) { // 187 isLaserDecreasing = 0; if(__laserColisonStarted) { __laserColisonStarted = 0; isObstacleUpdated = 1; isObtacleHere = 1; obstacleSize = __laserColisionBegin - laserPos; if(obstacleSize<0) { obstacleSize = -obstacleSize; } obstacleSize >>= 1; //obstaclePos = __laserColisionBegin + laserPos; int middleDistanceOld = __laserColisionBegin - 543; int middleDistanceNew = laserPos - 543; if(middleDistanceOld<0) middleDistanceOld = -middleDistanceOld; if(middleDistanceNew<0) middleDistanceNew = -middleDistanceNew; if(middleDistanceOld<middleDistanceNew) { obstaclePos = __laserColisionBegin<<1; endObstaclePos = laserPos; } else { obstaclePos = laserPos<<1; endObstaclePos = __laserColisionBegin; } obstaclePos >>= 1; obstaclePos -= 543; // based on servo middle obstaclePos = -obstaclePos; endObstaclePos -= 543; // based on servo middle endObstaclePos = -obstaclePos; } else { isObtacleHere = 0; obstacleSize = 0; obstaclePos = 0; endObstaclePos = 0; } } else if(laserPos>=900) { // 938 isLaserDecreasing = 1; if(__laserColisonStarted) { __laserColisonStarted = 0; isObstacleUpdated = 1; isObtacleHere = 1; obstacleSize = __laserColisionBegin - laserPos; if(obstacleSize<0) { obstacleSize = -obstacleSize; } obstacleSize>>=1; //obstaclePos = __laserColisionBegin + laserPos; int middleDistanceOld = __laserColisionBegin - 543; int middleDistanceNew = laserPos - 543; if(middleDistanceOld<0) middleDistanceOld = -middleDistanceOld; if(middleDistanceNew<0) middleDistanceNew = -middleDistanceNew; if(middleDistanceOld<middleDistanceNew) { obstaclePos = __laserColisionBegin<<1; endObstaclePos = laserPos; } else { obstaclePos = laserPos<<1; endObstaclePos = __laserColisionBegin; } obstaclePos >>= 1; obstaclePos -= 543; // based on servo middle obstaclePos = -obstaclePos; endObstaclePos -= 543; // based on servo middle endObstaclePos = -obstaclePos; } else { isObtacleHere = 0; obstacleSize = 0; obstaclePos = 0; endObstaclePos = 0; } } } FTM0->CONTROLS[2].CnV = laserPos; // we set servo at right time to prevent bad output FTM0->SYNC |= 1 << 7; // trigger SW sync noSee++; } } namespace Motor { const unsigned int MOTOR_MODULO = 1000; volatile int rMotorSpeed = 0; volatile int lMotorSpeed = 0; void initMotorChannel(int channel) { /* Clear the current mode and edge level bits */ uint32_t reg = FTM3->CONTROLS[channel].CnSC; reg &= ~(FTM_CnSC_MSA_MASK | FTM_CnSC_MSB_MASK | FTM_CnSC_ELSA_MASK | FTM_CnSC_ELSB_MASK); /* Setup the active level */ reg |= (uint32_t)(kFTM_HighTrue << FTM_CnSC_ELSA_SHIFT); /* Edge-aligned mode needs MSB to be 1, don't care for Center-aligned mode */ reg |= FTM_CnSC_MSB(1U); /* Update the mode and edge level */ FTM3->CONTROLS[channel].CnSC = reg; } void setup() { ftm_config_t ftmConfig; FTM_GetDefaultConfig(&ftmConfig); ftmConfig.prescale = kFTM_Prescale_Divide_64; FTM_Init(FTM3, &ftmConfig); FTM3->SC &= ~FTM_SC_CPWMS_MASK; FTM3->MOD = MOTOR_MODULO; // MOTOR R: ch4, ch5 // MOTOR L: ch1, ch0 initMotorChannel(0); initMotorChannel(1); initMotorChannel(4); initMotorChannel(5); ftm_chnl_pwm_signal_param_t pwmPar; pwmPar.chnlNumber = kFTM_Chnl_0; pwmPar.dutyCyclePercent = 0; pwmPar.enableDeadtime = false; pwmPar.firstEdgeDelayPercent = 0; pwmPar.level = kFTM_HighTrue; FTM_SetupPwm(FTM3, &pwmPar, 1, kFTM_EdgeAlignedPwm, 1000, 60000000); //int startupVal = MOTOR_MODULO >> 1; // MOTOR_MODULO / 2 for ability of back riding; 0 for forward only; MOTOR_MODULO for backward only FTM3->CONTROLS[1].CnV = 0; FTM3->CONTROLS[0].CnV = 0; FTM3->CONTROLS[4].CnV = 0; FTM3->CONTROLS[5].CnV = 0; FTM_StartTimer(FTM3, kFTM_SystemClock); PORTD->PCR[0] = PORT_PCR_MUX(4); PORTD->PCR[1] = PORT_PCR_MUX(4); PORTC->PCR[8] = PORT_PCR_MUX(3); PORTC->PCR[9] = PORT_PCR_MUX(3); FTM_StartTimer(FTM3, kFTM_SystemClock); NVIC_EnableIRQ(FTM3_IRQn); FTM_EnableInterrupts(FTM3, kFTM_TimeOverflowInterruptEnable); } inline void setLMotorSpeed(int speed) { lMotorSpeed = speed; } inline void setRMotorSpeed(int speed) { rMotorSpeed = speed; } }; extern "C" { void FTM3_IRQHandler() { // we need FTM3 interrupt, to update CnV to fix double update if(!(FTM3->SC&FTM_SC_TOF_MASK)) return; FTM3->SC &= ~(FTM_SC_TOF_MASK); int lSpeed = Motor::lMotorSpeed; if(lSpeed >= 0) { FTM3->CONTROLS[1].CnV = lSpeed; FTM3->CONTROLS[0].CnV = 0; } else { FTM3->CONTROLS[1].CnV = 0; FTM3->CONTROLS[0].CnV = -lSpeed; } int rSpeed = Motor::rMotorSpeed; if(rSpeed >= 0) { FTM3->CONTROLS[4].CnV = rSpeed; FTM3->CONTROLS[5].CnV = 0; } else { FTM3->CONTROLS[4].CnV = 0; FTM3->CONTROLS[5].CnV = -rSpeed; } FTM3->SYNC |= 1 << 7; // trigger SW sync } } void init_ADC16(void){ adc16_config_t config; ADC16_GetDefaultConfig(&config); config.resolution = kADC16_ResolutionSE10Bit; config.enableHighSpeed = true; ADC16_Init(ADC0, &config); ADC16_DoAutoCalibration(ADC0); } volatile unsigned char cameraPulseState = 0; volatile unsigned char generateSI = 0; volatile unsigned int cameraScanTime = 50000; volatile unsigned char currentCameraSwapBuffer = 0; volatile unsigned short cameraData[2][128]; // 2 swap buffers volatile unsigned char isCameraBufferReady[2] = {0}; volatile char isCameraPeriodReady = 0; volatile unsigned char cameraPeriodWriteCount[2]; inline void enablePIT(pit_chnl_t channel, uint32_t count) { PIT_StopTimer(PIT, channel); PIT_DisableInterrupts(PIT, channel, kPIT_TimerInterruptEnable); PIT_SetTimerPeriod(PIT, channel, count); PIT_StartTimer(PIT, channel); PIT_EnableInterrupts(PIT, channel, kPIT_TimerInterruptEnable); EnableIRQ(PIT0_IRQn); EnableIRQ(PIT1_IRQn); EnableIRQ(PIT2_IRQn); EnableIRQ(PIT3_IRQn); } void setupCamera() { init_ADC16(); PORTB->PCR[2] = PORT_PCR_MUX(0); // Camera ADC PORTC->PCR[7] = PORT_PCR_MUX(1); // Camera CLK PORTC->PCR[0] = PORT_PCR_MUX(1); // Camera SI PORTB->PCR[3] = PORT_PCR_MUX(1);// (0) // Camera ADC2 // it will work as switch for stepper detector PORTB->PCR[3] = PORT_PCR_MUX(1) | (1 << 24); // GPIO GPIOB->PDDR &= ~(1 << 3); PORTD->PCR[3] = PORT_PCR_MUX(1); // Camera CLK2 PORTC->PCR[12] = PORT_PCR_MUX(1); // Camera SI2 GPIOC->PCOR |= 1 << 7; GPIOC->PCOR |= 1 << 0; GPIOD->PCOR |= 1 << 3; GPIOC->PCOR |= 1 << 12; GPIOC->PDDR |= 1 << 7; GPIOC->PDDR |= 1 << 0; GPIOD->PDDR |= 1 << 3; GPIOC->PDDR |= 1 << 12; pit_config_t pitConfig; pitConfig.enableRunInDebug = false; PIT_Init(PIT, &pitConfig); enablePIT(kPIT_Chnl_1, cameraScanTime); enablePIT(kPIT_Chnl_0, 600000); // 100x per second } volatile unsigned int time = 0; char antiFlickerSyncType = 0; extern "C" { void PIT_CHANNEL_0_IRQHANDLER(void) { if(PIT->CHANNEL[0].TFLG & PIT_TFLG_TIF_MASK) { PIT->CHANNEL[0].TFLG = PIT_TFLG_TIF_MASK; for(int i=0; i<14; i++) { if(((cameraScanTime+8000)>>i)<600000) { // 26 if(antiFlickerSyncType != i) { antiFlickerSyncType = i; enablePIT(kPIT_Chnl_0, 600000<<i); } break; } } time += 1<<antiFlickerSyncType; isCameraPeriodReady = 1; GPIOC->PSOR |= 1 << 0; // set SI high GPIOC->PSOR |= 1 << 12; // set SI2 high for(int j=8; j!=0; --j) __asm("NOP"); // 4*3 clocks GPIOC->PSOR |= 1 << 7; // set clock high GPIOD->PSOR |= 1 << 3; // set clock2 high for(int j=8; j!=0; --j) __asm("NOP"); // 4*3 clocks GPIOC->PCOR |= 1 << 0; // set SI low GPIOC->PCOR |= 1 << 12; // set SI2 low for(int j=8; j!=0; --j) __asm("NOP"); // 4*3 clocks for(int i=0; i<18; ++i) { GPIOC->PCOR |= 1 << 7; // set clock low GPIOD->PCOR |= 1 << 3; // set clock2 low for(int j=8; j!=0; --j) __asm("NOP"); // 4*3 clocks GPIOC->PSOR |= 1 << 7; // set clock high GPIOD->PSOR |= 1 << 3; // set clock2 high for(int j=8; j!=0; --j) __asm("NOP"); // 4*3 clocks } enablePIT(kPIT_Chnl_1, cameraScanTime); for(int i=0; i<112; ++i) { GPIOC->PCOR |= 1 << 7; // set clock low GPIOD->PCOR |= 1 << 3; // set clock2 low for(int j=8; j!=0; --j) __asm("NOP"); // 4*3 clocks GPIOC->PSOR |= 1 << 7; // set clock high GPIOD->PSOR |= 1 << 3; // set clock2 high for(int j=8; j!=0; --j) __asm("NOP"); // 4*3 clocks } GPIOC->PCOR |= 1 << 7; // set clock low GPIOD->PCOR |= 1 << 3; // set clock2 low PIT->CHANNEL[1].TFLG = PIT_TFLG_TIF_MASK; } } } extern "C" { void PIT_CHANNEL_1_IRQHANDLER(void) { if(PIT->CHANNEL[1].TFLG & PIT_TFLG_TIF_MASK) { PIT->CHANNEL[1].TFLG = PIT_TFLG_TIF_MASK; // clear flag #ifndef CAMERA_AVERAGING enablePIT(kPIT_Chnl_1, 0xFFFFFFFF); #endif GPIOC->PSOR |= 1 << 0; // set SI high GPIOC->PSOR |= 1 << 12; // set SI2 high for(int j=15; j!=0; --j) __asm("NOP"); // 4*3 clocks GPIOC->PSOR |= 1 << 7; // set clock high GPIOD->PSOR |= 1 << 3; // set clock2 high for(int j=15; j!=0; --j) __asm("NOP"); // 4*5 clocks //ADC0_SC1A = AIEN_OFF | DIFF_SINGLE | ADC_SC1_ADCH(6); ADC0->SC1[0] = ADC_SC1_AIEN(0) | ADC_SC1_DIFF(0) | ADC_SC1_ADCH(12); GPIOC->PCOR |= 1 << 0; // set SI low GPIOC->PCOR |= 1 << 12; // set SI2 low for(int j=15; j!=0; --j) __asm("NOP"); // 4*3 clocks for(int i=0; i<128; ++i) { GPIOC->PCOR |= 1 << 7; // set clock low GPIOD->PCOR |= 1 << 3; // set clock2 low for(int j=15; j!=0; --j) __asm("NOP"); // 4*5 clocks while(!(ADC0->SC1[0] & ADC_SC1_COCO_MASK)); short temp = ADC0->R[0]; //temp -= 60; temp-=170; // 150 if(temp&0x800) { temp = 0; } temp = (temp*3)>>1; if(temp&0x700) { temp = 0xFF; } #ifdef CAMERA_AVERAGING if(cameraPeriodWriteCount[currentCameraSwapBuffer]) { cameraData[currentCameraSwapBuffer][i] += temp; } else { cameraData[currentCameraSwapBuffer][i] = temp; } #else cameraData[currentCameraSwapBuffer][i] = temp; #endif GPIOC->PSOR |= 1 << 7; // set clock high GPIOD->PSOR |= 1 << 3; // set clock2 high for(int j=15; j!=0; --j) __asm("NOP"); // 4*5 clocks ADC0->SC1[0] = ADC_SC1_AIEN(0) | ADC_SC1_DIFF(0) | ADC_SC1_ADCH(12); } isCameraBufferReady[currentCameraSwapBuffer] = 1; GPIOC->PCOR |= 1 << 7; // set clock low GPIOD->PCOR |= 1 << 3; // set clock2 low for(int j=15; j!=0; --j) __asm("NOP"); // 4*5 clocks GPIOC->PSOR |= 1 << 7; // set clock high GPIOD->PSOR |= 1 << 3; // set clock2 high for(int j=15; j!=0; --j) __asm("NOP"); // 4*5 clocks GPIOC->PCOR |= 1 << 7; // set clock low GPIOD->PCOR |= 1 << 3; // set clock2 low #ifdef CAMERA_AVERAGING cameraPeriodWriteCount[currentCameraSwapBuffer]++; #endif } } } // pointer obtained by getNextImage is valid till next call of getNextImage unsigned short* getNextImage() { // will return null if there is no image yet unsigned char oldBuffer = currentCameraSwapBuffer; if(isCameraBufferReady[oldBuffer] && isCameraPeriodReady) { // we need to change current buffer without changing current buffer // to value which is bigger than bufferCount - 1 currentCameraSwapBuffer ^= 1; isCameraBufferReady[oldBuffer] = 0; unsigned short* oldData = (unsigned short*)cameraData[oldBuffer]; #ifdef CAMERA_AVERAGING unsigned char writeCount = cameraPeriodWriteCount[oldBuffer]; for(int i = 0; i<128; i++) { oldData[i] = oldData[i]/writeCount; } cameraPeriodWriteCount[oldBuffer] = 0; #endif isCameraPeriodReady = 0; return oldData; } return 0; } // info about camera values, updated at call of calibrateCamera unsigned char cameraMinValue = 0; unsigned char cameraMaxValue = 0; unsigned char cameraMiddleValue = 0; void calibrateCamera(unsigned short* cameraData) { unsigned int minVal = 1020; unsigned int maxVal = 0; for(int j=125; j; j--) { unsigned short average = ((unsigned short)cameraData[j+0]) + ((unsigned short)cameraData[j+1]) + ((unsigned short)cameraData[j+2]) + ((unsigned short)cameraData[j+3]); if(average > maxVal ) { maxVal = average; } else if(average < minVal ) { minVal = average; } } if(minVal == 0 && maxVal == 1020) { return; } int middle = minVal + maxVal; if(middle < 8) middle = 8; cameraScanTime *= 1024.0f / (float)middle; } void cameraInitialCalibration() { for(int i=0; i<40;) { unsigned short* cameraData = getNextImage(); if(cameraData) { i++; calibrateCamera(cameraData); } } } void initI2C() { i2c_master_config_t config = { .enableMaster = true, .enableStopHold = false, .baudRate_Bps = 400000, .glitchFilterWidth = 0 }; I2C_MasterInit(I2C0, &config, 12000000U); PORTE->PCR[24] = PORT_PCR_MUX(5); PORTE->PCR[25] = PORT_PCR_MUX(5); } void setupIOExpander() { uint8_t data[] = { 6, 0b11111111, 0b10111111 }; // 1 = input, 0 = output i2c_master_transfer_t transfer; transfer.flags = kI2C_TransferDefaultFlag; transfer.slaveAddress = 0x24; transfer.direction = kI2C_Write; transfer.subaddress = 0; transfer.subaddressSize = 0; transfer.data = data; transfer.dataSize = sizeof(data); I2C_MasterTransferBlocking(I2C0, &transfer); PORTC->PCR[1] = PORT_PCR_MUX(1) | (1 << 24) | (0b1010 << 16); // GPIO + interrupt + falling edge interrupt type GPIOC->PDDR &= ~(1 << 1); } struct ExpanderData { bool sw1 : 1; bool sw2 : 1; bool sw3 : 1; bool sw4 : 1; bool btn1 : 1; bool btn2 : 1; bool btn3 : 1; bool btn4 : 1; bool btn5 : 1; bool btKey : 1; bool btState : 1; bool undef1 : 1; bool undef2 : 1; bool undef3 : 1; bool undef4 : 1; bool undef5 : 1; }; ExpanderData readIOExapnder() { ExpanderData data; i2c_master_transfer_t transfer; transfer.flags = kI2C_TransferDefaultFlag; transfer.slaveAddress = 0x24; transfer.direction = kI2C_Read; transfer.subaddress = 0; transfer.subaddressSize = 1; transfer.data = (uint8_t*)&data; transfer.dataSize = 2; I2C_MasterTransferBlocking(I2C0, &transfer); return data; } void setupGyroscope() { uint8_t data[] = { 0x13, 0b00000010 }; // CTRL_REG1[ACTIVE] = 1 i2c_master_transfer_t transfer; transfer.flags = kI2C_TransferDefaultFlag; transfer.slaveAddress = 0x20; transfer.direction = kI2C_Write; transfer.subaddress = 0; transfer.subaddressSize = 0; transfer.data = data; transfer.dataSize = sizeof(data); I2C_MasterTransferBlocking(I2C0, &transfer); PORTB->PCR[20] = PORT_PCR_MUX(1) | (1 << 24) | (0b1010 << 16); // INT1 // GPIO + interrupt + falling edge interrupt type GPIOB->PDDR &= ~(1 << 20); PORTE->PCR[26] = PORT_PCR_MUX(1) | (1 << 24) | (0b1010 << 16); // INT2 // GPIO + interrupt + falling edge interrupt type GPIOE->PDDR &= ~(1 << 26); } void setupAccelerometerAndMagnetometer() { const int commandLen = 2; const int commandCount = 5; uint8_t data[commandCount][commandLen] = { { 0x2A, 0b00000000 }, // set to standy mode { 0x5B, 0b00011111 }, // setup magnetometer { 0x5C, 0b00100000 }, // setup magnetometer part 2 { 0x0E, 0b00000001 }, // set accelerometer range { 0x2A, 0b00001101 } // launch accelerometer }; i2c_master_transfer_t transfer; transfer.flags = kI2C_TransferDefaultFlag; transfer.slaveAddress = 0x20; transfer.direction = kI2C_Write; transfer.subaddress = 0; transfer.subaddressSize = 0; for(int i=0; i<commandCount; i++) { transfer.data = data[i]; transfer.dataSize = commandLen; I2C_MasterTransferBlocking(I2C0, &transfer); } { const int commandLen = 2; const int commandCount = 1; uint8_t data[commandCount][commandLen] = { { 0x00, 0b00000000 } }; i2c_master_transfer_t transfer; transfer.flags = kI2C_TransferDefaultFlag; transfer.slaveAddress = 0x20; transfer.direction = kI2C_Read; transfer.subaddress = 0; transfer.subaddressSize = 0; for(int i=0; i<commandCount; i++) { transfer.data = data[i]; transfer.dataSize = commandLen; I2C_MasterTransferBlocking(I2C0, &transfer); } } } namespace Bluetooth { void setup() { uart_config_t uartConfig; uartConfig.baudRate_Bps = 9600; uartConfig.parityMode = kUART_ParityDisabled; uartConfig.stopBitCount = kUART_OneStopBit; uartConfig.txFifoWatermark = 0; uartConfig.rxFifoWatermark = 1; uartConfig.enableRxRTS = false; uartConfig.enableTxCTS = false; uartConfig.idleType = kUART_IdleTypeStartBit; uartConfig.enableTx = true; uartConfig.enableRx = true; UART_Init(UART3, &uartConfig, 60000000); PORTC->PCR[16] = PORT_PCR_MUX(3); PORTC->PCR[17] = PORT_PCR_MUX(3); } void print(char* text) { while (*text) { while (!(UART3->S1 & UART_S1_TDRE_MASK)); UART3->D = *(text++); } while (!(UART3->S1 & UART_S1_TDRE_MASK)); } void print(char ch) { while (!(UART3->S1 & UART_S1_TDRE_MASK)); UART3->D = ch; while (!(UART3->S1 & UART_S1_TDRE_MASK)); } void print(int i) { char text[16]; itoa(i, text, 10); print(text); } void printLn(char* text) { print(text); print('\n'); } }; namespace Stepper { uint8_t state = 0; int position = 0; int desiredPosition = 0; const uint8_t positionsB[] = { 0b01, 0b11, 0b10, 0b10, 0b00, 0b00, 0b00, 0b01 }; const uint8_t positionsC[] = { 0b00, 0b00, 0b00, 0b10, 0b10, 0b11, 0b01, 0b01 }; char getEndState() { return (GPIOB->PDIR & (1 << 3)) >> 3; } void unsafeStepUp() { state++; state &= 0x07; GPIOB->PSOR = positionsB[state] << 10; GPIOB->PCOR = ((~positionsB[state])&3) << 10; GPIOC->PSOR = positionsC[state] << 10; GPIOC->PCOR = ((~positionsC[state])&3) << 10; position++; } void stepUp() { if(position < 1000) { unsafeStepUp(); } } void unsafeStepDown() { state--; state &= 0x07; GPIOB->PSOR = positionsB[state] << 10; GPIOB->PCOR = ((~positionsB[state])&3) << 10; GPIOC->PSOR = positionsC[state] << 10; GPIOC->PCOR = ((~positionsC[state])&3) << 10; position--; } void stepDown() { if(position > 0) { unsafeStepDown(); } } void calibrate() { while(!getEndState()) { unsafeStepDown(); for(int i=0; i<10000; i++) { __asm("NOP"); } } position = 0; } void setup() { PORTB->PCR[10] = PORT_PCR_MUX(1); PORTB->PCR[11] = PORT_PCR_MUX(1); PORTC->PCR[11] = PORT_PCR_MUX(1); PORTC->PCR[10] = PORT_PCR_MUX(1); GPIOB->PSOR |= 1 << 10; GPIOB->PCOR |= 1 << 11; GPIOC->PCOR |= 1 << 11; GPIOC->PCOR |= 1 << 10; GPIOB->PDDR |= 1 << 10; GPIOB->PDDR |= 1 << 11; GPIOC->PDDR |= 1 << 11; GPIOC->PDDR |= 1 << 10; calibrate(); enablePIT(kPIT_Chnl_2, 600000); } }; extern "C" { void PIT_CHANNEL_2_IRQHANDLER(void) { if(PIT->CHANNEL[2].TFLG & PIT_TFLG_TIF_MASK) { PIT->CHANNEL[2].TFLG = PIT_TFLG_TIF_MASK; if(Stepper::desiredPosition != Stepper::position) { if(Stepper::desiredPosition<Stepper::position) { Stepper::stepDown(); } else { Stepper::stepUp(); } } } } } extern void onEncoderUpdate(); namespace Encoder { float currentSpeed = 0.0f; float readsPerSecond = 20.0f; void setup() { ftm_config_t ftmInfo; FTM_GetDefaultConfig(&ftmInfo); FTM_Init(FTM2, &ftmInfo); FTM_SetQuadDecoderModuloValue(FTM2, 0, -1); ftm_phase_params_t phaseOptions; phaseOptions.phasePolarity = kFTM_QuadPhaseNormal; phaseOptions.enablePhaseFilter = false; phaseOptions.phaseFilterVal = 0; FTM_SetupQuadDecode(FTM2, &phaseOptions, &phaseOptions, kFTM_QuadPhaseEncode); PORTB->PCR[18] = PORT_PCR_MUX(6); // ENC1A PORTB->PCR[19] = PORT_PCR_MUX(6); // ENC1B PORTA->PCR[2] = PORT_PCR_MUX(1); // ENC2A PORTB->PCR[23] = PORT_PCR_MUX(1); // ENC2B enablePIT(kPIT_Chnl_3, 60000000/readsPerSecond); } int read() { int encoderCount = (int16_t)FTM_GetQuadDecoderCounterValue(FTM2); /* Clear counter */ FTM_ClearQuadDecoderCounterValue(FTM2); /* Read direction */ /*if (!(FTM_GetQuadDecoderFlags(FTM2) & kFTM_QuadDecoderCountingIncreaseFlag)) { encoderCount = -encoderCount; }*/ return encoderCount; } }; extern "C" { void PIT_CHANNEL_3_IRQHANDLER(void) { if(PIT->CHANNEL[3].TFLG & PIT_TFLG_TIF_MASK) { PIT->CHANNEL[3].TFLG = PIT_TFLG_TIF_MASK; Encoder::currentSpeed = Encoder::read()*Encoder::readsPerSecond; onEncoderUpdate(); } } } #include "u8g2.h" namespace Display { u8g2_t u8g2; uint8_t u8x8_gpio_and_delay(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { int waitClocks; switch(msg) { case U8X8_MSG_GPIO_AND_DELAY_INIT: // called once during init phase of u8g2/u8x8 PORTC->PCR[5] = PORT_PCR_MUX(2); // SCK PORTA->PCR[1] = PORT_PCR_MUX(1); // RES PORTB->PCR[9] = PORT_PCR_MUX(1); // CS PORTC->PCR[4] = PORT_PCR_MUX(1); // DC PORTD->PCR[2] = PORT_PCR_MUX(2); // SDA GPIOA->PDDR |= 1 << 1; // RES GPIOB->PDDR |= 1 << 9; // CS GPIOC->PDDR |= 1 << 4; // DC break; // can be used to setup pins case U8X8_MSG_DELAY_NANO: // delay arg_int * 1 nano second waitClocks = arg_int*40/1000; for(int i=0; i<waitClocks; i++) __asm("NOP"); break; case U8X8_MSG_DELAY_100NANO: // delay arg_int * 100 nano seconds waitClocks = arg_int*40/10; for(int i=0; i<waitClocks; i++) __asm("NOP"); break; case U8X8_MSG_DELAY_10MICRO: // delay arg_int * 10 micro seconds waitClocks = arg_int*40*10; for(int i=0; i<waitClocks; i++) __asm("NOP"); break; case U8X8_MSG_DELAY_MILLI: // delay arg_int * 1 milli second waitClocks = arg_int*40*1000; for(int i=0; i<waitClocks; i++) __asm("NOP"); break; case U8X8_MSG_DELAY_I2C: // arg_int is the I2C speed in 100KHz, e.g. 4 = 400 KHz break; // arg_int=1: delay by 5us, arg_int = 4: delay by 1.25us case U8X8_MSG_GPIO_D0: // D0 or SPI clock pin: Output level in arg_int //case U8X8_MSG_GPIO_SPI_CLOCK: break; case U8X8_MSG_GPIO_D1: // D1 or SPI data pin: Output level in arg_int //case U8X8_MSG_GPIO_SPI_DATA: break; case U8X8_MSG_GPIO_D2: // D2 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D3: // D3 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D4: // D4 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D5: // D5 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D6: // D6 pin: Output level in arg_int break; case U8X8_MSG_GPIO_D7: // D7 pin: Output level in arg_int break; case U8X8_MSG_GPIO_E: // E/WR pin: Output level in arg_int break; case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int if(arg_int) { GPIOB->PSOR |= 1 << 9; } else { GPIOB->PCOR |= 1 << 9; } break; case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int if(arg_int) { GPIOC->PSOR |= 1 << 4; } else { GPIOC->PCOR |= 1 << 4; } break; case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int if(arg_int) { GPIOA->PSOR |= 1 << 1; } else { GPIOA->PCOR |= 1 << 1; } break; case U8X8_MSG_GPIO_CS1: // CS1 (chip select) pin: Output level in arg_int break; case U8X8_MSG_GPIO_CS2: // CS2 (chip select) pin: Output level in arg_int break; case U8X8_MSG_GPIO_I2C_CLOCK: // arg_int=0: Output low at I2C clock pin break; // arg_int=1: Input dir with pullup high for I2C clock pin case U8X8_MSG_GPIO_I2C_DATA: // arg_int=0: Output low at I2C data pin break; // arg_int=1: Input dir with pullup high for I2C data pin case U8X8_MSG_GPIO_MENU_SELECT: u8x8_SetGPIOResult(u8x8, 0); break; case U8X8_MSG_GPIO_MENU_NEXT: u8x8_SetGPIOResult(u8x8, 0); break; case U8X8_MSG_GPIO_MENU_PREV: u8x8_SetGPIOResult(u8x8, 0); break; case U8X8_MSG_GPIO_MENU_HOME: u8x8_SetGPIOResult(u8x8, 0); break; default: u8x8_SetGPIOResult(u8x8, 1); // default return value break; } return 1; } extern "C" uint8_t u8x8_byte_arduino_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) { switch(msg) { case U8X8_MSG_BYTE_SEND: dspi_transfer_t transferConfig; transferConfig.dataSize = arg_int; transferConfig.txData = (uint8_t *)arg_ptr; transferConfig.rxData = NULL; transferConfig.configFlags = 0; DSPI_MasterTransferBlocking(SPI0, &transferConfig); break; case U8X8_MSG_BYTE_INIT: dspi_master_config_t spiConfig; spiConfig.whichCtar = kDSPI_Ctar0; spiConfig.ctarConfig.baudRate = u8x8->display_info->sck_clock_hz; spiConfig.ctarConfig.bitsPerFrame = 8; if(u8x8->display_info->spi_mode&0x2) { spiConfig.ctarConfig.cpol = static_cast<dspi_clock_polarity_t>(1); } else { spiConfig.ctarConfig.cpol = static_cast<dspi_clock_polarity_t>(0); } if(u8x8->display_info->spi_mode&0x1) { spiConfig.ctarConfig.cpha = static_cast<dspi_clock_phase_t>(1); } else { spiConfig.ctarConfig.cpha = static_cast<dspi_clock_phase_t>(0); } spiConfig.ctarConfig.direction = kDSPI_MsbFirst; spiConfig.ctarConfig.pcsToSckDelayInNanoSec = 10000; spiConfig.ctarConfig.lastSckToPcsDelayInNanoSec = 10000; spiConfig.ctarConfig.betweenTransferDelayInNanoSec = 10000; spiConfig.whichPcs = kDSPI_Pcs0; spiConfig.pcsActiveHighOrLow = kDSPI_PcsActiveLow; spiConfig.enableContinuousSCK = false; spiConfig.enableRxFifoOverWrite = false; spiConfig.enableModifiedTimingFormat = false; spiConfig.samplePoint = kDSPI_SckToSin0Clock; DSPI_MasterInit(SPI0, &spiConfig, 60000000); u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level); break; case U8X8_MSG_BYTE_SET_DC: u8x8_gpio_SetDC(u8x8, arg_int); break; case U8X8_MSG_BYTE_START_TRANSFER: u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level); u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL); break; case U8X8_MSG_BYTE_END_TRANSFER: u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL); u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level); break; default: return 0; } return 1; } const uint8_t loading_img[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x3c, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x7c, 0x00, 0x38, 0xf0, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0xfc, 0x00, 0x78, 0xf0, 0xf8, 0x00, 0x00, 0x00, 0x01, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x01, 0xfc, 0x00, 0xf8, 0xf1, 0xf0, 0x0e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x03, 0xc0, 0x03, 0xf8, 0x01, 0xf8, 0xf3, 0xe0, 0x1e, 0x00, 0xf0, 0x07, 0xc0, 0x00, 0x00, 0x00, 0x03, 0xe0, 0x07, 0xc0, 0x03, 0xf8, 0xf7, 0xe0, 0x3e, 0x01, 0xf0, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x0f, 0xc0, 0x03, 0xf8, 0xff, 0x80, 0x3e, 0x03, 0xf0, 0x0f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x0f, 0x80, 0x0f, 0xf0, 0x7f, 0x80, 0x7f, 0x07, 0xf0, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xe0, 0x0f, 0x00, 0x1f, 0xf0, 0x7f, 0x80, 0x7f, 0x07, 0xc0, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xf0, 0x1f, 0x00, 0x3f, 0xe0, 0x7f, 0x00, 0xff, 0x0f, 0x80, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x3e, 0x00, 0x3f, 0xe0, 0x7f, 0x00, 0xff, 0x0f, 0x00, 0x3f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7c, 0x00, 0x7f, 0xe0, 0x7e, 0x01, 0xff, 0x1f, 0x00, 0x7f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xf8, 0x00, 0xfb, 0xc0, 0x7c, 0x01, 0xef, 0x1e, 0x00, 0xfb, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xf0, 0x01, 0xf3, 0xc0, 0xf8, 0x01, 0xef, 0x1e, 0x01, 0xf3, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x79, 0xf0, 0x03, 0xe3, 0xc1, 0xf8, 0x01, 0xef, 0x3e, 0x01, 0xe3, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xe0, 0x07, 0xcf, 0xc3, 0xfc, 0x03, 0xef, 0x3c, 0x01, 0xe3, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7b, 0xc0, 0x0f, 0xff, 0x87, 0xfc, 0x03, 0xcf, 0x7c, 0x03, 0xe3, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xc0, 0x1f, 0xff, 0x87, 0xfc, 0x07, 0xcf, 0xf8, 0x03, 0xc3, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x3f, 0xff, 0x8f, 0xbc, 0x07, 0x87, 0xf8, 0x07, 0xc3, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x7c, 0xff, 0x1f, 0x3c, 0x07, 0x87, 0xf8, 0x07, 0x83, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0xf8, 0x0f, 0x3e, 0x3c, 0x07, 0x87, 0xf0, 0x0f, 0x87, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x01, 0xf0, 0x0f, 0x3c, 0x3c, 0x0f, 0x87, 0xf0, 0x1f, 0x87, 0x80, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x03, 0xe0, 0x1f, 0x3c, 0x3c, 0x0f, 0x07, 0xf0, 0x3f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x03, 0xc0, 0x1f, 0x38, 0x3c, 0x0f, 0x07, 0xe0, 0x7f, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x0e, 0x00, 0x3c, 0x1f, 0x07, 0xe0, 0xff, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x07, 0xe0, 0xf0, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x1e, 0x03, 0xc1, 0xf0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x1e, 0x03, 0xc3, 0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0xc7, 0xe0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x80, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe0, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xfc, 0x07, 0x80, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xff, 0x07, 0xfc, 0x07, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x87, 0xff, 0x0f, 0x0f, 0x80, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x1f, 0xc7, 0xff, 0x0f, 0x0f, 0x81, 0xf8, 0x0e, 0x07, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x03, 0x8f, 0xff, 0x0f, 0x1f, 0x83, 0xf0, 0x1e, 0x0f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x01, 0x0f, 0x0f, 0x1f, 0x1f, 0x07, 0xe0, 0x1e, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x0f, 0x1f, 0x1e, 0x3e, 0x0f, 0x80, 0x1e, 0xff, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x0f, 0x1f, 0x1e, 0x3c, 0x0f, 0x00, 0x1f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x0f, 0x3e, 0x1e, 0x3c, 0x1f, 0x00, 0x1f, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x0f, 0x3e, 0x1e, 0x7c, 0x1e, 0x00, 0x1f, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x0f, 0x3c, 0x1e, 0x78, 0x3e, 0x00, 0x1f, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1f, 0x3c, 0x1e, 0x78, 0x7c, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1e, 0x3f, 0x1e, 0xf8, 0x78, 0x00, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x1e, 0x1f, 0x9e, 0xf0, 0x78, 0x3c, 0x3f, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x3e, 0x0f, 0xde, 0xf0, 0xf8, 0x7e, 0x3f, 0xc0, 0x00, 0x10, 0x89, 0x94, 0x5e, 0x00, 0xf8, 0x00, 0x3e, 0x07, 0xdf, 0xf0, 0xf3, 0xfc, 0x7f, 0xe0, 0x00, 0x11, 0x55, 0x56, 0x50, 0x00, 0xf0, 0x00, 0x1c, 0x03, 0xdf, 0xe0, 0xff, 0xf8, 0x7b, 0xf0, 0x00, 0x11, 0x55, 0x55, 0x56, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x0f, 0xc0, 0xff, 0xf0, 0x79, 0xfc, 0x00, 0x11, 0x5d, 0x54, 0xd2, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x07, 0xc0, 0x7f, 0xc0, 0x38, 0xfe, 0x00, 0x1c, 0x95, 0x94, 0x5e, 0xa8, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; void setup() { u8g2_Setup_ssd1306_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_arduino_hw_spi, u8x8_gpio_and_delay); u8g2_InitDisplay(&u8g2); u8g2_SetPowerSave(&u8g2, 0); u8g2_ClearBuffer(&u8g2); u8g2_SetFont(&u8g2, u8g2_font_ncenB08_tr); //u8g2_DrawStr(&u8g2, 0, 10, "Hello world!"); u8g2_DrawBitmap(&u8g2, 0, 0, 16, 64, loading_img); u8g2_SendBuffer(&u8g2); } }; void enableClocks() { CLOCK_EnableClock(kCLOCK_PortA); CLOCK_EnableClock(kCLOCK_PortB); CLOCK_EnableClock(kCLOCK_PortC); CLOCK_EnableClock(kCLOCK_PortD); CLOCK_EnableClock(kCLOCK_PortE); } void setupTFC() { enableClocks(); setupServo(0); Motor::setup(); setupCamera(); initI2C(); setupIOExpander(); setupGyroscope(); setupAccelerometerAndMagnetometer(); Display::setup(); Bluetooth::setup(); Stepper::setup(); Encoder::setup(); } #endif /* __TFC_H__ */