int main(void) { init_ports(); init_osc(); startup(); // setup sequence TMR0_init(); // will use for 15 min timer int i; while(1)// main loop { while(!detect);// main loop, program spends majority here, detect active low for(i=5; i !=0; i--) // to separate beginning of trigger sequence { delayUs(50000); } trigger(); // take picture for(i=10; i !=0; i--) // delay after picture { delayUs(50000); } } return (EXIT_SUCCESS); }
void writeFourBits(unsigned char word, unsigned int commandType, unsigned int delayAfter, unsigned int lower){ //TODO: // set the commandType (RS value) // WTF is this here for we are supposed to use 4 bit mode and you have LATE 0, 2, 4, and 6 when you tell us to use the ODD registers //LATEbits.LATE0 = word&0x01; //LATEbits.LATE2 = word&0x02; //LATEbits.LATE4 = word&0x04; //LATEbits.LATE6 = word&0x08; if(lower){ // set least sig bits TRIS_D4 = word&0x01; TRIS_D5 = word&0x02; TRIS_D6 = word&0x03; TRIS_D7 = word&0x04; } else{ // set most sig figs TRIS_D4 = word&0x01; TRIS_D5 = word&0x02; TRIS_D6 = word&0x03; TRIS_D7 = word&0x04; } LCD_RS = commandType; // 1 for write 0 for F*****G USELESS we never read. and the ports would have to be changed to inputs instead of outputs to read anyways //enable LCD_E = 1; // This allows reading of data into LCD mem //delay delayUs(1); //disable LCD_E = 0; // Finishes writing data delayUs(1); delayUs(delayAfter); }
CmdResult Command::IRQsend(CommandType cmd, unsigned int arg) { unsigned char cc=static_cast<unsigned char>(cmd); //Handle ACMDxx as CMD55, CMDxx if(cc & 0x80) { CmdResult r=IRQsend(CMD55,(static_cast<unsigned int>(rca))<<16); if(r.IRQvalidateR1Response()==false) return CmdResult(cc & 0x3f,CmdResult::ACMDFail); //Bit 5 @ 1 = next command will be interpreted as ACMD if((r.getResponse() & (1<<5))==0) return CmdResult(cc & 0x3f,CmdResult::ACMDFail); } //Send command cc &= 0x3f; unsigned int command=SDIO_CMD_CPSMEN | static_cast<unsigned int>(cc); if(cc!=CMD0) command |= SDIO_CMD_WAITRESP_0; //CMD0 has no response if(cc==CMD2) command |= SDIO_CMD_WAITRESP_1; //CMD2 has long response if(cc==CMD9) command |= SDIO_CMD_WAITRESP_1; //CMD9 has long response SDIO->ARG=arg; SDIO->CMD=command; //CMD0 has no response, so wait until it is sent if(cc==CMD0) { for(int i=0;i<500;i++) { if(SDIO->STA & SDIO_STA_CMDSENT) { SDIO->ICR=0x7ff;//Clear flags return CmdResult(cc,CmdResult::Ok); } delayUs(1); } SDIO->ICR=0x7ff;//Clear flags return CmdResult(cc,CmdResult::Timeout); } //Command is not CMD0, so wait a reply for(int i=0;i<500;i++) { unsigned int status=SDIO->STA; if(status & SDIO_STA_CMDREND) { SDIO->ICR=0x7ff;//Clear flags if(SDIO->RESPCMD==cc) return CmdResult(cc,CmdResult::Ok); else return CmdResult(cc,CmdResult::RespNotMatch); } if(status & SDIO_STA_CCRCFAIL) { SDIO->ICR=SDIO_ICR_CCRCFAILC; return CmdResult(cc,CmdResult::CRCFail); } if(status & SDIO_STA_CTIMEOUT) break; delayUs(1); } SDIO->ICR=SDIO_ICR_CTIMEOUTC; return CmdResult(cc,CmdResult::Timeout); }
void lcd_disp_sz_char_24(uchar cx,uchar cy,uchar* chr,uchar* buf) { uchar *p,i,s,page; uchar port; if(chr!=0) { get24x24BytesFormGB2312s(chr,buf); } p=chrBuf_24; if(cx<2) { port=1; s=cx*24; } else { port=2; s=((cx-2)*24); } for(page=0;page<3;page++) { LCD_WrCmd(port,0xb8+cy*3+page); delayUs(100); LCD_WrCmd(port,0x40+s); delayUs(100); for(i=0;i<24;i++) { LCD_WrDat(port,*p); delayUs(10); p++; } } }
//Initializes the LCD as described in the HD44780 datasheet. //Normally called only by the initialize() function in utility.c. void lcdInit() { //configure LCD E (Enable) control pin as an output sbi(DDRD, 6); //configure LCD RS (Register Select) control pin as an output sbi(DDRD, 7); //set LCD E (Enable) line low inititally, so it can rise later cbi(PORTD, 6); //wait 15ms after power on delayMs(15); //Issue 'Function Set' commands to initialize LCD for 8-bit interface mode writeControl(0x38); delayUs(4900); //+100us in writeControl = 5000us or 5ms total writeControl(0x38); delayUs(50); //+100us in writeControl = 150us total writeControl(0x38); //Function Set command to specify 2 display lines and character font writeControl(0x38); //Display off lcdOff(); //Clear display clearScreen(); //Set entry mode writeControl(0x06); //Display on lcdOn(); }
int main() { enableInterrupts(); initTMR2(); char key = 'x'; while(1); { clearLCD(); InitKeyPad(); switch(state) { case findKey: ScanKeys(); //should i update the key value here? break; case debouncePress: delayUs(5000); //Proper Delay? break; case debounceRelease: delayUs(5000); break; case display: printCharLCD(key); break; } } }
uint8_t getKeyColumnPattern() { uint8_t result=0; PORTB&=~((1<<3)|(1<<2)|(1<<0)); // set not used multiplexer lines to 0 DDRB|=((1<<3)|(1<<2)); // set multplexer lines as outputs DDRB&=~(1<<0); // set the selected line as input delayUs(KEYSCANDELAY); if(PINB&(1<<0)) result|=(1<<0) ; PORTB&=~((1<<3)|(1<<2)|(1<<0)); // set not used multiplexer lines to 0 DDRB|=((1<<3)|(1<<0)); // set multplexer lines as outputs DDRB&=~(1<<2); // set the selected line as input delayUs(KEYSCANDELAY); if(PINB&(1<<2)) result|=(1<<1) ; PORTB&=~((1<<3)|(1<<2)|(1<<0)); // set not used multiplexer lines to 0 DDRB|=((1<<2)|(1<<0)); // set multplexer lines as outputs DDRB&=~(1<<3); // set the selected line as input delayUs(KEYSCANDELAY); if(PINB&(1<<3)) result|=(1<<2) ; return result; }
void ReadSensor(){ int duration=0; int cm=0; Signal = OUTPUT; //Set Pin as an output LATBbits.LATB4 = 0; //Write a digital 0 to the pin to initialize the sensor delayUs(2); LATBbits.LATB4 = 1; //Write a digital 1 to the pin to initialize the sensor delayUs(3); //Wait for (aprox) 5 microseconds before turning the pin low LATBbits.LATB4 = 0; //Turns the pin low to a digital 0 Signal = INPUT; // Sets the pin as an input to read the pulse from the Sensor //while (Signal == 0) {} T4CONbits.ON = 1; //Initiates the timer4 delayUs(2); //while (Signal == 1) {} duration = TMR4; IFS0bits.AD1IF = 0; //Turns the flag off T4CONbits.ON = 0; //Turns the timer off TMR4 = 0; //Clear TMR4 duration = duration / 1000; // The speed of sound is 340 m/s or 29 microseconds per centimeter. // The ping travels out and back, so to find the distance of the // object we take half of the distance travelled. // cm = duration / 29 / 2, equals cm = duration / 58; cm = duration / 58; if (cm <= 30) {LATDbits.LATD2 = 1;} // Turns the led ON else { LATDbits.LATD2 = 0; // Turns the led OFF} }}
void DisplayCGRAM(unsigned char cx,unsigned char cy) { uchar *p,i,s,page; uchar port; cy--; p=lbatStateGraph; if(cx<4) { port=1; s=cx<<4; } else { port=2; s=((cx-4)<<4); } for(page=0;page<2;page++) { LCD_WrCmd(port,0xb8+cy*2+page); delayUs(100); LCD_WrCmd(port,0x40+s); delayUs(100); for(i=0;i<16;i++) { LCD_WrDat(port,*p); delayUs(10); p++; } } }
int main(void) { SYSTEMConfigPerformance(10000000); initTimer1(); initSW2(); initLEDs(); enableInterrupts(); state = led1; while(1) { //TODO: Using a finite-state machine, define the behavior of the LEDs //Debounce the switch switch(state) { case led1: turnOnLED(1); stateNext = led2; break; case led2: turnOnLED(2); stateNext = led1; break; case deBounce1: delayUs(10000); break; case deBounce2: delayUs(10000); break; } } return 0; }
void lcd_disp_sz_SingleBytechar(uchar cy,uchar cx,uchar* chr) { uchar *p,i,s,page; uchar port; getBytesFormASCIIs(chr); p=chrBuf; if(cx<8) { port=1; s=cx<<3; } else { port=2; s=((cx-8)<<3); } for(page=0;page<2;page++) { LCD_WrCmd(port,0xb8+cy*2+page); delayUs(100); LCD_WrCmd(port,0x40+s); delayUs(100); for(i=0;i<8;i++) { LCD_WrDat(port,*p); delayUs(10); p++; } } }
void LCD_PutChar(unsigned char cx,unsigned char cy,unsigned char chr){ uchar *p,i,s,page; uchar port; chr=0;//消除warning 该变量无用,仅为兼容之前接口 cy--; p=arrow16x16; if(cx<4) { port=1; s=cx<<4; } else { port=2; s=((cx-4)<<4); } for(page=0;page<2;page++) { LCD_WrCmd(port,0xb8+cy*2+page); delayUs(100); LCD_WrCmd(port,0x40+s); delayUs(100); for(i=0;i<16;i++) { LCD_WrDat(port,*p); delayUs(10); p++; } } }
void lcd_disp_sz_char_24_original_x(uchar x,uchar cy,uchar* chr,uchar* buf) { uchar *p,i,s,page; uchar port; if(chr!=0) { get24x24BytesFormGB2312s(chr,buf); } p=buf; if(x<64) { port=1; s=x; } else { port=2; s=x-64; } for(page=0;page<3;page++) { LCD_WrCmd(port,0xb8+cy*3+page); delayUs(100); LCD_WrCmd(port,0x40+s); delayUs(100); for(i=0;i<24;i++) { LCD_WrDat(port,*p); delayUs(10); p++; } } }
/******************************************************************************* * Description : * Syntax : * Parameters I: * Parameters O: * return : *******************************************************************************/ static void CC1101_reset(void) { CSN_OUT_H; delayUs(200); CSN_OUT_L; delayUs(200); CSN_OUT_H; delayUs(200); CSN_OUT_L; if (TestSOMI()) { SPI_byte(SRES); // GDO2 _|-|_ 3.5us } else { RF.SOMI_false = 1u; } delayUs(200); if (TestSOMI()) { NOP(); } else { RF.SOMI_false = 1u; } CSN_OUT_H; }
void lcd_disp_sz_char(uchar cx,uchar cy,uchar* chr) { uchar *p,i,s,page; uchar port; getBytesFormGB2312s(chr); p=chrBuf; if(cx<4) { port=1; s=cx<<4; } else { port=2; s=((cx-4)<<4); } for(page=0;page<2;page++) { LCD_WrCmd(port,0xb8+cy*2+page); delayUs(100); LCD_WrCmd(port,0x40+s); delayUs(100); for(i=0;i<16;i++) { LCD_WrDat(port,*p); delayUs(10); p++; } } }
/* void nRF24L01_TxPacket(uchar * addr,uchar addrLen,uchar *datas,uchar datasLen) { power_off(); CE=0; // CSN=1; //SPI标止 // SCLK=0; //SPI时钟置低 // delayUs(20); SPI_Write_Read_Register(WRITE_REG + EN_AA, 0x00); // 失能接收通道0自动应答 // SPI_Write_Read_Register(WRITE_REG + EN_RXADDR, 0x00); // 失能接收通道0 SPI_Write_Read_Register(WRITE_REG + SETUP_RETR, 0x00); // 失能自动重发 SPI_Write_Read_Register(WRITE_REG + RF_CH, 0); // 选择射频通道0x00 SPI_Write_Read_Register(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 // SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x7e); // CRC使能,16位CRC校验,上电 // CE=1; // delayUs(200); //// CE=0; //StandBy I模式 SPI_Write_Buffer(WRITE_REG + TX_ADDR, addr, addrLen); // 写入发送地址 SPI_Write_Buffer(WR_TX_PLOAD,datas, datasLen); // 装载数据 SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x7e); // IRQ收发完成中断响应,16位CRC,主发送 CE=1; //置高CE,激发数据发送 // delayUs(400); //delayUs(500); delayMs(50); CE=0; SPI_Write_Read_Register(WRITE_REG + STATUS, 0xff); // 清除TX_DS或MAX_RT中断标志 //SPI_Write_Read_Register(FLUSH_TX,0x0); clearTXFIFO(); } */ void nRF24L01_TxPacket(uchar * addr,uchar addrLen,uchar *datas,uchar datasLen) { CE=0; CSN=1; //SPI标止 SCLK=0; //SPI时钟置低 delayUs(20); // power_off(); // SPI_Write_Buffer(WRITE_REG + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH); // 写入发送地址 SPI_Write_Read_Register(WRITE_REG + EN_AA, 0x00); // 失能接收通道0自动应答 // SPI_Write_Read_Register(WRITE_REG + EN_RXADDR, 0x00); // 失能接收通道0 SPI_Write_Read_Register(WRITE_REG + SETUP_RETR, 0x00); // 失能自动重发 SPI_Write_Read_Register(WRITE_REG + RF_CH, 0x0); // 选择射频通道0x00 SPI_Write_Read_Register(WRITE_REG + RF_SETUP, 0x07); // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益 // SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x7e); // CRC使能,16位CRC校验,上电 // CE=1; // delayUs(200); CE=0; //StandBy I模式 SPI_Write_Buffer(WRITE_REG + TX_ADDR, addr, addrLen); // 写入发送地址 SPI_Write_Buffer(WR_TX_PLOAD,datas, datasLen); // 装载数据 SPI_Write_Read_Register(WRITE_REG + CONFIG, 0x7e); // IRQ收发完成中断响应,16位CRC,主发送 CE=1; //置高CE,激发数据发送 // delayUs(600); delayUs(600); SPI_Write_Read(FLUSH_TX); SPI_Write_Read_Register(WRITE_REG + STATUS, 0xff); // 清除TX_DS或MAX_RT中断标志 }
int main(void) { //Initialize new interrupt fix SYSTEMConfigPerformance(40000000); #ifdef part1 initSW(); initLED(RUN_LED); initLED(STOP_LED); initTimer2(); enableInterrupts(); // initialize the lights state = runToggle; turnOffLED(STOP_LED); turnOnLED(RUN_LED); while(1){ switch(state){ // the state that toggles the LEDs case runToggle: // switch the led's toggleAllLEDs(); prevState = runToggle; state = waitForPress; //Go to debounce press state break; // wait for user input i.e. button press case waitForPress: while (state == waitForPress); break; // once the button has been pressed case dbPress: delayUs(DBdelayTime); // Delay for 5ms while(state == dbPress ); break; // once the button has been released case dbRelease: delayUs(DBdelayTime); //Delay for 5ms state = runToggle; break; } } #endif return 0; }
int main(void) { SYSTEMConfigPerformance(40000000); initKeypad(); enableEnterruptKeypad(); initTimer2(); initLCD(); enableInterrupts(); moveCursorLCD(0,0); state = Wait; while (1) { switch (state) { case Wait: break; case Scan: key = scanKeypad(); state = MoveCursor; break; case MoveCursor: if(count == 0) moveCursorLCD(0,0); else if (count == 9) moveCursorLCD(1,0); state = Print; break; case debounce1: delayUs(500); state = Scan; break; case debounce2: delayUs(500); state = MoveCursor; break; case Print: delayUs(100); if(key == 0) printCharLCD('0'); else if(key == 1) printCharLCD('1'); else if(key == 2) printCharLCD('2'); else if(key == 3) printCharLCD('3'); else if(key == 4) printCharLCD('4'); else if(key == 5) printCharLCD('5'); else if(key == 6) printCharLCD('6'); else if(key == 7) printCharLCD('7'); else if(key == 8) printCharLCD('8'); else if(key == 9) printCharLCD('9'); else if(key == 10) printCharLCD('*'); else if(key == 11) printCharLCD('#'); state = Wait; break; } } return 0; }
void toggleE() { delayUs(5); LATCbits.LAT_E = ENABLED; delayUs(E_DELAY); LATCbits.LAT_E = DISABLED; delayUs(E_DELAY); return; }
void rightcircle(){ sendCommand("LVM 75000"); delayUs(1000000); sendCommand("RMR -300000"); sendCommand("LMR 150000"); delayUs(8500000); sendCommand("LVM 155000"); delayUs(100000); }
void leftcircle(){ sendCommand("RVM 75000"); delayUs(1000000); sendCommand("RMR -150000"); sendCommand("LMR 300000"); delayUs(8500000); sendCommand("RVM 150000"); delayUs(100000); }
/******************************************************************************* * Description : * Syntax : * Parameters I: * Parameters O: * return : *******************************************************************************/ static void CC1101_RxMode(void) { SpiWriteStrobe(SIDLE); delayUs(200); SpiWriteStrobe(SFRX); // clear RF RX buff (buff index return 0) delayUs(200); SpiWriteStrobe(SRX); CC1101_ExtInt_enable(); }
/********************************************************** * Performs AAP Window Expansion. This function will reset * target, send the AAP expansion sequence, initialize the * debug interface and verify that AAP can be accessed. * It will try several delays between reset is released * and reading the AAP in case the reset line has a slow * ramp-up. * * After this function completes the AAP registers are * available. If it fails to access the AAP, it will * throw an exception. * **********************************************************/ void performAapExpansion(void) { uint32_t dpId, apId; int i,j; bool success = false; for ( i=0; i<AAP_EXPANSION_RETRY_COUNT; i++ ) { /* Pull reset pin low */ GPIO_PinOutClear((GPIO_Port_TypeDef)RESET_PORT, RESET_PIN); SWCLK_CLR(); delayMs(50); /* Send the AAP Window expansion sequence */ aapExtensionSequence(); /* Release reset */ delayUs(10); GPIO_PinOutSet((GPIO_Port_TypeDef)RESET_PORT, RESET_PIN); /* Try different delays in case of slow reset ramp */ for ( j=0; j<i; j++ ) { delayUs(10); } /* Connect to SW-DP */ TRY dpId = initDp(); apId = readApId(); if ( verifyDpId(dpId) && apId == EFM32_AAP_ID ) { /* Success! AAP registers can now be accessed. * We cannot return in the middle of a TRY block. * Set flag here and return after ENDTRY */ success = true; } CATCH /* Do nothing in case of error. We retry. */ ENDTRY /* Return if we found the AAP registers*/ if ( success ) { printf("AAP registers found\n"); return; } } /* Failed to get access to AAP registers. Raise an error. */ RAISE(SWD_ERROR_AAP_EXTENSION_FAILED); }
/******************************************************************************* * Description : * Syntax : CC1101(TxBuff, RF_payloadSize) * Parameters I: * Parameters O: * return : *******************************************************************************/ void CC1101_Send(uint8_t *TxBuff, const uint8_t len) { #ifdef CC1101_DISPLAY_TX_COMM_SYMBOL_EN CC1101_displayTxCommSymbol(); #endif CC1101_ExtInt_disable(); SpiWriteStrobe(SIDLE); /* IDL状态下进行配置 */ delayUs(200); CC1101_setPATable(); //8 level 0~7 CC1101_setTxPower(PA_LEVEL_7); // choice max PA SpiWriteStrobe(SFTX); delayUs(200); SpiWriteBurstReg(TXFIFO, TxBuff, len); delayUs(200); #ifdef RF_PA_EN pinPA_Tx_EN; // Tx PA (RF PA内部 三极管有延时,配置完PA需 delayUs(200);) delayMs(5); #endif //delayMs(10); // ARM 频率快 延时发送 20ms <= T <= 500ms SpiWriteStrobe(STX); //CC1101_waitSend(); //待改 // delayMs(55); // 20K delayMs(5); /* 预留间隔时间 */ #ifdef RF_PA_EN pinPA_Tx_DIS; // Tx don't through PA and Rx #endif //------------------------------------------ #ifdef RF_SLAVE SpiWriteStrobe(SIDLE); /* IDL状态下进行配置 */ delayUs(200); CC1101_setPATable(); //8 level 0~7 CC1101_setTxPower(PA_LEVEL_1); // choice max PA delayMs(10); // ARM 频率快 延时发送 SpiWriteStrobe(STX); delayMs(55); //CC1101_waitSend(); //待改 delayMs(5); #endif CC1101_RxMode(); //default Rx mode enalbe ExtInt //wzg test IO_WriteGPIOPin(IO_PORT4,IO_PINxC,IO_BIT_SET); //M-RXD-LED IO_WriteGPIOPin(IO_PORT3,IO_PINxF,IO_BIT_CLR); //M-TXD-LED //--------------------- }
int main(void) { enableInterrupts(); initLEDs(); initSW2(); initTimer2(); updateLEDState(); while(1) { switch (currentState) { case wait: if(buttonState==risingEdge)//button is pressed { currentState=debouncePress; buttonState=Idle; } // if(IFS1bits.CNDIF==1) // //if(PORTDbits.RD6==0) //!!! use change notifications, not polling // { // currentState=debouncePress; // } break; case debouncePress: delayUs(50); currentState=waitForRelease; break; case waitForRelease: //!!! use change notifications, not polling if(buttonState==fallingEdge)//button released { currentState=debounceRelease; buttonState=Idle; } // if(IFS1bits.CNDIF==1) // //if(PORTDbits.RD6==1)//released // { // currentState=debounceRelease; // } break; case debounceRelease: delayUs(50); updateLEDState(); currentState=wait; break; } } return 0; }
void Lcd44780::half(unsigned char byte) { if(byte & (1<<7)) d7.high(); else d7.low(); //Not much fast, but works if(byte & (1<<6)) d6.high(); else d6.low(); if(byte & (1<<5)) d5.high(); else d5.low(); if(byte & (1<<4)) d4.high(); else d4.low(); delayUs(1); e.high(); delayUs(1); e.low(); }
void sendDisplay(){ uchar m; CS_DISP=0; WriteByte(SPI_START); delayUs(5); for(m=0;m<DISPLAY_BUF_LEN;m++){ WriteByte(displayBuf[m]); delayUs(5); } WriteByte(SYM_END); CS_DISP=1; }
void writeBit(uint8_t bit){ //Pull line low for 1uS pullLineLow(); delayUs(1); //If we want to write 1, release the line (if not will keep low) if(bit) { releaseLine(); } //Wait for 60uS and release the line delayUs(60); releaseLine(); }
/* * This function is called in lab1p2.c for testing purposes. * If everything is working properly, you should get this to look like the video on D2L * However, it is suggested that you test more than just this one function. */ void testLCD(){ initLCD(); int i = 0; printCharLCD('c'); for(i = 0; i < 1000; i++) delayUs(1000); clearLCD(); printStringLCD("Hello!"); moveCursorLCD(1, 2); for(i = 0; i < 1000; i++) delayUs(1000); printStringLCD("Hello!"); for(i = 0; i < 1000; i++) delayUs(1000); }
unsigned char scanKeypad(){ //Scans through Keypad unsigned char key = 'x'; //Check 1st row ODC1 = 1; ODC2 = 0; ODC4 = 0; ODC4 = 0; delayUs(4000); if(col1 == 0) key = '1'; else if(col2 == 0) key = '2'; else if(col3 == 0) key = '3'; //Check 2nd Row ODC1 = 0; ODC2 = 1; ODC4 = 0; ODC4 = 0; delayUs(4000); if(col1 == 0) key = '4'; else if(col2 == 0) key = '5'; else if(col3 == 0) key = '6'; //Check 3rd Row ODC1 = 0; ODC2 = 0; ODC4 = 1; ODC4 = 0; delayUs(4000); if(col1 == 0) key = '7'; else if(col2 == 0) key = '8'; else if(col3 == 0) key = '9'; //Check 4th Row ODC1 = 0; ODC2 = 0; ODC4 = 0; ODC4 = 1; delayUs(4000); if(col1 == 0) key = '*'; else if(col2 == 0) key = '0'; else if(col3 == 0) key = '#'; if(key != 'x') return key; }