int main(int argc, char** argv) { char value, count = '0'; lcdInit(); i2c_init(); for(int i = 0; i < 16; i++) { sendByte(count++,0x30<<1); lcdSetPos(i,0); lcdWriteChar(count); //for(int i = 0; i<10; i++ ) __delay_ms(10); value = readByte(0x30<<1); lcdSetPos(i,1); lcdWriteChar(value); //for(int i = 0; i<10; i++ ) __delay_ms(10); } while(1) { } return (EXIT_SUCCESS); }
static void _hSensorCalibration() { if (elementIndex == 0) { if (KEY4) { elementIndex = 1; lcdClear(); lcdSetPos(3, 18); lcdWriteString_P(strWait); lcdSetPos(3, 78); lcdWriteString_P(strSec); writeSoftkeys(_skCANCEL); _tStart = millis(); } } else if (elementIndex == 1) { lcdSetPos(3, 66); uint8_t sec = (millis() - _tStart) / 1000; lcdWriteChar((5-sec) + 48); if (sec >= 5) { sensorsCalibrate(); configSave(); lcdSetPos(3, 0); lcdWriteString_P(strCalSucc); writeSoftkeys(NULL); elementIndex = 2; } } else if (KEY4) loadPage(PAGE_MENU); }
void multimeterDisplayAll() { char text[17] = " MIN MAX AVG " ; uint8_t i = mmeter.measureMode; text[i*4] = '['; text[(i*4)+4] = ']'; if(mmeter.countsIndex == 16) { text[14] = '1'; text[15] = '6'; } else { text[15] = '0' + mmeter.countsIndex; } text[16] = '\0'; lcdSetPos(0, 1); lcdSendStr(text); multimeterGetMeasStr(text); lcdSetPos(0,0); lcdSendStr(text); }
static void showMotor(uint8_t motor, uint8_t withDir) { uint8_t x, y; mixer_channel_t *channel = &Config.Mixer[motor]; if (channel->IsMotor) { x = CENTER_X + (channel->Aileron / 4); y = CENTER_Y - (channel->Elevator / 4); lcdLine(x, y, CENTER_X, CENTER_Y); lcdXY(CENTER_X - 2, CENTER_Y - 2); lcdWriteGlyph_P(&glyFC, ROP_COPY); lcdXY(x - 4, y - 4); lcdWriteGlyph_P(&glyBall, ROP_PAINT); lcdXY(x - 4, y - 7); if (channel->Rudder >= 0) lcdWriteGlyph_P(&glyDirCW, ROP_PAINT); else lcdWriteGlyph_P(&glyDirCCW, ROP_PAINT); lcdXY(x - 2, y - 2); lcdReverse(1); lcdSelectFont(&font4x6); lcdWriteChar(motor + '1'); lcdSelectFont(NULL); lcdReverse(0); if (withDir) { lcdSetPos(2, 0); lcdWriteString_P(strDirSeen); lcdSetPos(5, 0); if (channel->Rudder >= 0) lcdWriteString_P(strCW); else lcdWriteString_P(strCCW); } } else if (withDir) { lcdSetPos(3, 64); if (channel->IsServo) lcdWriteString_P(strServo); else lcdWriteString_P(strUnused); } }
//電流を表示する //引数: 0.1mA単位の値 void lcdPutCurrent(int16_t mValue, int xPos, int yPos) { uint16_t num, dec; lcdLineClear(xPos, yPos); lcdSetPos(xPos * 8, yPos); // 符号の表示 if (mValue < 0) lcdPutChar('-'); else lcdPutChar(' '); num = abs(mValue) / 10; //整数部 dec = abs(mValue) % 10; //小数部 //100mA未満は小数第1位まで表示 //100mA以上は整数部のみ表示(小数点以下は切り捨て) //[99.9][100]mAが境目 if (num < 100) { if (num < 10) lcdPutChar(' '); lcdPutUInt(num); lcdPutChar('.'); lcdPutUInt(dec); } else { if (num < 1000) lcdPutChar(' '); lcdPutUInt(num); } lcdPutStr("mA"); }
static void writeString_P(uint8_t x, uint8_t y, PGM_P str, uint8_t len, uint8_t index) { lcdReverse(index == elementIndex); lcdSetPos(x, y); writePadded_P(str, len); lcdReverse(0); }
static void _hShowModelLayout() { if (ANYKEY) { if (KEY2) // NEXT elementIndex = (elementIndex + 1) % 9; lcdClear(); writeSoftkeys(NULL); lcdSetPos(0, 0); lcdWriteString_P(strOutput); lcdWriteChar(32); if (elementIndex == 0) { lcdWriteString_P(strALL); for (uint8_t i = 0; i < 8; i++) showMotor(i, 0); } else { lcdWriteChar(elementIndex + '0'); showMotor(elementIndex - 1, 1); } } }
static void _hStickCentering() { if (KEYINIT) { if ((RX_good & 0x0F) != 0x0F) { lcdWriteString_P(scrRadioCal1); elementIndex = 1; writeSoftkeys(_skBACK); } else lcdWriteString_P(scrRadioCal0); } if (elementIndex == 0) { if (KEY4) { lcdClear(); if (rxCalibrate()) { configSave(); lcdSetPos(3, 0); lcdWriteString_P(strCalSucc); } else lcdWriteString_P(scrRadioCal2); writeSoftkeys(NULL); elementIndex = 1; } } else if (KEY4) loadPage(PAGE_MENU); }
void writeValue_test(uint8_t x, uint8_t y, int16_t value, uint8_t len, uint8_t index) { char s[7]; itoa(value, s, 10); lcdReverse(index == elementIndex); lcdSetPos(x, y); writePadded(s, len); lcdReverse(0); }
static uint8_t doMenu(menu_t *menu) { if (!keys) return 0; // key handling if (KEY2) // UP { if (menu->marked > 0) menu->marked--; } else if (KEY3) // DOWN { if (menu->marked < menu->len - 1) menu->marked++; } else if (KEY4) // ENTER return 1; if (menu->marked < menu->top) menu->top = menu->marked; else if (menu->marked - menu->top >= 5) menu->top = menu->marked - 4; // upper arrow lcdSetPos(0, 58); lcdReverse(menu->top == 0); lcdWriteGlyph_P(&glyArrowUp, ROP_PAINT); // text output for (uint8_t i = 0; i < 5 && i < menu->len; i++) { lcdSetPos(i + 1, 0); PGM_P item = menu->textSelector(menu->top + i); lcdReverse(menu->top + i == menu->marked); writePadded_P(item, 21); } // lower arrow lcdSetPos(6, 58); lcdReverse(menu->top >= menu->len - 5); lcdWriteGlyph_P(&glyArrowDown, ROP_PAINT); return 0; }
static void writeSoftkeys(const char* sk) { if (!sk) sk = currentPage.softkeys; if (sk) { lcdSetPos(7, 0); writePadded_P(sk, 21); } }
static void writeCPPMScreen(uint8_t index) { lcdClear(); lcdWriteString_P(strCPPMSettings); lcdSetPos(2, 0); if (index == 0) lcdWriteString_P(scrCPPMSettings1); else lcdWriteString_P(scrCPPMSettings2); writeSoftkeys(NULL); }
static void _hReceiverTest() { static const char* const info[6][2] PROGMEM = { { strLeft, strRight }, { strForward, strBack }, { strRight, strLeft }, { strIdle, strFull }, { strOff, strOn }, { strOff, strOn }, }; for (uint8_t i = 0; i < 6; i++) { if (RX_good & _BV(i)) { writeValue(i, 66, RX[i], 4, -1); lcdSetPos(i, 96); if (i == THR) { if (State.ThrottleOff) writePadded_P(strIdle, 5); else if (RX[THR] >= RX_THRESHOLD) writePadded_P(strFull, 5); else writeSpace(5); } else { if (abs(RX[i]) > (RX_THRESHOLD / 2)) writePadded_P((PGM_P)pgm_read_word(&info[i][RX[i] > 0]), 5); else writeSpace(5); } } else { lcdSetPos(i, 66); lcdWriteString_P(strNoSignal); } } }
//電圧を表示する //引数: mV単位の値 void lcdPutVoltage(int16_t mValue, int xPos, int yPos) { uint16_t num, dec; lcdLineClear(xPos, yPos); lcdSetPos(xPos * 8, yPos); // 符号の表示 if (mValue < 0) lcdPutChar('-'); else lcdPutChar(' '); num = abs(mValue) / 1000; //整数部 dec = abs(mValue) % 1000; //小数部 /* //10mV未満は小数第2位まで表示(小数第3位以下は切り捨て) //10mV以上は小数第1位まで表示(小数第2位以下は切り捨て) //[9.99][10.0]mVが境目 if (num < 10) { */ if (num < 10) lcdPutChar(' '); lcdPutUInt(num); lcdPutChar('.'); //小数部3桁中2桁表示(3桁目は切り捨て) dec /= 10; if (dec < 10) lcdPutChar('0'); lcdPutUInt(dec); /* } else { lcdPutUInt(num); lcdPutChar('.'); //小数部3桁中1桁表示(2桁目以降は切り捨て) lcdPutUInt(dec / 1000); } */ lcdPutStr("V"); }
static void _hFactoryReset() { if (KEYINIT) { lcdSetPos(3, 18); lcdWriteString_P(strAreYouSure); } else if (KEY4) // Yes { configReset(); configSave(); // force reset by enabling watchdog and enter endless loop cli(); wdt_enable(WDTO_15MS); for(;;); } }
void switchSize() { if(mmeter.countsIndex == MMETER_COUNTS_N-1) mmeter.countsIndex = 0; else ++mmeter.countsIndex; multimeterUpdateData(); multimeterSaveToFlash(); lcdSetPos(14,1); uint8_t i = mmeter.countsIndex; if(i == 16) lcdSendStr("16"); else { lcdSendChr(' '); lcdSendChr('0' + i); } }
static void defaultHandler() { if (editMode) // edit mode? editModeHandler(); else { if (KEYINIT | KEYREFRESH) { lcdClear(); if (currentPage.screen) lcdWriteString_P(currentPage.screen); writeSoftkeys(NULL); lcdSetPos(0, 0); } if (currentPage.handler) currentPage.handler(); } }
void switchMode() { if(mmeter.measureMode == MMETER_AVG) mmeter.measureMode = MMETER_MIN; else ++mmeter.measureMode; multimeterUpdateData(); multimeterSaveToFlash(); char nibble[4] = { ' ', ' ', ' ', ' ' }; uint8_t i = mmeter.measureMode; nibble[i] = '[' ; nibble[i+1] = ']'; i = 3 ; uint8_t x = 12 ; do { lcdSetPos(x, 1); lcdSendChr(nibble[i]); x -= 4; }while(i--); }
static void _hLoadModelLayout() { if (KEYINIT) mnuMLayout.marked = Config.MixerIndex; if (elementIndex == 0) { if (doMenu(&mnuMLayout)) { lcdClear(); lcdSetPos(3, 18); lcdWriteString_P(strAreYouSure); writeSoftkeys(_skCANCELYES); elementIndex = 1; } } else if (KEY4) // YES { mixerLoadModel(mnuMLayout.marked); //configSave(); loadPage(PAGE_SHOW_LAYOUT); } }
static void _hPIEditor() { NOKEYRETURN; elementKey(5); uint8_t index = subpage; if (Config.LinkRollPitch) index = subpage & 0xFE; if (KEY4) // CHANGE { if (elementIndex == 0) { subpage = (subpage + 1) % 3; index = subpage; if (Config.LinkRollPitch) index = subpage & 0xFE; } else { startEditMode(&Config.PID[index].UI8[elementIndex - 1], 0, 200, TYPE_UINT8); return; } } lcdSetPos(0, 30); lcdReverse(elementIndex == 0); switch (subpage) { case 0: writePadded_P(strRollAil, 16); break; case 1: writePadded_P(strPitchEle, 16); break; default: writePadded_P(strYawRud, 16); break; } for (uint8_t i = 0; i < 4; i++) writeValue(i + 2, 60, Config.PID[index].UI8[i], 5, i + 1); }
//LCDの表示を1行消去する void lcdLineClear(int x, int y) { lcdSetPos(x * 8, y); lcdPutStr(" "); //8桁 }
int main(void) { uint16_t adcPVoltages[BUFSIZE] = {0UL}; uint16_t adcNVoltages[BUFSIZE] = {0UL}; uint16_t adcCurrents[BUFSIZE] = {0UL}; uint16_t adcGNDs[BUFSIZE] = {0UL}; uint16_t adcValue; int16_t gndValue; int16_t mVoltage, mCurrent; uint8_t idx; float fv, fa; // ポートの初期化 DDRD = _BV(2); // RSTピンを出力に PORTC = _BV(4) | _BV(5); // SCL, SDA内蔵プルアップを有効 // デバイスの初期化 i2c_init(); // AVR内蔵I2Cモジュールの初期化 wait_ms(500); PORTD &= ~_BV(2); // RSTをLにします。リセット wait_ms(1); PORTD |= _BV(2); // RSTをHにします。リセット解除 wait_ms(10); lcdInit(); //LCD初期表示 lcdSetPos(0, 0); lcdPutStr("Volt + / Current"); lcdSetPos(0, 1); lcdPutStr("Volt - / GND"); wait_sec(3); //消費電力削減のためADC使用ピンをデジタル入力禁止にする(ADC入力(アナログ)専用となる) DIDR0 |= (1 << ADC0D) | (1 << ADC1D) | (1 << ADC2D) | (1 << ADC3D); //PC0,PC1,PC2,PC3 //ADC動作設定 ADCSRA = 0b10000110 //bit2-0: 110 = 64分周 8MHz/64=125kHz (50k〜200kHzであること) | (1 << ADIE); //割り込み許可(スリープ対応) //ADCの基準電圧(AVCC)と入力ピンを設定する ADMUX = (1 << REFS0) | ADC_SET_PVOLTAGE; //A/D変換ノイズ低減のスリープモードを設定する set_sleep_mode(SLEEP_MODE_ADC); sei(); //割り込み許可 sleep_mode(); //A/Dコンバータ初期化として初回変換開始…変換中…変換完了 adcValue = ADC; //値の読み捨て idx = 0; while(1) { //===== GND電圧を測定する =================================================== // ADMUX = ADC_SET_GND; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcGNDs[idx] = ADC; adcValue = total(adcGNDs); gndValue = (float)adcValue / BUFSIZE; fv = gndValue * F_VCC * 1000 / 1024; // mV単位 //電圧を表示する mVoltage = (int16_t)fv; lcdPutVoltage(mVoltage, 1, 1); //===== 正電圧を測定する =================================================== // ADMUX = ADC_SET_PVOLTAGE; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcPVoltages[idx] = ADC; adcValue = total(adcPVoltages); //A/D変換値から電圧を求める fv = (((float)adcValue / BUFSIZE) - gndValue) * F_VCC * 1000 / (1024 * F_POSITIVE_V_RATE); // mV単位 //電圧を表示する mVoltage = (int16_t)fv; lcdPutVoltage(mVoltage, 0, 0); //===== 負電圧を測定する =================================================== // ADMUX = ADC_SET_NVOLTAGE; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcNVoltages[idx] = ADC; adcValue = total(adcNVoltages); //A/D変換値から電圧を求める fv = (((float)adcValue / BUFSIZE) - gndValue) * F_VCC * 1000 / (1024 * F_NEGATIVE_V_RATE); // mV単位 //電圧を表示する mVoltage = (int16_t)fv; lcdPutVoltage(mVoltage, 0, 1); //===== 電流を測定する ==================================================== // ADMUX = ADC_SET_CURRENT; wait_ms(10); //安定待ち sleep_mode(); //スリープモード突入…変換中…変換完了 adcCurrents[idx] = ADC; adcValue = total(adcCurrents); // ADCの読み取り値が1000以上の場合測定不可とする if ((float)adcValue / BUFSIZE < 1000) { //A/D変換値から電圧を求め、電流を算出する fv = (((float)adcValue / BUFSIZE) - gndValue) * F_VCC * 1000 / (1024 * F_CURRENT_AMP); // mV単位 fa = fv / F_SHUNT_R; //mA単位 //電流を表示する mCurrent = (int16_t)(fa * 10.0); //0.1mA単位 lcdPutCurrent(mCurrent, 1, 0); } else { lcdLineClear(1, 0); lcdSetPos(8, 0); lcdPutStr(" OVER"); } //次のループの準備 if (++idx == BUFSIZE) idx = 0; } return 0; }
static void _hStart() { char s[7]; if (KEY4) // MENU { arm(OFF); loadPage(PAGE_MENU); return; } if (KEYINIT || KEYREFRESH) { if (Config.ArmingMode) arm(ON); if (State.Armed) { lcdSetPos(3, 30); lcdSelectFont(&font12x16); lcdWriteString_P(strARMED); lcdSelectFont(NULL); return; } else { lcdSetPos(0, 5); lcdSelectFont(&font12x16); lcdWriteString_P(strHeader); lcdSelectFont(NULL); lcdSetPos(2, 0); lcdWriteString_P(scrStart); } } if (!State.Armed) { lcdSetPos(2, 84); if (State.SelfLevel) writePadded_P(strON, 3); else writePadded_P(strOFF, 3); lcdSetPos(3, 0); if (State.Error) { lcdWriteString_P(strError); lcdWriteChar(32); if (State.Error & ERR_NOT_CALIBRATED) lcdWriteString_P(strSensorNotCal); else { lcdWriteString_P(PSTR("no ")); const char* s; if ((State.Error & ERR_NO_RX) == ERR_NO_RX) s = PSTR("RX"); else if (State.Error & ERR_NO_ROLL) s = strRoll; else if (State.Error & ERR_NO_PITCH) s = strPitch; else if (State.Error & ERR_NO_YAW) s = strYaw; else s = strThro; lcdWriteString_P(s); lcdWriteString_P(PSTR(" input")); } } else lcdWriteString_P(PSTR("Ready for departure!")); // battery level lcdSetPos(4, 13*6); utoa(BATT / 10, s, 10); lcdWriteString(s); lcdWriteChar('.'); utoa(BATT % 10, s, 10); writePadded(s, 3); // roll angle writeValue(5, 13*6, (int16_t)ANGLE[ROL], 7, -1); // pitch angle writeValue(6, 13*6, (int16_t)ANGLE[PIT], 7, -1); } }