/* Fixa initiering av parallellportar 2012-10-19 Started RoJ 2012-12-13 BETA-version RoJ */ #include "misc.h" #include "stm32f10x_usart.h" #include "stm32f10x_exti.h" #include "stm32f10x_rcc.h" #include "stm32f10x_gpio.h" #include "lu3.h" static unsigned short switch_status_array; static unsigned char memory[256]; static unsigned char address; static unsigned char autoaddress; static unsigned char modifydata; unsigned char interactive_mode; /* Chip initialisation */ void initGPIO(void ) { // unsigned char i; EXTI_InitTypeDef EXTI_InitStructure; /* EXTI structure to init EXT */ NVIC_InitTypeDef NVIC_InitStructure; /* NVIC structure to set up NVIC controller */ GPIO_InitTypeDef GPIO_InitStructure; USART_ClockInitTypeDef USART_ClockInitStructure; USART_InitTypeDef USART_InitStructure; //#if 0 GPIO_AFIODeInit(); GPIO_DeInit(GPIOA); GPIO_DeInit(GPIOB); GPIO_DeInit(GPIOC); USART_DeInit(USART1); //#endif RCC_APB2PeriphClockCmd( RCC_APB2Periph_USART1, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE ); RCC_APB2PeriphClockCmd( RCC_APB2Periph_AFIO, ENABLE); /* PA13 - JTMS */ /* PA14 - JTCK */ /* PA15 - JTDI */ /* PB4 - JTRST */ /* PB3 - JTDO */ /* PA9 - USART TX */ /* PA10 - USART RX */ /* PA11 - USART CTS not used*/ /* PA12 - USART RTS not used */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //Set USART1 Tx (PA.09) as AF push-pull GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //Set USART1 Rx (PA.10) as input floating // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_ClockStructInit(&USART_ClockInitStructure); //Write USART1 parameters USART_ClockInit(USART1, &USART_ClockInitStructure); // USART_InitStructure.USART_BaudRate = 9600; USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No ; USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_Init(USART1, &USART_InitStructure); USART_Cmd(USART1, ENABLE); //Enable USART1 //configure NVIC NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn; //select NVIC channel to configure NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0xF; //set priority to lowest NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0xF; //set subpriority to lowest NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //enable IRQ channel NVIC_Init(&NVIC_InitStructure); //update NVIC registers USART_ITConfig(USART1, USART_IT_TXE, DISABLE); //disable Transmit Data Register empty interrupt USART_ITConfig(USART1, USART_IT_RXNE, ENABLE); //enable Receive Data register not empty interrupt /* PB7,6,5,2,1,0 - (One of) External interrupt lines */ /* PB 0 will be interrupt pin */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0); /* Connect EXTI Line to IRQ (port B, pin 0) */ EXTI_InitStructure.EXTI_Line = EXTI_Line0; /* Configure Button EXTI line */ EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; /* select interrupt mode */ EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; /* generate interrupt on falling edge */ EXTI_InitStructure.EXTI_LineCmd = ENABLE; /* enable EXTI line */ EXTI_Init(&EXTI_InitStructure); /* send values to registers */ /* configure NVIC */ NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; /* select NVIC channel to configure */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0F; /* set priority to lowest */ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0F; /* set subpriority to lowest */ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; /* enable IRQ channel */ NVIC_Init(&NVIC_InitStructure); /* update NVIC registers */ /* PC0-PC7, 8-bit inport */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; /* */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = ((uint16_t)0xFF); /* eight low bits */ GPIO_Init( GPIOC, &GPIO_InitStructure); /* PC8-PC15, 8 bit outport, Chip select signals */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* push/pull */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStructure.GPIO_Pin = ((uint16_t) 0xFF00); GPIO_Init( GPIOC, &GPIO_InitStructure); /* PB8-PB15, 8-bit outport, (Outbus high ) */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* push/pull */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Pin = ((uint16_t) 0xFF00); GPIO_Init( GPIOB, &GPIO_InitStructure); /* PA0-PA7, 8-bit outport, (Output low ) */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* push/pull */ GPIO_InitStructure.GPIO_Pin = ((uint16_t)0xFF); /* eight low bits */ GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init( GPIOA, &GPIO_InitStructure); consoleInit( ); } /* Low level read and write */ unsigned char readIn( unsigned char i ) { unsigned short d,r,j; /* Activate chip select in signal */ r = i; r = r << 12; r = r & 0xF000; /* Write value to port C (high byte) */ GPIOC->BRR = 0xF000; /* reset port bits */ GPIOC->BSRR = r; /* set bits */ /* Read 16 bit value from port C */ for( j = 0; j< 400; j++); d = GPIO_ReadInputData( GPIOC ); GPIOC->BRR = 0xFF00; /* reset port bits */ /* return low byte */ return (unsigned char) d ; } void outbusHigh( unsigned char c ) { // unsigned short j; unsigned int r = ( unsigned short ) c ; r = r << 8; /* Write byte to port B (high byte ) */ GPIOB->BRR = ((uint32_t) 0xFF00); /* reset port bits */ GPIOB->BSRR = r; /* set bits */ } void outbusLow( unsigned char c ) { unsigned short r; /* Write byte to port A (low byte ) */ r = c; GPIOA->BRR = ((uint32_t) 0xFF); /* reset port bits */ GPIOA->BSRR = r; /* set bits */ } void selectOut( unsigned char i ) { /* Activate chip select out signal */ int j; unsigned short r = (unsigned short) (i & 0xF); r = r << 8; /* Write value to port C, high word, (low byte) */ GPIOC->BRR = ((uint32_t) 0x0F00); /* reset port bits */ GPIOC->BSRR = r; /* set bits */ for( j = 0; j< 4000; j++); GPIOC->BRR = ((uint32_t) 0x0F00); /* reset port bits */ for( j = 0; j< 4000; j++); } /* Refresh/Update routines refresh - copy from hardware to internal data structures update - copy from internal data structures to hardware */ void refreshSwitches(void) { unsigned char c1, c2; c1 = readIn( 1 ); c2 = readIn( 2 ); switch_status_array = ((unsigned short) c2 << 8 ); switch_status_array |= (unsigned short) c1; switch_status_array &= 0x3FFF; } /* Utility routines */ int isDataSetMode( void) { /* return setting for data set mode switch */ refreshSwitches(); return (DATA_SET_MODE & switch_status_array) ; } int isDataDisplayMode( void) { return ( ! isDataSetMode() ); } int isAddressSetMode( void) { /* return setting for data set mode switch */ return (ADDRESS_SET_MODE & switch_status_array) ; } int isAddressDisplayMode( void) { return ( ! isAddressSetMode() ); } void clearDataPath( void ) { unsigned char i,j; outbusHigh (0); outbusLow (0); for( i = 1; i < 16; i++ ) { selectOut( i ); for( j = 0; j < 100; j++ ); } /* Clear displays */ outbusHigh(0xFF); outbusLow (0xFF); selectOut( 12 ); selectOut( 13 ); } //static unsigned char segcode[]={ 3, 0xF9 ,~6,~0x3B,~0x2F,~0x66,~0x6D,~0x3B,~0x3B,~0x3B,~0x3B,~0x3B,~0x3B,~0x3B,~0x3B,0x71 }; unsigned char tosegcode( unsigned char c ) { switch (c) { case 0: return 0xC0; case 1: return 0xF9; case 2: return 0xA4; case 3: return 0xB0; case 4: return 0x99; case 5: return 0x92; case 6: return 0x82; case 7: return 0xF8; case 8: return 0x80; case 9: return 0x98; case 0xA: return 0x88; case 0xB: return 0x83; case 0xC: return 0xC6; case 0xD: return 0xA1; case 0xE: return 0x86; case 0xF: return 0x8E; default: return 0xFF; } } void setDataDisplay( unsigned char value ) { outbusLow ( tosegcode( value & 0xF) ); outbusHigh ( tosegcode( (value >> 4)&0xF ) ); selectOut( 12 ); } void setAddressDisplay( unsigned char value ) { outbusLow ( tosegcode( value & 0xF) ); outbusHigh ( tosegcode( (value >> 4)&0xF ) ); selectOut( 13 ); } void EXTI0_IRQHandler(void) { static unsigned char mem_adr_toggle = 0; unsigned short stat; CMD c; /* switch interrupt handler */ refreshSwitches(); stat = switch_status_array & 0xFFFF; /* extract IRQ status bits */ c.p1 = 0; c.p2 = 0; if( stat & IRQ0_DATA_HIGH_INCREMENT) { if (!(DATA_SET_MODE & switch_status_array)) goto ackirq; c.message = MEM_DATA_H_INC; mem_adr_toggle ^= 0x80; if( (mem_adr_toggle & 0x80 )==0) goto ackirq; }else if( stat & IRQ1_DATA_HIGH_DECREMENT) { if (!(DATA_SET_MODE & switch_status_array)) goto ackirq; c.message = MEM_DATA_H_DEC; mem_adr_toggle ^= 0x40; if( (mem_adr_toggle & 0x40 )==0) goto ackirq; }else if( stat & IRQ2_DATA_LOW_INCREMENT) { if (!(DATA_SET_MODE & switch_status_array)) goto ackirq; c.message = MEM_DATA_L_INC; mem_adr_toggle ^= 0x20; if( (mem_adr_toggle & 0x20 )==0) goto ackirq; }else if( stat & IRQ3_DATA_LOW_DECREMENT) { if (!(DATA_SET_MODE & switch_status_array)) goto ackirq; c.message = MEM_DATA_L_DEC; mem_adr_toggle ^= 0x10; if( (mem_adr_toggle & 0x10 )==0) goto ackirq; }else if( stat & IRQ4_ADDRESS_HIGH_INCREMENT) { if( isAddressDisplayMode()) goto ackirq; c.message = MEM_ADDR_H_INC; mem_adr_toggle ^= 8; if( (mem_adr_toggle & 8 )== 0) goto ackirq; }else if( stat & IRQ5_ADDRESS_HIGH_DECREMENT) { if( isAddressDisplayMode()) goto ackirq; c.message = MEM_ADDR_H_DEC; mem_adr_toggle ^= 4; if( (mem_adr_toggle & 4 )== 0) goto ackirq; }else if( stat & IRQ6_ADDRESS_LOW_INCREMENT) { if( isAddressDisplayMode()) goto ackirq; c.message = MEM_ADDR_L_INC; mem_adr_toggle ^= 2; if( (mem_adr_toggle & 2 )== 0) goto ackirq; }else if( stat & IRQ7_ADDRESS_LOW_DECREMENT) { if( isAddressDisplayMode()) goto ackirq; c.message = MEM_ADDR_L_DEC; mem_adr_toggle ^= 1; if( (mem_adr_toggle & 1 )== 0) goto ackirq; }else if( stat & IRQ8_DATA_SET) { c.message = MEM_DATA_SET; //setAddressDisplay( 8 ); }else if( stat & IRQ9_FLISP_RESET) { c.message = FLISP_RESET; //setAddressDisplay( 9 ); }else if( stat & IRQ10_FLISP_CLK) { c.message = FLISP_CLK; //setAddressDisplay( 10 ); }else if( stat & IRQ11_FLISP_NF) { c.message = FLISP_NF; //setAddressDisplay( 11 ); }else { /* spurious interrupt */ } putCmd( &c ); ackirq: while( stat ){ outbusHigh( 0 ); outbusLow( 0) ; selectOut( 15 ); outbusHigh( 0xFF ); outbusLow( 0xFF) ; selectOut( 15 ); refreshSwitches(); stat = switch_status_array & 0xFFF; /* extract IRQ status bits */ /* Ack controller */ EXTI_ClearITPendingBit(EXTI_Line0); } } void updateDataDisplay( unsigned char cmd ) { if( isDataDisplayMode() ) { /* just update the display */ setDataDisplay( memory[address] ); }else{ /* Data modify mode */ switch( cmd ) { case MEM_DATA_H_INC: modifydata += 0x10; break; case MEM_DATA_H_DEC: modifydata -= 0x10; break; case MEM_DATA_L_INC: modifydata = (modifydata & 0xF0 ) + ((modifydata + 1) & 0xF); break; case MEM_DATA_L_DEC: modifydata = (modifydata & 0xF0 ) + ((modifydata - 1) & 0xF); break; } setDataDisplay( modifydata ); } } void updateAddressDisplay( unsigned char cmd ) { if( isAddressDisplayMode() ) { /* just update the display with memory address register */ setAddressDisplay( autoaddress ); }else{ /* Address modify mode */ switch( cmd ) { case MEM_ADDR_H_INC: address = address + 0x10; break; case MEM_ADDR_H_DEC: address = address - 0x10; break; case MEM_ADDR_L_INC: address = (address & 0xF0 ) + ((address + 1) & 0xF); break; case MEM_ADDR_L_DEC: address = (address & 0xF0 ) + ((address - 1) & 0xF); break; } setAddressDisplay( address ); } } void setMemory(unsigned char add, unsigned char data) { memory[add] = data; } unsigned char getMemory(unsigned char add ) { return memory[add]; } void setAutoAddress(unsigned char add) { autoaddress = add; } /* void banner(void) { unsigned char *cp; cp = BANNER_ID; while( *cp ) consoleOut (*cp++ ); sendEOT(); } */ void main( void ) { int i,j; PCMD p; // unsigned char ch; initGPIO(); /* core init, clock GPIO's, interrupt system etc uart init, console interface */ clearDataPath(); /* turn all LED's off */ /* Calm flipflops */ outbusHigh( 0 ); outbusLow( 0) ; selectOut( 15 ); outbusHigh( 0xFF ); outbusLow( 0xFF) ; selectOut( 15 ); #if 0 /* Startup delay to make something happen... */ for( i = 0; i <= 0xF ; i++ ) { setAddressDisplay( (unsigned char) i ); setDataDisplay( (unsigned char) i ); for( j = 0; j< 80000; j++); } /* Test diodes */ for( i = 1; i <= 11 ; i++ ) { outbusHigh( 0xFF ); outbusLow( 0xFF) ; selectOut( i ); for( j = 0; j< 900000; j++); outbusHigh( 0 ); outbusLow( 0) ; selectOut( i ); } #endif interactive_mode = 1; initCmd(); /* initialize buffered command handling */ doFlispReset(); /* reset state machine */ __enable_irq(); while(1) { if( (( p = getCmd() ) == ((PCMD) 0) )) { /* monitor data_set and address_set switches */ updateDataDisplay( 0 ); updateAddressDisplay( 0 ); if(isExternalOpcode() ) { doExternalOpcode(); } }else{ /* do command */ switch( (int) p->message ) { /* Commands */ case QUIET_MODE: interactive_mode = 0; break; case INTERACTIVE_MODE: interactive_mode = 1; break; case GET_VERSION: sendAsAscii( MAJOR_VERSION ); consoleOut('.'); sendAsAscii( MINOR_VERSION ); sendEOT(); break; case MEM_ADDR_H_INC: case MEM_ADDR_H_DEC: case MEM_ADDR_L_INC: case MEM_ADDR_L_DEC: updateAddressDisplay( p->message ); updateDataDisplay( 0 ); break; case MEM_DATA_H_INC: case MEM_DATA_H_DEC: case MEM_DATA_L_INC: case MEM_DATA_L_DEC: updateDataDisplay( p->message ); break; case FLISP_RESET: doFlispReset(); break; case FLISP_NF: doFlispNF(); break; case FLISP_CLK: doFlispClk(); break; case MEM_DATA_SET: consoleOut( 'D' ); if( isDataSetMode() ) { if( isAddressDisplayMode()) memory[address]= modifydata; else memory[autoaddress]= modifydata; } break; case MEMORY_WRITE: setMemory(p->p1, p->p2); if( interactive_mode ) updateAll(); break; case MEMORY_READ: sendAsAscii( getMemory( p->p1 ) ); sendEOT(); break; case REGISTER_WRITE: setFlispRegisterValue(p->p1, p->p2); if( interactive_mode ) updateAll(); break; case REGISTER_READ: sendAsAscii( getFlispRegisterValue( p->p1 ) ); sendEOT(); break; } } } }