/* LU3_console.c Implement console communication and commands in FLISP LU3 systems */ #include "misc.h" #include "stm32f10x_usart.h" #include "stm32f10x_exti.h" #include "stm32f10x_rcc.h" #include "stm32f10x_gpio.h" # ifdef LU4 #include "lu4.h" #else #include "lu3.h" #endif typedef struct{ unsigned char in; unsigned char out; unsigned char count; unsigned char buff[USARTBUFFSIZE]; }FIFO_TypeDef; static FIFO_TypeDef U1Tx; static int buffer_o; static unsigned char console_state; static void bufferInit( FIFO_TypeDef *buffer ) { buffer->count = 0; //0 bytes in buffer buffer->in = 0; //index points to start buffer->out = 0; //index points to start buffer_o = 0; console_state = 0; } static void bufferPut( FIFO_TypeDef *buffer, unsigned char ch ) { if( buffer->count==USARTBUFFSIZE ){ buffer_o++; return ; //buffer full } buffer->buff[buffer->in++]=ch; buffer->count++; if(buffer->in==USARTBUFFSIZE) buffer->in=0; //wrap } static int bufferGet( FIFO_TypeDef *buffer, unsigned char *ch) { if(buffer->count==0) return 0; //buffer empty *ch=buffer->buff[buffer->out++]; buffer->count--; if(buffer->out==USARTBUFFSIZE) buffer->out=0;//start from beginning return 1; } void consoleInit( void ) { bufferInit( &U1Tx ); /* init transmit buffer */ } void consoleOut(unsigned char ch) { bufferPut(&U1Tx, ch); USART_ITConfig(USART1, USART_IT_TXE, ENABLE); } static unsigned char hex( unsigned char ch) { switch( ch ) { case '0': case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9': return ch - '0'; case 'a': case 'b':case 'c':case 'd':case 'e':case 'f': return ch - 'a' + 10; case 'A': case 'B':case 'C':case 'D':case 'E':case 'F': return ch - 'A' + 10; } return 0xFF; } unsigned char binToAscii( unsigned char c ) { switch( c ) { case 0: case 1:case 2:case 3:case 4:case 5:case 6:case 7:case 8:case 9: return c + '0'; case 0xA: case 0xB:case 0xC:case 0xD:case 0xE:case 0xF: return c + 'A'-10; } return '?'; } void sendAsAscii( unsigned char c ) { if( interactive_mode ){ consoleOut ( binToAscii( (c >> 4) & 0xF)); consoleOut ( binToAscii( c & 0xF )); } } void sendAscii( unsigned char c ) { if( interactive_mode ) consoleOut ( c ); } void sendEOT( void ) { if( interactive_mode ) consoleOut ( '\n' ); } /* console in states: 0: initial 1: W 2: R 3: WM 4: RM RM x1 (accept) x1 valid hex 5: WR 6: RR RR x1 (accept) x1 valid register 7: WM x1 x1 valid hex WM x1 x2 x2 valid hex 8: WM x1 x1 valid hex WM x1 x2 x3 (accept) x2/x3 valid hex 9: WR x1 x1 valid register WR x1 x2 x2 valid register 10: WR x1 x1 valid register WR x1 x2 (accept) x2/x3 valid register */ void USART1_IRQHandler(void) { static unsigned char x1,x2,x3,x4; unsigned char ch; CMD c; if (USART_GetITStatus(USART1, USART_IT_TXE) != RESET) { if (bufferGet(&U1Tx, &ch) == 1)//if buffer read { USART_SendData(USART1, ch); } else//if buffer empty { //disable Transmit Data Register empty interrupt USART_ITConfig(USART1, USART_IT_TXE, DISABLE); } } /* If Overrun occures, clear the OVR condition */ if (USART_GetFlagStatus(USART1, USART_FLAG_ORE) != RESET) { USART_ClearITPendingBit(USART1, USART_FLAG_ORE); } //if Receive interrupt if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) { ch=(unsigned char)USART_ReceiveData(USART1); sendAscii( ch ); switch ( console_state ) { case 0: if( (ch == 'i') || (ch=='I')) { c.message = INTERACTIVE_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'q') || (ch =='Q') ) { c.message = QUIET_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'v') || (ch =='V') ) { c.message = GET_VERSION; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 't') || (ch=='T')) { if( ! toggleTestMode() ) { c.message = TEST_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); } break; } if( (ch == 'a') || (ch=='A')) { c.message = FLISP_RESET; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #ifndef LU4 if( (ch == 'n') || (ch=='N')) { c.message = FLISP_NF; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 'c') || (ch=='C')) { c.message = FLISP_CLK; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } #endif if( (ch == 'e') || (ch=='E')) { c.message = RUN_MODE; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } if( (ch == 's') || (ch=='S')) { c.message = STEP_INSTRUCTION; c.p1 = 0; c.p2 = 0; putCmd( &c ); break; } else if( (ch == 'w')||(ch=='W') ) console_state=1; else if( (ch == 'r')||(ch=='R') ) console_state=2; break; case 1: if( (ch == 'm')||(ch=='M') ) console_state=3; else if( (ch == 'r')||(ch=='R') ) console_state=5; else console_state=0; break; case 2: if( (ch == 'm')||(ch=='M') ) console_state=4; else if( (ch == 'r')||(ch=='R') ) console_state=6; else console_state=0; break; case 3: x1 = hex( ch ); if( x1 != 0xFF) console_state=7; // WM x else console_state=0; break; case 4: x1 = hex( ch ); if( x1 != 0xFF) /* seen RM x */ console_state=11; else console_state=0; break; case 5: x1 = translateFlispRegister( ch ); if( x1 != 0xFF) console_state=9; else console_state=0; break; case 6: x1 = translateFlispRegister( ch ); if( x1 != 0xFF) /* Accept RR x1 */ { c.message = REGISTER_READ; c.p1 = x1; c.p2 = 0; putCmd( &c ); } console_state=0; break; case 7: x2 = hex( ch ); if( x2 != 0xFF) /* seen WM x1 x2 */ { console_state=8; }else console_state=0; break; case 8: x3 = hex( ch ); if( x3 != 0xFF) /* seen WM x1|x2 x3 */ console_state=12; else console_state=0; break; case 9: x2 = hex( ch ); if( x2 != 0xFF) /* seen RW x1 x? */ { console_state=10; } else console_state=0; break; case 10: x3 = hex( ch ); if( x3 != 0xFF) /* Accept RW x1 x2|x3 */ { c.message = REGISTER_WRITE; c.p1 = x1; c.p2 = ( x2 << 4 )| x3 ; putCmd( &c ); } console_state=0; break; case 11: x2 = hex( ch ); if( x2 != 0xFF) /* Accept RM xx */ { c.message = MEMORY_READ; c.p1 = ( x1 << 4 )| x2 ; c.p2 = 0; putCmd( &c ); } console_state=0; break; case 12: x4 = hex( ch ); if( x4 != 0xFF) /* accptn WM x1|x2 x3|x4 */ { c.message = MEMORY_WRITE; c.p1 = ( x1 << 4 )| x2 ; c.p2 = ( x3 << 4 )| x4 ; putCmd( &c ); } console_state=0; break; default: console_state=0; } } }