/*********************************************************************************/ /** * File: dvoraj42.c * Author: Jan Dvořák z Vozerovic * FEL-ID: dvoraj42 * e-mail: dvorkaman@gmail.com * site: dvorkaman.php5.cz */ #ifndef __dvoraj42_c__ #define __dvoraj42_c__ #include "stm32f10x_gpio.h" #include "dvoraj42.h" #include "letters.c" extern volatile timeStruct SYSTEM_CLOCK; extern int keyboardLock; bool keyboard_isPressed; // true if any key is down timeStruct keyboard_keyDownTime; // time, when a key was pushed int keyboard_pressTime; // how long was the key pressed in ms int keyboard_pressedKey; int keyboard_lastState; // to recognize if key are still int keyboard_actualValue; int LONG_PRESS = 1500; int UART_last; // last sign sent through uart bool UART_valid; // if uart data are valid (unvalid after read) /*********************************************************************************/ /** * Performace of keyboard cycle .. read and evaluate */ void keyboardCycle(void) { keyboard_actualValue = readKeyboard(); if( keyboard_actualValue==KEY_NONE && keyboard_lastState==KEY_NONE) return; // nothing happened // Start of pressing down if( keyboard_lastState==KEY_NONE ) { keyboard_keyDownTime = SYSTEM_CLOCK; keyboard_lastState = keyboard_actualValue; keyboard_isPressed = TRUE; return; } // End of key pressing if( keyboard_actualValue==KEY_NONE ) { keyboard_pressedKey = keyboard_lastState; keyboard_pressTime = getTimeDiff(keyboard_keyDownTime, SYSTEM_CLOCK); keyboard_isPressed = FALSE; keyboard_lastState = KEY_NONE; return; } // Check if state dit not change if( keyboard_actualValue != keyboard_lastState ) { keyboard_lastState = KEY_NONE; // clear information keyboard_isPressed = FALSE; return; } } /*********************************************************************************/ /** * Clear the keyboard state */ void keyboardClearState(void) { keyboard_pressTime = 0; keyboard_pressedKey = KEY_NONE; } /*********************************************************************************/ /** * Returns if some key is pressed */ bool keyboardIsPressed(void) { return keyboard_isPressed; } /*********************************************************************************/ /** * Get pressed key code and press time */ pressedKey getPressedKey(void) { pressedKey pk; pk.key = KEY_NONE; pk.time = 0; // check if not in the middle of pressing if( keyboard_isPressed )return pk; // return value pk.time = keyboard_pressTime; pk.key = keyboard_pressedKey; // clear state keyboardClearState(); return pk; } /*********************************************************************************/ /** * Wait until pressed keyboart is released */ pressedKey waitForKeyboardIsReleased(void) { pressedKey pk; keyboardCycle(); while( keyboardIsPressed()==TRUE ) { keyboardCycle(); } pk = getPressedKey(); if( pk.time < KEY_MINIMAL_TIME ) { pk.key = 0; pk.time = 0; } return pk; } /*********************************************************************************/ /** * System clock handler */ void SysTick_Handler(void) { // System clock SYSTEM_CLOCK.ms++; if( SYSTEM_CLOCK.ms>=1000 ) { SYSTEM_CLOCK.ms = 0; SYSTEM_CLOCK.s++; } } /*********************************************************************************/ /** * USART handler */ void USART1_IRQHandler(void) { int ch; ch = USART_ReceiveData(USART1); UART_valid = TRUE; UART_last = ch; } /*********************************************************************************/ /** * Send single char */ void USARTsendChar(int ch) { USART_SendData(USART1, ch); while (USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); } /*********************************************************************************/ /** * Send single char */ void USARTsendString(int* string) { while( *string!= '\0' ) { USARTsendChar(*string); // set char string++; // move to another char } } /*********************************************************************************/ /** * Get difference between to time in ms */ int getTimeDiff(timeStruct startTime, timeStruct endTime) { int ms, s; ms = endTime.ms - startTime.ms; s = endTime.s - startTime.s; if( ms<0 ) { ms += 1000; s--; } return s * 1000 + ms; } /*********************************************************************************/ /** * Delay pc cycles */ void delayCycles(vu32 cycles) { while( cycles >0 ) { cycles--; } } /*********************************************************************************/ /** * Configure keyboard */ void configureKeyboard(void) { //K1, K2, K3: OPEN DRAIN A1, A2, A3 //K4, K5, K6, K7: PULL UP A4, A5, A6, A7 GPIO_InitTypeDef init; // Open drain - output init.GPIO_Mode = GPIO_Mode_Out_OD; init.GPIO_Speed = GPIO_Speed_10MHz; init.GPIO_Pin = GPIO_Pin_1; GPIO_Init(GPIOA, &init); init.GPIO_Pin = GPIO_Pin_2; GPIO_Init(GPIOA, &init); init.GPIO_Pin = GPIO_Pin_3; GPIO_Init(GPIOA, &init); // Pull up - input init.GPIO_Mode = GPIO_Mode_IPU; init.GPIO_Pin = GPIO_Pin_4; GPIO_Init(GPIOA, &init); init.GPIO_Pin = GPIO_Pin_5; GPIO_Init(GPIOA, &init); init.GPIO_Pin = GPIO_Pin_6; GPIO_Init(GPIOA, &init); init.GPIO_Pin = GPIO_Pin_7; GPIO_Init(GPIOA, &init); // Default settings setKeyboardToDefaultState(); keyboardClearState(); } /*********************************************************************************/ /** * Set default state of keyboard */ void setKeyboardToDefaultState(void) { GPIO_SetBits(GPIOA, GPIO_Pin_1); GPIO_SetBits(GPIOA, GPIO_Pin_2); GPIO_SetBits(GPIOA, GPIO_Pin_3); } /*********************************************************************************/ /** * Read keyboard */ int readKeyboard(void) { int i; int value = 0; int output = 0; for( i = 0; i<3; i++ ) { // Set one to zero, others to one switch(i) { case 0: GPIO_ResetBits(GPIOA, GPIO_Pin_1); GPIO_SetBits(GPIOA, GPIO_Pin_2); GPIO_SetBits(GPIOA, GPIO_Pin_3); break; case 1: GPIO_SetBits(GPIOA, GPIO_Pin_1); GPIO_ResetBits(GPIOA, GPIO_Pin_2); GPIO_SetBits(GPIOA, GPIO_Pin_3); break; case 2: GPIO_SetBits(GPIOA, GPIO_Pin_1); GPIO_SetBits(GPIOA, GPIO_Pin_2); GPIO_ResetBits(GPIOA, GPIO_Pin_3); break; } delayCycles(KEY_OD_CHANGE); // Read bits to the value value = 0; value |= (1 - GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_4)); value |= (1 - GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_5)) << 1; value |= (1 - GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_6)) << 2; value |= (1 - GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_7)) << 3; // Set to ouput output = output << 4; output |= value; } // Default settings setKeyboardToDefaultState(); return output; } /*********************************************************************************/ /** * Configure segment */ void configureSegment(void) { // PINS: DATA PC13 // CLK PC14 // WRITE PC15 GPIO_InitTypeDef init; init.GPIO_Mode = GPIO_Mode_Out_PP; // All pins are the same Mode init.GPIO_Speed = GPIO_Speed_10MHz; // All pins are the same Speed // CLK init.GPIO_Pin = SEGMENT_CLK; GPIO_Init(GPIOC, &init); // WRT init.GPIO_Pin = SEGMENT_WRL; GPIO_Init(GPIOC, &init); // Data init.GPIO_Pin = SEGMENT_DATA; GPIO_Init(GPIOC, &init); // Wait delayCycles(SEGMENT_DELAY); delayCycles(SEGMENT_DELAY); // Clear to zero GPIO_ResetBits(GPIOC, SEGMENT_DATA | SEGMENT_CLK | SEGMENT_WRL); delayCycles(SEGMENT_DELAY); delayCycles(SEGMENT_DELAY); } /*********************************************************************************/ /** * Write to segment */ void writeToSegment(int letter) { // Read bit by bit, push into register using Data and Clk; after all done, set Wrt; // Shift register is 100MHZ => we do not need to wait in int i; BitAction bit; for( i = 0; i<8; i++) { bit = (BitAction)( 1 -(letter & 0x1) ); //LSB, active in zero letter = letter >> 1; //shift right // set bit value GPIO_WriteBit(GPIOC, SEGMENT_DATA, bit); delayCycles(SEGMENT_DELAY); // set clock GPIO_SetBits(GPIOC, SEGMENT_CLK); delayCycles(SEGMENT_DELAY); GPIO_ResetBits(GPIOC, SEGMENT_CLK); delayCycles(SEGMENT_DELAY); } // set WRL GPIO_SetBits(GPIOC, SEGMENT_WRL); delayCycles(SEGMENT_DELAY); GPIO_ResetBits(GPIOC, SEGMENT_WRL); delayCycles(SEGMENT_DELAY); } /*********************************************************************************/ /** * Delay ms */ void delayMS(vu32 ms) { int diff; timeStruct now = SYSTEM_CLOCK; while(1) { diff = getTimeDiff(now, SYSTEM_CLOCK); if( diff>=ms )return; } } /*********************************************************************************/ /** * Get segment equivalent code of given key */ int getSegmentEquivalentOfKey(int key) { switch(key) { case KEY_0: return SEGMENT_0; case KEY_1: return SEGMENT_1; case KEY_2: return SEGMENT_2; case KEY_3: return SEGMENT_3; case KEY_4: return SEGMENT_4; case KEY_5: return SEGMENT_5; case KEY_6: return SEGMENT_6; case KEY_7: return SEGMENT_7; case KEY_8: return SEGMENT_8; case KEY_9: return SEGMENT_9; case KEY_F: return SEGMENT_F; case KEY_N: return SEGMENT_N; } return SEGMENT_EMPTY; } /*********************************************************************************/ /** * Get number equivalent of given key */ int getNumberEquivalentOfKey(int key) { switch(key) { case KEY_0: return 0; case KEY_1: return 1; case KEY_2: return 2; case KEY_3: return 3; case KEY_4: return 4; case KEY_5: return 5; case KEY_6: return 6; case KEY_7: return 7; case KEY_8: return 8; case KEY_9: return 9; } return 0; } /*********************************************************************************/ /** * Get segment equivalent of digit */ int getSegmentEquivalentOfNumber(int digit) { switch(digit) { case 0: return SEGMENT_0; case 1: return SEGMENT_1; case 2: return SEGMENT_2; case 3: return SEGMENT_3; case 4: return SEGMENT_4; case 5: return SEGMENT_5; case 6: return SEGMENT_6; case 7: return SEGMENT_7; case 8: return SEGMENT_8; case 9: return SEGMENT_9; } return SEGMENT_EMPTY; } /*********************************************************************************/ /** * Configure LCD */ void configureLCD(void) { GPIO_InitTypeDef init; init.GPIO_Mode = GPIO_Mode_Out_PP; // All pins are the same Mode init.GPIO_Speed = GPIO_Speed_10MHz; // All pins are the same Speed // DATA init.GPIO_Pin = LCD_DATA4 | LCD_DATA5 | LCD_DATA6 | LCD_DATA7; GPIO_Init(LCD_DATA_PORT, &init); // RS + ENABLE init.GPIO_Pin = LCD_RS | LCD_ENABLE; GPIO_Init(LCD_SIGNAL_PORT, &init); // Write 0 GPIO_ResetBits(LCD_DATA_PORT, LCD_DATA4 | LCD_DATA5 | LCD_DATA6 | LCD_DATA7); GPIO_ResetBits(LCD_SIGNAL_PORT, LCD_RS | LCD_ENABLE ); } /*********************************************************************************/ /** * Send 4bit to lcd, LSB on data4; MSB on dat7 */ void sendDataBitsToLCD(int bits) { // set enable to 1 GPIO_SetBits(LCD_SIGNAL_PORT, LCD_ENABLE); // port C // send GPIO_WriteBit(LCD_DATA_PORT, LCD_DATA4, (BitAction)(bits & 0x1)); // port A GPIO_WriteBit(LCD_DATA_PORT, LCD_DATA5, (BitAction)((bits >> 1) & 0x1)); GPIO_WriteBit(LCD_DATA_PORT, LCD_DATA6, (BitAction)((bits >> 2) & 0x1)); GPIO_WriteBit(LCD_DATA_PORT, LCD_DATA7, (BitAction)((bits >> 3) & 0x1)); // reset enable to 0 delayCycles(LCD_DELAY); GPIO_ResetBits(LCD_SIGNAL_PORT, LCD_ENABLE); // port C } /*********************************************************************************/ /** * Send 8bit command to lcd, LSB on data4; MSB on dat7 */ void sendCommandToLCD(int command) { // 1st part - top bits first sendDataBitsToLCD( (command >> 4) & 0xF ); delayMS(1); // 2nd part sendDataBitsToLCD( command & 0xF ); delayMS(1); } /*********************************************************************************/ /** * Send string to LCD */ void LCDSendString(char* string) { while( *string!= '\0' ) { LCDSendChar(*string); // set char string++; // move to another char } } /*********************************************************************************/ /** * Send char to the LCD */ void LCDSendChar(int ch) { // set RS GPIO_SetBits(LCD_SIGNAL_PORT, LCD_RS); delayCycles(LCD_DELAY); // send sendCommandToLCD( getLCDLetterCommand(ch) ); // return RS to zero GPIO_ResetBits(LCD_SIGNAL_PORT, LCD_RS); // send to rs232 USARTsendChar(ch); } /*********************************************************************************/ /** * Initialize LCD */ void initializeLCD(void) { // After reset (power on) /* 1) pins are all in 0 => wait 15ms if U >= 4,5V, 40ms otherwise */ delayMS(40); /* 2) send 0011 on data bits and wait 4,1ms + */ sendDataBitsToLCD(0x3); delayMS(6); /* 3) send 0011 on data bits and wait 0,1ms + */ sendDataBitsToLCD(0x3); delayMS(1); /* 4) send 0011 on data bits and wait 4,1ms + */ sendDataBitsToLCD(0x3); delayMS(1); /* 5) configuration to 4B */ sendDataBitsToLCD(0x2); // 0010: 4b mode delayMS(1); // 2 lines: N = 1; 4bit interface: DL = 0; letter 5x8: F = 0 sendCommandToLCD(0x28); // 0010 10xx delayMS(1); sendCommandToLCD(0x08); // 0000 1000 : turn off delayMS(1); sendCommandToLCD(0x01); // 0000 0001 : clear delayMS(1); // increment address and move cursor 0000 0110 sendCommandToLCD(0x06); delayMS(1); /* 6) Power ON*/ sendCommandToLCD(0x0C); // 0000 1100 delayMS(1); /* 7) Set Cursor Home */ LCDSetCursorHome(); } /*********************************************************************************/ /** * Set cursor home */ void LCDSetCursorHome(void) { // write 0000 001x and wait 1,64ms sendCommandToLCD(0x02); delayMS(2); // send to usart USARTsendChar(128); } /*********************************************************************************/ /** * Set cursor to specific position */ void LCDSetCursor(int x, int y) { // 1st row 00h..13h // command 1aaa aaa; mask for addr = 0111 111 = 7F // 2nd row 40h..53h // wait 47us int addr; if( y>=0 && y<=1 && x>=0 && x<=19) { addr = 0x40 * y + x; sendCommandToLCD( 0x80 | (addr & 0x7F) ); delayMS(1); // send to usart USARTsendChar(128 + x + y * 20); } } /*********************************************************************************/ /** * Clear lcd */ void LCDClear(void) { // 0000 0001; wait 1,64ms sendCommandToLCD(0x01); delayMS(2); } /*********************************************************************************/ /** * Read input both from uart and from keyboard */ input readInput( void(*callFunction)(void) ) { pressedKey pk; input inp; inp.longN = FALSE; inp.longF = FALSE; inp.key = 0; while(1) { // call given function callFunction(); // make key cycle keyboardCycle(); // KEY if( keyboardIsPressed()==TRUE && keyboardLock==0 ) { pk = waitForKeyboardIsReleased(); if( pk.key == KEY_NONE )continue; // no relevant data if( pk.key == KEY_N ) { inp.key = 'N'; if( pk.time >= LONG_PRESS )inp.longN = TRUE; } else if( pk.key == KEY_F ) { inp.key = 'F'; if( pk.time >= LONG_PRESS )inp.longF = TRUE; } else{ inp.key = '0' + getNumberEquivalentOfKey(pk.key); } return inp; // UART }else if(UART_valid) { keyboardLock = 1; UART_valid = FALSE; switch( UART_last ) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': inp.key = UART_last; break; case 'N': case 'n': inp.key = 'N'; break; case 'F': case 'f': inp.key = 'F'; break; case 'W': case 'w': inp.key = 'N'; inp.longN = TRUE; break; case 'Q': case 'q': inp.key = 'F'; inp.longF = TRUE; break; } if( inp.key!=0 )return inp; // if valid } } } /*********************************************************************************/ /** * Create empty password */ password getEmptyPassword(void) { password pass; pass.value = 1; // start with 1 to ACK leading zeros pass.longN = FALSE; pass.longF = FALSE; pass.N = FALSE; pass.F = FALSE; return pass; } /*********************************************************************************/ /** * Create empty user */ user getEmptyUser(void) { user u = { 0x69696969, 1, {32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}, 0 }; return u; } /*********************************************************************************/ #endif