├── .gitignore ├── Makefile ├── actions ├── button0.c ├── button1.c ├── button2.c ├── button3.c ├── button4.c ├── button5.c ├── button6.c ├── button7.c ├── disco.c ├── hello.c ├── help.c ├── hotbutton.c ├── hotbutton.h ├── hotkey.c ├── hotkey.h ├── laser.c ├── led.c ├── peek.c ├── poke.c ├── spi.c ├── spispy.c └── target.c ├── delaycycles.S ├── dkactiontable.S ├── dkbuttons.c ├── dkbuttons.h ├── dkclock.c ├── dkclock.h ├── dkebi.c ├── dkebi.h ├── dkfile.c ├── dkfile.h ├── dkfile_uart.c ├── dkfile_uart.h ├── dkinteractive.c ├── dkinteractive.h ├── dkstring.c ├── dkstring.h ├── dktables.S ├── dktables.h ├── dkterm.c ├── dkterm.h ├── dkvt100.c ├── dkvt100.h ├── hardware.h ├── readme.txt ├── timeout.c ├── timeout.h └── xplainer.c /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore objects and archives, anywhere in the tree. 2 | *.[oa] 3 | *.lst 4 | *.elf 5 | *.eep 6 | *.hex 7 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | TARGET = xplainer 3 | CSRC = xplainer.c dkfile.c dkfile_uart.c dkterm.c dkvt100.c dkstring.c dkinteractive.c dkbuttons.c dkclock.c dkebi.c timeout.c \ 4 | actions/button0.c actions/button1.c actions/button2.c actions/button3.c actions/button4.c actions/button5.c actions/button6.c actions/button7.c \ 5 | actions/help.c actions/peek.c actions/poke.c actions/hello.c actions/led.c actions/hotbutton.c actions/hotkey.c actions/disco.c actions/spi.c actions/spispy.c \ 6 | actions/target.c actions/laser.c 7 | ASRC = dktables.S dkactiontable.S delaycycles.S 8 | MCU_TARGET = atxmega128a1 9 | OPTIMIZE = -Os -mcall-prologues 10 | DEFS = -DF_CPU=32000000 -D_GLITCHER_VERSION_NUM=2 11 | LIBS = 12 | DEBUG = dwarf-2 13 | 14 | CC = avr-gcc 15 | ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs 16 | ALL_ASFLAGS = -mmcu=$(MCU_TARGET) -I. -x assembler-with-cpp $(ASFLAGS) 17 | CFLAGS = -g$(DEBUG) -Wall -Werror $(OPTIMIZE) -mmcu=$(MCU_TARGET) $(DEFS) -lm 18 | LDFLAGS = -Wl,-u,vfprintf -lprintf_flt 19 | #LDFLAGS += -Wl,--section-start=.bootloader=$(BOOTLOAD) 20 | #LDFLAGS += -Wl,--section-start=.flashfile=$(FLASHFILE) 21 | OBJ = $(CSRC:.c=.o) $(ASRC:.S=.o) 22 | 23 | OBJCOPY = avr-objcopy 24 | OBJDUMP = avr-objdump 25 | SIZE = avr-size 26 | 27 | HEX_FLASH_FLAGS = -R .eeprom -R .fuse -R .lock -R .signature 28 | #HEX_FLASH_FLAGS = -j .text -j .data -j .bootloader 29 | 30 | HEX_EEPROM_FLAGS = -j .eeprom 31 | HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load" 32 | HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings 33 | 34 | 35 | 36 | all: $(TARGET).elf lst text eep size 37 | 38 | $(TARGET).elf: $(OBJ) 39 | $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS) 40 | 41 | 42 | prog: clean all 43 | avrdude -p $(MCU_TARGET) -c jtag2 -P usb -U flash:w:$(TARGET).hex 44 | # avrdude -p $(MCU_TARGET) -c jtag2 -P usb -U flash:w:$(TARGET).hex -U eeprom:w:$(TARGET).eep:r 45 | # avrdude -p $(MCU_TARGET) -c stk500 -P /dev/ttyUSB1 -U flash:w:$(TARGET).hex -U eeprom:w:$(TARGET).eep:r 46 | 47 | clean: 48 | rm -rf *.o $(TARGET).elf *.eps *.bak *.a 49 | rm -rf actions/*.o 50 | rm -rf *.lst *.map $(EXTRA_CLEAN_FILES) 51 | rm -rf $(TARGET).hex 52 | rm -rf $(TARGET).eep 53 | 54 | size: $(TARGET).elf 55 | # $(SIZE) --target=$(MCU_TARGET) $(TARGET).elf 56 | # $(SIZE) -C --mcu=$(MCU_TARGET) $(TARGET).elf 57 | 58 | lst: $(TARGET).lst 59 | %.lst: %.elf 60 | $(OBJDUMP) -h -S $< > $@ 61 | 62 | %.o : %.S 63 | $(CC) -c $(ALL_ASFLAGS) $< -o $@ 64 | 65 | 66 | eep: $(TARGET).eep 67 | 68 | %.eep: %.elf 69 | $(OBJCOPY) -O binary $(HEX_EEPROM_FLAGS) $< $@ 70 | 71 | 72 | text: hex 73 | hex: $(TARGET).hex 74 | 75 | %.hex: %.elf 76 | $(OBJCOPY) -O ihex $(HEX_FLASH_FLAGS) $< $@ 77 | 78 | 79 | -------------------------------------------------------------------------------- /actions/button0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | 9 | // TODO: button should be debounced to avoid multiple triggers caused by a single button press 10 | 11 | char *dkaction_button0( char *line ) 12 | { 13 | PORTE.OUT = ~(1<<0); // turn on only LED0 14 | 15 | dkuart_stuff_string( 0, dk_hotbuttons[0] ); // stuff the hotbutton string defined for this button into uart buffer 16 | 17 | 18 | return line; 19 | } 20 | 21 | -------------------------------------------------------------------------------- /actions/button1.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | char *dkaction_button1( char *line ) 9 | { 10 | PORTE.OUT = ~(1<<1); // turn on only LED1 11 | 12 | dkuart_stuff_string( 0, dk_hotbuttons[1] ); // stuff the hotbutton string defined for this button into uart buffer 13 | 14 | 15 | return line; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /actions/button2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | char *dkaction_button2( char *line ) 9 | { 10 | PORTE.OUT = ~(1<<2); // turn on only LED2 11 | 12 | dkuart_stuff_string( 0, dk_hotbuttons[2] ); // stuff the hotbutton string defined for this button into uart buffer 13 | 14 | 15 | return line; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /actions/button3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | char *dkaction_button3( char *line ) 9 | { 10 | PORTE.OUT = ~(1<<3); // turn on only LED3 11 | 12 | dkuart_stuff_string( 0, dk_hotbuttons[3] ); // stuff the hotbutton string defined for this button into uart buffer 13 | 14 | 15 | return line; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /actions/button4.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | char *dkaction_button4( char *line ) 9 | { 10 | PORTE.OUT = ~(1<<4); // turn on only LED4 11 | 12 | dkuart_stuff_string( 0, dk_hotbuttons[4] ); // stuff the hotbutton string defined for this button into uart buffer 13 | 14 | 15 | return line; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /actions/button5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | char *dkaction_button5( char *line ) 9 | { 10 | PORTE.OUT = ~(1<<5); // turn on only LED5 11 | 12 | dkuart_stuff_string( 0, dk_hotbuttons[5] ); // stuff the hotbutton string defined for this button into uart buffer 13 | 14 | 15 | return line; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /actions/button6.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | char *dkaction_button6( char *line ) 9 | { 10 | PORTE.OUT = ~(1<<6); // turn on only LED6 11 | 12 | dkuart_stuff_string( 0, dk_hotbuttons[6] ); // stuff the hotbutton string defined for this button into uart buffer 13 | 14 | 15 | return line; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /actions/button7.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "../dkfile_uart.h" 5 | #include "hotbutton.h" 6 | 7 | 8 | char *dkaction_button7( char *line ) 9 | { 10 | PORTE.OUT = (uint8_t)~(1<<7); // turn on only LED7 11 | 12 | dkuart_stuff_string( 0, dk_hotbuttons[7] ); // stuff the hotbutton string defined for this button into uart buffer 13 | 14 | 15 | return line; 16 | } 17 | 18 | -------------------------------------------------------------------------------- /actions/disco.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../dkterm.h" 9 | #include "../dkstring.h" 10 | 11 | 12 | char *dkaction_disco( char *line ) 13 | { 14 | char *token=NULL; 15 | char animation_sequence[]="|/-\\"; 16 | uint8_t i=0; 17 | 18 | 19 | line = dkgettoken( line, token ); // read first token from the line 20 | if( strlen(token) ) 21 | srand( strtol( token, NULL, 0 ) ); 22 | 23 | 24 | printf_P( PSTR("Party time! (ctrl-c to quit)\n") ); 25 | 26 | while( io_ctrl_char != DKKEY_CTRLC ) // loop until a ctrl-c is received 27 | { 28 | PORTE.OUT = rand(); // set LED0-LED7 to random states 29 | 30 | if( !animation_sequence[++i] ) 31 | i=0; 32 | _putch( animation_sequence[i] ); // display next step in animation 33 | _putch( '\b' ); 34 | 35 | _delay_ms(200); 36 | } 37 | io_ctrl_char = 0; // unset ctrl-c signal 38 | _flushuntil( DKKEY_CTRLC ); // flush everything up to and including ctrl-c from input buffer 39 | 40 | puts( " " ); 41 | 42 | 43 | return line; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /actions/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | char *dkaction_hello( char *line ) 5 | { 6 | printf( "Hello, world!\n" ); 7 | 8 | 9 | return line; 10 | } 11 | -------------------------------------------------------------------------------- /actions/help.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | char *dkaction_help( char *line ) 6 | { 7 | printf_P( PSTR( 8 | "DK-INTERACTIVE help:\n" 9 | "\n" 10 | "PEEK
[len] (PEEK 0x2000 3 to display 3 bytes at 0x2000)\n" 11 | "POKE
[value ...] (POKE 0x2000 0xFF to set 0x2000=0xFF)\n" 12 | "HELLO (\"Hello, world!\" example action)\n" 13 | "BEEP (make a short, loud, beep with the speaker)\n" 14 | "LED <#> <1/0> (LED 2 0 to turn LED2 off)\n" 15 | "BUTTON<#> (BUTTON0 to perform BUTTON0 action)\n" 16 | "HOTBUTTON <#> <\"string\"> (HOTBUTTON 0 \"BEEP\\n\" for example)\n" 17 | "HOTBUTTON ? (list hotbutton definitions)\n" 18 | "HOTKEY <#> <\"string\"> (HOTKEY F2 \"BEEP\\n\" for example)\n" 19 | "HOTKEY ? (list hotkey definitions)\n" 20 | ) ); 21 | 22 | return line; 23 | } 24 | -------------------------------------------------------------------------------- /actions/hotbutton.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../dkfile_uart.h" 7 | #include "../dkterm.h" 8 | #include "../dkstring.h" 9 | #include "hotbutton.h" 10 | 11 | 12 | char dk_hotbuttons[DK_NUM_HOTBUTTONS][DK_HOTBUTTON_MAXLEN]= 13 | { 14 | "HELP\r", 15 | "PEEK ", 16 | "POKE ", 17 | "LED ", 18 | "BUTTON", 19 | "F6", // "BEEP\r", 20 | "F7", 21 | "F8" 22 | }; 23 | 24 | 25 | char *dkaction_hotbutton( char *line ) 26 | { 27 | char *token=NULL; 28 | uint8_t button; 29 | int i,n; 30 | 31 | 32 | line = dkgettoken( line, token ); // read first token from the line 33 | if( !strlen(token) ) 34 | return line; 35 | 36 | if( token[0] == '?' ) // HOTBUTTON ? = list hotbutton settings 37 | { 38 | for( i=0; i= DK_NUM_HOTBUTTONS || button < 0 ) 60 | return line; 61 | 62 | line = dkgettoken( line, token ); // read second token from the line 63 | 64 | if( token[0] == '\"' && token[strlen(token)-1] == '\"' ) 65 | { 66 | token[strlen(token)-1] = '\0'; // remove trailing quote from token 67 | token++; // remove leading quote from token 68 | } 69 | 70 | strncpy( dk_hotbuttons[ button ], dkunescape( token ), DK_HOTBUTTON_MAXLEN); 71 | dk_hotbuttons[button][DK_HOTBUTTON_MAXLEN-1] = '\0'; 72 | 73 | printf_P( PSTR("BUTTON%d = \""), button, dk_hotbuttons[ button ] ); 74 | 75 | for( n=0; dk_hotbuttons[button][n]; n++ ) 76 | { 77 | if( dk_hotbuttons[button][n] == '\r' || dk_hotbuttons[button][n] == '\n' ) 78 | { 79 | _putch( '\\' ); // print escaped newlines 80 | _putch( 'n' ); 81 | } 82 | else 83 | _putch( dk_hotbuttons[button][n] ); 84 | } 85 | printf_P( PSTR("\"\n") ); 86 | 87 | 88 | return line; 89 | } 90 | 91 | -------------------------------------------------------------------------------- /actions/hotbutton.h: -------------------------------------------------------------------------------- 1 | 2 | #define DK_NUM_HOTBUTTONS 8 3 | #define DK_HOTBUTTON_MAXLEN 16 4 | 5 | extern char dk_hotbuttons[DK_NUM_HOTBUTTONS][DK_HOTBUTTON_MAXLEN]; 6 | -------------------------------------------------------------------------------- /actions/hotkey.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../dkfile_uart.h" 8 | #include "../dkterm.h" 9 | #include "../dkstring.h" 10 | #include "hotkey.h" 11 | 12 | //char dk_funckeystr[10][16]={ "HELP\n", "PEEK ", "POKE ", "LED ", "BUTTON", "BEEP\n", "F7", "F8", "F9", "F10" }; 13 | 14 | char dk_hotkeys[DK_NUM_HOTKEYS][DK_HOTKEY_MAXLEN]= 15 | { 16 | "HELP\r", 17 | "PEEK ", 18 | "POKE ", 19 | "LED ", 20 | "BUTTON", 21 | "BEEP\r", 22 | "F7", 23 | "F8", 24 | "F9", 25 | "F10", 26 | "F11", 27 | "F12" 28 | }; 29 | 30 | 31 | char *dkaction_hotkey( char *line ) 32 | { 33 | char *token=NULL; 34 | uint8_t hotkey; 35 | int i,n; 36 | 37 | 38 | line = dkgettoken( line, token ); // read first token from the line 39 | if( !strlen(token) ) 40 | return line; 41 | 42 | if( token[0] == '?' ) // HOTKEY ? = list hotkey settings 43 | { 44 | for( i=0; i<8; i++ ) 45 | { 46 | printf_P( PSTR("F%d = \""), i+1, dk_hotkeys[i] ); 47 | 48 | for( n=0; dk_hotkeys[i][n]; n++ ) 49 | { 50 | if( dk_hotkeys[i][n] == '\r' || dk_hotkeys[i][n] == '\n' ) 51 | { 52 | _putch( '\\' ); // print escaped newlines 53 | _putch( 'n' ); 54 | } 55 | else 56 | _putch( dk_hotkeys[i][n] ); 57 | } 58 | printf_P( PSTR("\"\n") ); 59 | } 60 | 61 | return line; 62 | } 63 | 64 | if( tolower( token[0] ) == 'f' ) 65 | hotkey = strtol( token+1, NULL, 0 )-1; // F1=0, F2=1, etc 66 | else 67 | hotkey = strtol( token, NULL, 0 ); // read index 0, 1, 2, etc 68 | 69 | if( hotkey >= DK_NUM_HOTKEYS || hotkey < 0 ) 70 | return line; 71 | 72 | line = dkgettoken( line, token ); // read second token from the line 73 | 74 | if( token[0] == '\"' && token[strlen(token)-1] == '\"' ) 75 | { 76 | token[strlen(token)-1] = '\0'; // remove trailing quote from token 77 | token++; // remove leading quote from token 78 | } 79 | 80 | strncpy( dk_hotkeys[ hotkey ], dkunescape( token ), DK_HOTKEY_MAXLEN); 81 | dk_hotkeys[ hotkey ] [DK_HOTKEY_MAXLEN-1 ] = '\0'; 82 | 83 | printf_P( PSTR("F%d = \""), hotkey+1, dk_hotkeys[ hotkey ] ); 84 | 85 | for( n=0; dk_hotkeys[hotkey][n]; n++ ) 86 | { 87 | if( dk_hotkeys[hotkey][n] == '\r' || dk_hotkeys[hotkey][n] == '\n' ) 88 | { 89 | _putch( '\\' ); // print escaped newlines 90 | _putch( 'n' ); 91 | } 92 | else 93 | _putch( dk_hotkeys[hotkey][n] ); 94 | } 95 | printf_P( PSTR("\"\n") ); 96 | 97 | 98 | return line; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /actions/hotkey.h: -------------------------------------------------------------------------------- 1 | 2 | #define DK_NUM_HOTKEYS 12 3 | #define DK_HOTKEY_MAXLEN 16 4 | 5 | extern char dk_hotkeys[DK_NUM_HOTKEYS][DK_HOTKEY_MAXLEN]; 6 | -------------------------------------------------------------------------------- /actions/laser.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../dkterm.h" 7 | #include "../hardware.h" 8 | #include "../dkstring.h" 9 | 10 | 11 | 12 | void Delay_ms(int n) { 13 | while (n--) { 14 | _delay_ms(1); 15 | } 16 | } 17 | 18 | char *dkaction_laser( char *line ) 19 | { 20 | char *token = NULL; 21 | int glitch_len = 100; 22 | int delay_len = 200; 23 | 24 | line = dkgettoken( line, token ); 25 | if( strlen(token) ) 26 | { 27 | glitch_len = strtoul(token,NULL,0); 28 | 29 | line = dkgettoken( line, token ); 30 | if( strlen(token) ) 31 | { 32 | delay_len = strtoul(token,NULL,0); 33 | } 34 | } 35 | 36 | 37 | 38 | printf( "Laser pointer test...\n" ); 39 | 40 | while( io_ctrl_char != DKKEY_CTRLC ) 41 | { 42 | G2981_PORT.DIRSET = (1< 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../dkstring.h" 7 | 8 | 9 | char *dkaction_led( char *line ) 10 | { 11 | char *token=NULL; 12 | int led; 13 | int status; 14 | 15 | 16 | line = dkgettoken( line, token ); // read first token from the line 17 | if( !strlen(token) ) 18 | return line; 19 | 20 | led = strtol( token, NULL, 0 ); 21 | 22 | 23 | line = dkgettoken( line, token ); // read second token from the line 24 | if( strlen(token) ) 25 | status = strtol( token, NULL, 0 ); // a status was specified 26 | else 27 | status = (PORTE.OUT & (1< 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../dkstring.h" 7 | 8 | 9 | char *dkaction_peek( char *line ) 10 | { 11 | char *token=NULL; 12 | uint32_t address; 13 | uint32_t len=1; 14 | uint32_t i; 15 | 16 | 17 | line = dkgettoken( line, token ); // read first token from the line 18 | if( !strlen(token) ) 19 | return line; 20 | 21 | address = strtol( token, NULL, 0 ); 22 | 23 | line = dkgettoken( line, token ); // read first token from the line 24 | if( strlen(token) ) 25 | len = strtol( token, NULL, 0 ); 26 | 27 | 28 | for( i=0; i 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../dkstring.h" 7 | 8 | 9 | char *dkaction_poke( char *line ) 10 | { 11 | char *token=NULL; 12 | unsigned int address; 13 | unsigned char data; 14 | int n=0; 15 | 16 | 17 | line = dkgettoken( line, token ); // read first token from the line 18 | if( !strlen(token) ) 19 | return line; 20 | 21 | address = strtol( token, NULL, 0 ); 22 | 23 | 24 | line = dkgettoken( line, token ); // read second token from the line 25 | while( strlen(token) ) 26 | { 27 | if( !(n%16) ) 28 | { 29 | if( n ) 30 | printf_P( PSTR("\n") ); 31 | printf_P( PSTR("%04X="), address+n ); 32 | } 33 | 34 | data = strtol( token, NULL, 0 ); 35 | 36 | printf_P( PSTR(" %02X"), data ); 37 | 38 | *( (unsigned char *)(address+n) ) = data; 39 | 40 | line = dkgettoken( line, token ); // read next token from the line 41 | n++; 42 | } 43 | 44 | printf_P( PSTR("\n") ); 45 | 46 | 47 | return line; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /actions/spi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../dkstring.h" 8 | #include "../dkterm.h" 9 | 10 | 11 | // SPI master transmit len bytes from data 12 | int spi_m_tx( uint8_t *data, int len ); 13 | 14 | 15 | char *dkaction_spi( char *line ) 16 | { 17 | char *token=NULL; 18 | uint8_t data[255]; // data to be transmitted 19 | int len; 20 | int i; 21 | 22 | 23 | line = dkgettoken( line, token ); // read first token from the line 24 | for( len=0; strlen(token); line=dkgettoken(line, token), len++ ) // loop through all tokens on the line 25 | data[ len ] = strtol( token, NULL, 16 ); // convert token to hex byte 26 | 27 | if( !len ) 28 | return line; // length == 0, return 29 | 30 | printf_P( PSTR("SPI TX:") ); // print data to be transmitted 31 | for( i=0; i 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../dkstring.h" 11 | #include "../dkterm.h" 12 | 13 | 14 | ////////////////////////////////////////////////////////////////////// 15 | // SPIF (Xplained J1) = primary slave (MOSI) 16 | // SPIC (Xplained J4) = secondary slave (MISO) 17 | ////////////////////////////////////////////////////////////////////// 18 | 19 | 20 | ////////////////////////////////////////////////////////////////////// 21 | // if SPISPY_BUFLEN is made > 255, head and tail pointers need to be changed from uint8_t to uint16_t 22 | #define SPISPY_BUFLEN 255 23 | 24 | volatile uint8_t spydata_mosi[ SPISPY_BUFLEN ]; 25 | volatile uint8_t spydata_miso[ SPISPY_BUFLEN ]; 26 | volatile uint8_t spy_mosi_head, spy_mosi_tail; // head and tail pointer for circular buffer 27 | volatile uint8_t spy_miso_head, spy_miso_tail; 28 | 29 | 30 | ////////////////////////////////////////////////////////////////////// 31 | char *dkaction_spispy( char *line ) 32 | { 33 | spy_mosi_head = 0; 34 | spy_mosi_tail = 0; 35 | spy_miso_head = 0; 36 | spy_miso_tail = 0; 37 | 38 | 39 | // setup SPIF as slave 40 | SPIF.INTCTRL = 0; // no SPIF interrupt (we only need one interrupt, since data is synchronous) 41 | SPIF.CTRL = SPI_ENABLE_bm | (1<= SPISPY_BUFLEN ) 82 | spy_mosi_tail = 0; 83 | if( spy_miso_tail >= SPISPY_BUFLEN ) 84 | spy_miso_tail = 0; 85 | } 86 | -------------------------------------------------------------------------------- /actions/target.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../dkterm.h" 11 | #include "../dkstring.h" 12 | #include "../hardware.h" 13 | #include "../dkfile_uart.h" 14 | #include "../timeout.h" 15 | 16 | 17 | //-------------------------------------------------------------------- 18 | 19 | DKFILE *t_uart = NULL; 20 | 21 | 22 | //-------------------------------------------------------------------- 23 | 24 | void t_open( void ) 25 | { 26 | // target rst = low 27 | TRST_PORT.OUTCLR = (1<devfile->info)->_flag &= ~DKUART_FLAG_TERMINAL; 102 | 103 | if( !t_uart ) 104 | t_uart = dkfopen( "COM1:115200,N,8,1", "r+" ); 105 | 106 | 107 | PORTD.DIR = 0x00; 108 | PORTD.OUT = 0x3F; 109 | PORTD.PIN0CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 110 | PORTD.PIN1CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 111 | PORTD.PIN2CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 112 | PORTD.PIN3CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 113 | PORTD.PIN4CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 114 | PORTD.PIN5CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 115 | 116 | PORTR.DIR = 0x00; 117 | PORTR.OUT = 0x03; 118 | PORTR.PIN0CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 119 | PORTR.PIN1CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 120 | 121 | PORTE.OUTSET = (1<<0); 122 | PORTE.OUTCLR = (1<<1); 123 | PORTE.OUTSET = (1<<2); 124 | PORTE.OUTSET = (1<<3); 125 | 126 | 127 | while( PORTD.IN & (1<<0) ) 128 | { // if a button is held down then break of out passthru mode 129 | if( !(PORTD.IN & (1<<2)) ) 130 | { 131 | // target rst = low 132 | TRST_PORT.OUTCLR = (1<devfile->info)->_flag |= DKUART_FLAG_TERMINAL; 150 | 151 | 152 | return line; 153 | } 154 | 155 | //-------------------------------------------------------------------- 156 | 157 | char *dkaction_glitch( char *line ) 158 | { 159 | if( !t_uart ) 160 | t_uart = dkfopen( "COM1:115200,N,8,1", "r+" ); 161 | 162 | while( io_ctrl_char != DKKEY_CTRLC ) 163 | { 164 | while( !dkfeof(t_uart) && io_ctrl_char != DKKEY_CTRLC ) 165 | _putch(dkfgetc(t_uart)); 166 | 167 | 168 | while( PORTF.IN & (1<<1) && io_ctrl_char != DKKEY_CTRLC ) 169 | { 170 | if( _kbhit() && _getch() == 'r' ) 171 | { 172 | // target rst = low 173 | TRST_PORT.OUTCLR = (1<= 0 && last_rx == stop_char ) 413 | stop_char_received = 1; 414 | } 415 | 416 | // insert artifical slowdown 417 | for( i=0; i= 0 && last_rx == stop_char ) 425 | stop_char_received = 1; 426 | } 427 | 428 | if( stop_char_received ) 429 | break; 430 | 431 | t_timeout_after_ms(50); 432 | while( !(PORTF.IN & (1<<4)) && io_ctrl_char != DKKEY_CTRLC ) 433 | { 434 | if( !t_timeout_check() ) 435 | continue; // do nothing until timeout expires (wait for signal from target on PF4) 436 | 437 | // timeout has expired, reset the target 438 | 439 | // target rst = low 440 | TRST_PORT.OUTCLR = (1<=0 && (unsigned char)last_rx == stop_after_rx ) 672 | break; 673 | } 674 | 675 | if( glitch_delay 0x7E ) 951 | // printf_P(PSTR("{%02X}"),last_rx); 952 | // else 953 | // printf_P(PSTR("%c"),last_rx); 954 | } 955 | 956 | dkfwrite( "12000\n", 1, strlen("12000\n"), t_uart ); 957 | _delay_ms( 5 ); 958 | 959 | while( !dkfeof(t_uart) && io_ctrl_char != DKKEY_CTRLC ) 960 | { 961 | last_rx = dkfgetc(t_uart); 962 | if( last_rx == '\n' ) 963 | break; 964 | // if( last_rx < 0x21 || last_rx > 0x7E ) 965 | // printf_P(PSTR("{%02X}"),last_rx); 966 | // else 967 | // printf_P(PSTR("%c"),last_rx); 968 | } 969 | 970 | if( dkfeof(t_uart) ) 971 | { 972 | printf_P(PSTR("\n")); 973 | continue; 974 | } 975 | 976 | 977 | printf_P(PSTR(".")); 978 | 979 | while( !dkfeof(t_uart) && dkfgetc(t_uart) != '\n' && io_ctrl_char != DKKEY_CTRLC ) 980 | ; 981 | 982 | printf_P(PSTR("R")); 983 | 984 | dkfwrite( "R 0 4\n", 1, strlen("R 0 4\n"), t_uart ); 985 | _delay_ms( 5 ); 986 | 987 | while( !dkfeof(t_uart) && dkfgetc(t_uart) != '\n' && io_ctrl_char != DKKEY_CTRLC ) 988 | ; 989 | 990 | if( dkfeof(t_uart) || dkfgetc(t_uart) == '1' ) 991 | { 992 | // printf_P(PSTR("\n")); 993 | continue; 994 | } 995 | 996 | printf_P(PSTR("1")); 997 | 998 | printf_P( PSTR("\nSuccess!\n") ); 999 | // return line; 1000 | 1001 | // if( dkfeof(t_uart) || dkfgetc(t_uart) == '9' ) 1002 | // { 1003 | // printf_P(PSTR("\n")); 1004 | // continue; 1005 | // } 1006 | // 1007 | // printf_P( PSTR("\nSuccess!\n") ); 1008 | // return line; 1009 | } 1010 | } 1011 | 1012 | return line; 1013 | } 1014 | 1015 | //-------------------------------------------------------------------- 1016 | 1017 | char *dkaction_glitchnoisp( char *line ) 1018 | { 1019 | uint16_t glitch_delay = 0; 1020 | uint16_t glitch_delay_start = 1600; 1021 | uint16_t glitch_delay_end = 1630; 1022 | char *token = NULL; 1023 | 1024 | 1025 | line = dkgettoken( line, token ); 1026 | if( strlen(token) ) 1027 | { 1028 | glitch_delay_start = strtoul(token,NULL,0); 1029 | 1030 | line = dkgettoken( line, token ); 1031 | if( strlen(token) ) 1032 | { 1033 | glitch_delay_end = strtoul(token,NULL,0); 1034 | } 1035 | } 1036 | 1037 | 1038 | printf_P( PSTR("Using delay range: %d - %d\n"), glitch_delay_start, glitch_delay_end ); 1039 | 1040 | if( !t_uart ) 1041 | t_uart = dkfopen( "COM1:115200,N,8,1", "r+" ); 1042 | 1043 | PORTCFG.VPCTRLA = 0; // virtual port 0 = porta 1044 | 1045 | while( io_ctrl_char != DKKEY_CTRLC ) 1046 | { 1047 | for( glitch_delay = glitch_delay_start; glitch_delay < glitch_delay_end && io_ctrl_char != DKKEY_CTRLC; glitch_delay++ ) 1048 | { 1049 | printf_P(PSTR("\r%d "), glitch_delay); 1050 | 1051 | // target rst = low 1052 | TRST_PORT.OUTCLR = (1<devfile->info)->_flag &= ~DKUART_FLAG_TERMINAL; 1176 | 1177 | if( !t_uart ) 1178 | t_uart = dkfopen( "COM1:115200,N,8,1", "r+" ); 1179 | 1180 | 1181 | PORTD.DIR = 0x00; 1182 | PORTD.OUT = 0x3F; 1183 | PORTD.PIN0CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1184 | PORTD.PIN1CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1185 | PORTD.PIN2CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1186 | PORTD.PIN3CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1187 | PORTD.PIN4CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1188 | PORTD.PIN5CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1189 | 1190 | PORTR.DIR = 0x00; 1191 | PORTR.OUT = 0x03; 1192 | PORTR.PIN0CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1193 | PORTR.PIN1CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 1194 | 1195 | PORTE.OUTSET = (1<<0); 1196 | PORTE.OUTCLR = (1<<1); 1197 | PORTE.OUTSET = (1<<2); 1198 | PORTE.OUTSET = (1<<3); 1199 | 1200 | while( PORTD.IN & (1<<0) ) 1201 | { 1202 | PORTE.OUTSET = (1<<0); 1203 | if( _kbhit() && _getch() == '?' ) 1204 | { // received '?' 1205 | printf_P(PSTR( "Synchronized\r\n" ) ); 1206 | 1207 | while( PORTD.IN & (1<<0) && PORTD.IN & (1<<1) ) 1208 | { 1209 | if( _kbhit() ) 1210 | { 1211 | c = _getch(); 1212 | _putch(c); 1213 | if( c == '\n' ) 1214 | break; 1215 | } 1216 | } 1217 | 1218 | printf_P(PSTR( "OK\r\n")); 1219 | 1220 | while( PORTD.IN & (1<<0) && PORTD.IN & (1<<1) ) 1221 | { 1222 | if( _kbhit() ) 1223 | { 1224 | c = _getch(); 1225 | _putch(c); 1226 | if( c == '\n' ) 1227 | break; 1228 | } 1229 | } 1230 | 1231 | printf_P(PSTR( "OK\r\n" )); 1232 | 1233 | PORTE.OUTCLR = (1<<0); 1234 | while( PORTD.IN & (1<<0) && PORTD.IN & (1<<1) ) 1235 | { 1236 | if( !dkfeof(t_uart) ) 1237 | _putch(dkfgetc(t_uart)); 1238 | 1239 | if(_kbhit()) 1240 | dkfputc(_getch(), t_uart); 1241 | } 1242 | } 1243 | } 1244 | 1245 | 1246 | ((struct _dk_uart *)dkterm_interfaces->devfile->info)->_flag |= DKUART_FLAG_TERMINAL; 1247 | 1248 | 1249 | return line; 1250 | } 1251 | 1252 | 1253 | //-------------------------------------------------------------------- 1254 | // note: perform reset after this to change mode 1255 | char *dkaction_disableisp( char *line ) 1256 | { 1257 | // target ISP = high 1258 | TISP_PORT.OUTSET = (1< 0x7E ) 1385 | // printf_P(PSTR("{%02X}"),last_rx); 1386 | // else 1387 | // printf_P(PSTR("%c"),last_rx); 1388 | } 1389 | 1390 | //LPC812 only: 1391 | dkfwrite( "12000\r\n", 1, strlen("12000\r\n"), t_uart ); 1392 | // dkfwrite( "12000\n", 1, strlen("12000\n"), t_uart ); 1393 | 1394 | 1395 | //TODO - the wait for PF0 to go low should be inside the asm() block so it is a proper timing reference 1396 | 1397 | t_timeout_after_ms(25); 1398 | while( !t_timeout_check() && io_ctrl_char != DKKEY_CTRLC ) 1399 | { 1400 | if( !dkfeof(t_uart) ) 1401 | { 1402 | last_rx = dkfgetc(t_uart); 1403 | if( last_rx == 0x0D ) 1404 | // if( last_rx == 'K' ) 1405 | break; 1406 | } 1407 | } 1408 | if( t_timeout_check() || io_ctrl_char == DKKEY_CTRLC ) 1409 | { 1410 | printf_P(PSTR("\n")); 1411 | continue; 1412 | } 1413 | 1414 | asm volatile( 1415 | 1416 | //TODO: wait for PF0 to go low 1417 | // while( PORTF.IN & (1<<1) && io_ctrl_char != DKKEY_CTRLC ) 1418 | 1419 | // "sts 0x0BC3, %0" "\n\t" // SPIF_DATA 1420 | "call DelayCycles" "\n\t" 1421 | "out 0x0011, %0" "\n\t" // vport0 out 1422 | "out 0x0011, %1" "\n\t" 1423 | "out 0x0011, %2" "\n\t" 1424 | "out 0x0011, %3" "\n\t" 1425 | "out 0x0011, %4" "\n\t" 1426 | "out 0x0011, %5" "\n\t" 1427 | "out 0x0011, %6" "\n\t" 1428 | "out 0x0011, %7" "\n\t" 1429 | "out 0x0011, %8" "\n\t" 1430 | : 1431 | : 1432 | "r" (glitch_form[0]), 1433 | "r" (glitch_form[1]), 1434 | "r" (glitch_form[2]), 1435 | "r" (glitch_form[3]), 1436 | "r" (glitch_form[4]), 1437 | "r" (glitch_form[5]), 1438 | "r" (glitch_form[6]), 1439 | "r" (glitch_form[7]), 1440 | "r" (noglitch_form), 1441 | "z" (glitch_delay) 1442 | ); 1443 | 1444 | 1445 | _delay_ms( 5 ); 1446 | 1447 | if( dkfeof(t_uart) ) 1448 | { 1449 | printf_P(PSTR("\n")); 1450 | continue; 1451 | } 1452 | 1453 | 1454 | printf_P(PSTR(".")); 1455 | 1456 | while( !dkfeof(t_uart) && dkfgetc(t_uart) != '\n' && io_ctrl_char != DKKEY_CTRLC ) 1457 | ; 1458 | 1459 | printf_P(PSTR("R")); 1460 | 1461 | //LPC812 only: 1462 | dkfwrite( "R 0 4\r\n", 1, strlen("R 0 4\r\n"), t_uart ); 1463 | // dkfwrite( "R 0 4\n", 1, strlen("R 0 4\n"), t_uart ); 1464 | 1465 | t_timeout_after_ms(50); 1466 | while( !t_timeout_check() && io_ctrl_char != DKKEY_CTRLC ) 1467 | { 1468 | if( !dkfeof(t_uart) ) 1469 | last_rx = dkfgetc(t_uart); 1470 | // if( last_rx == 0x0D ) 1471 | if( last_rx == 'R' ) 1472 | break; 1473 | } 1474 | if( t_timeout_check() || io_ctrl_char == DKKEY_CTRLC ) 1475 | { 1476 | printf_P(PSTR("\n")); 1477 | continue; 1478 | } 1479 | 1480 | 1481 | while( !dkfeof(t_uart) && dkfgetc(t_uart) != '\n' && io_ctrl_char != DKKEY_CTRLC ) 1482 | ; 1483 | 1484 | if( dkfeof(t_uart) || dkfgetc(t_uart) == '1' ) 1485 | { 1486 | // printf_P(PSTR("\n")); 1487 | continue; 1488 | } 1489 | 1490 | printf_P(PSTR("1")); 1491 | 1492 | printf_P( PSTR("\nSuccess!\n") ); 1493 | // return line; 1494 | 1495 | // if( dkfeof(t_uart) || dkfgetc(t_uart) == '9' ) 1496 | // { 1497 | // printf_P(PSTR("\n")); 1498 | // continue; 1499 | // } 1500 | // 1501 | // printf_P( PSTR("\nSuccess!\n") ); 1502 | // return line; 1503 | } 1504 | } 1505 | 1506 | return line; 1507 | } 1508 | 1509 | -------------------------------------------------------------------------------- /delaycycles.S: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | 4 | ;---------------------------------------------------------------------------- 5 | ; DelayCycles - delay for total of 23 + Z card cycles, including ldi/call/ret 6 | .global DelayCycles 7 | DelayCycles: 8 | lsr ZL 9 | brcs delay1 10 | 11 | delay1: 12 | lsr ZL 13 | brcc delay2 14 | nop 15 | rjmp delay2 16 | 17 | delay2: 18 | inc ZL 19 | inc ZH 20 | 21 | delay3_loop: 22 | nop 23 | dec ZL 24 | brne delay3_loop 25 | nop 26 | ldi ZL, 0x3F 27 | dec ZH 28 | brne delay3_loop 29 | 30 | 31 | ret 32 | 33 | -------------------------------------------------------------------------------- /dkactiontable.S: -------------------------------------------------------------------------------- 1 | ;--------------------------------------------------------------------- 2 | ; dkactiontable.S - table of action names and handler functions for DK-INTERACTIVE - Chris Gerlinsky, 2011 3 | ;--------------------------------------------------------------------- 4 | 5 | .nolist 6 | #include // Include device specific definitions. 7 | .list 8 | 9 | 10 | ;--------------------------------------------------------------------- 11 | ; FLASH - constants (in code segment) 12 | 13 | .section .text 14 | 15 | 16 | ; actions are found in actions/ directory 17 | 18 | .global dkactiontable 19 | dkactiontable: 20 | .string "help" ; keyword "help" 21 | .word dkaction_help ; dkaction_help() in actions/help.c 22 | 23 | .string "hello" ; keyword "hello" - "Hello, world!" example 24 | .word dkaction_hello ; dkaction_hello() in actions/hello.c 25 | 26 | .string "peek" 27 | .word dkaction_peek 28 | .string "poke" 29 | .word dkaction_poke 30 | 31 | .string "led" 32 | .word dkaction_led 33 | 34 | .string "spi" ; SPI master TX bytes 35 | .word dkaction_spi 36 | .string "spispy" ; SPISPY - dual slave SPI monitoring 37 | .word dkaction_spispy 38 | 39 | .string "hotbutton" 40 | .word dkaction_hotbutton 41 | .string "hotkey" 42 | .word dkaction_hotkey 43 | 44 | .string "disco" 45 | .word dkaction_disco 46 | 47 | .string "button0" 48 | .word dkaction_button0 49 | .string "button1" 50 | .word dkaction_button1 51 | .string "button2" 52 | .word dkaction_button2 53 | .string "button3" 54 | .word dkaction_button3 55 | .string "button4" 56 | .word dkaction_button4 57 | .string "button5" 58 | .word dkaction_button5 59 | .string "button6" 60 | .word dkaction_button6 61 | .string "button7" 62 | .word dkaction_button7 63 | 64 | 65 | .string "pon" 66 | .word dkaction_pon 67 | .string "poff" 68 | .word dkaction_poff 69 | 70 | .string "passthru" 71 | .word dkaction_passthru 72 | 73 | .string "glitch" 74 | .word dkaction_glitch 75 | 76 | .string "setglitch" 77 | .word dkaction_setglitch 78 | 79 | .string "target_glitch" 80 | .word dkaction_target_glitch 81 | 82 | .string "glitch3" 83 | .word dkaction_glitch3 84 | 85 | .string "rstloop" 86 | .word dkaction_rstloop 87 | 88 | .string "glitchcrp" 89 | .word dkaction_glitchcrp 90 | 91 | .string "glitchcrp2" 92 | .word dkaction_glitchcrp2 93 | 94 | .string "glitchnoisp" 95 | .word dkaction_glitchnoisp 96 | 97 | .string "rst_glitch" 98 | .word dkaction_rst_glitch 99 | 100 | .string "repass" 101 | .word dkaction_repass 102 | 103 | 104 | .string "laser" 105 | .word dkaction_laser 106 | 107 | 108 | .byte 0 ; end dkactiontable with an empty string (NULL) 109 | 110 | 111 | .align 2 ; code must be aligned on word boundary 112 | 113 | 114 | ;--------------------------------------------------------------------- 115 | ; dkfindaction 116 | ; r25:r24 in = ptr to string in ram 117 | ; r25:r24 out = ptr to action handler function 118 | ; note: side effect: string is converted to lowercase 119 | 120 | .func dkfindaction 121 | .global dkfindaction 122 | dkfindaction: 123 | ldi r23, hi8(dkactiontable) ; dkactiontable in FLASH is a list of names and matching functions 124 | ldi r22, lo8(dkactiontable) 125 | 126 | call dksearchtable 127 | 128 | lsr r25 ; shift address to the right (adjust from byte address to word address) 129 | ror r24 130 | 131 | ret 132 | 133 | .endfunc 134 | 135 | 136 | ;--------------------------------------------------------------------- 137 | 138 | -------------------------------------------------------------------------------- /dkbuttons.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "dkbuttons.h" 6 | 7 | 8 | unsigned char dk_buttons=0xFF; // used to remember what previous pin values were, to execut dkaction_buttonX() only on button press 9 | 10 | 11 | void dkbuttons_init( void ) 12 | { 13 | PORTD.DIR = 0x00; 14 | PORTD.OUT = 0x3F; 15 | PORTD.INTCTRL = PORT_INT0LVL_LO_gc; 16 | PORTD.INT0MASK = 0x3F; // button0-button5 = PD0-PD5 17 | PORTD.PIN0CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 18 | PORTD.PIN1CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 19 | PORTD.PIN2CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 20 | PORTD.PIN3CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 21 | PORTD.PIN4CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 22 | PORTD.PIN5CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 23 | 24 | PORTR.DIR = 0x00; 25 | PORTR.OUT = 0x03; 26 | PORTR.INTCTRL = PORT_INT0LVL_LO_gc; 27 | PORTR.INT0MASK = 0x03; // button6-button7 = PR0-PR1 28 | PORTR.PIN0CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 29 | PORTR.PIN1CTRL = PORT_OPC_PULLUP_gc | PORT_ISC_BOTHEDGES_gc; 30 | } 31 | 32 | 33 | ISR(PORTD_INT0_vect) 34 | { 35 | if( !(PORTD.IN & 1<<0) ) 36 | { 37 | if( dk_buttons & 1<<0 ) 38 | dkaction_button0( NULL ); 39 | } 40 | if( !(PORTD.IN & 1<<1) ) 41 | { 42 | if( dk_buttons & 1<<1 ) 43 | dkaction_button1( NULL ); 44 | } 45 | if( !(PORTD.IN & 1<<2) ) 46 | { 47 | if( dk_buttons & 1<<2 ) 48 | dkaction_button2( NULL ); 49 | } 50 | if( !(PORTD.IN & 1<<3) ) 51 | { 52 | if( dk_buttons & 1<<3 ) 53 | dkaction_button3( NULL ); 54 | } 55 | if( !(PORTD.IN & 1<<4) ) 56 | { 57 | if( dk_buttons & 1<<4 ) 58 | dkaction_button4( NULL ); 59 | } 60 | if( !(PORTD.IN & 1<<5) ) 61 | { 62 | if( dk_buttons & 1<<5 ) 63 | dkaction_button5( NULL ); 64 | } 65 | 66 | dk_buttons = (dk_buttons & 0xC0) | (PORTD.IN & 0x3F); 67 | } 68 | 69 | 70 | ISR(PORTR_INT0_vect) 71 | { 72 | if( !(PORTR.IN & 1<<0) ) 73 | { 74 | if( dk_buttons & 1<<6 ) 75 | dkaction_button6( NULL ); 76 | } 77 | if( !(PORTR.IN & 1<<1) ) 78 | { 79 | if( dk_buttons & 1<<7 ) 80 | dkaction_button7( NULL ); 81 | } 82 | 83 | dk_buttons = (dk_buttons & 0x3F) | ( (PORTR.IN<<6) & 0xC0); 84 | } 85 | -------------------------------------------------------------------------------- /dkbuttons.h: -------------------------------------------------------------------------------- 1 | 2 | void dkbuttons_init( void ); 3 | 4 | // dkaction_buttonX() functions are defined in actions/buttonX.c 5 | char *dkaction_button0( char *line ); 6 | char *dkaction_button1( char *line ); 7 | char *dkaction_button2( char *line ); 8 | char *dkaction_button3( char *line ); 9 | char *dkaction_button4( char *line ); 10 | char *dkaction_button5( char *line ); 11 | char *dkaction_button6( char *line ); 12 | char *dkaction_button7( char *line ); 13 | -------------------------------------------------------------------------------- /dkclock.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | 6 | // setup the clock 7 | 8 | void dk_clock_init( void ) 9 | { 10 | OSC_CTRL |= OSC_RC32MEN_bm; // enable 32 MHz RC oscillator 11 | 12 | while( !(OSC_STATUS & OSC_RC32MRDY_bm) ) 13 | ; // wait for 32 MHz RC oscillator to be ready 14 | 15 | _delay_ms(1); 16 | 17 | CPU_CCP = CCP_IOREG_gc; // set CPU_CCP to get access to CLK_CTRL 18 | CLK_CTRL = CLK_SCLKSEL_RC32M_gc; // select 32 MHz internal rc osc. 19 | CLK_PSCTRL = 0; // no divisor 20 | 21 | _delay_ms(1); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /dkclock.h: -------------------------------------------------------------------------------- 1 | 2 | void dk_clock_init( void ); 3 | -------------------------------------------------------------------------------- /dkebi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | // void ebi_init( void ) - configure the EBI 6 | // 7 | // Xplained board has a 47LC16M4A2 16M x 4 (8 MB) SDRAM 8 | // 8MB SDRAM will live at 000000-7FFFFF 9 | // (xmega internal memories occupy 0000-3FFF, so 004000-7FFFFF is visible SDRAM) 10 | // 11 | // NOTE: as of version 4.3.4 of avr-gcc (2011-05-22), only 16-bit address space is supported on AVR 12 | // the c compiler can access only 0000-FFFF 13 | void dk_ebi_init( void ) 14 | { 15 | PORTK.DIR = 0xFF; // set the three EBI ports as outputs 16 | PORTJ.DIR = 0xFF; // EBI module will automatically override pin direction for the data pins 17 | PORTH.DIR = 0xFF; 18 | 19 | 20 | EBI.CTRL = EBI_IFMODE_3PORT_gc; // 3 port EBI (PORTH/PORTJ/PORTK) 21 | EBI.REFRESH = 0x03FF; 22 | EBI.INITDLY = 0x0100; 23 | EBI.SDRAMCTRLA = EBI_SDROW_bm | EBI_SDCOL_10BIT_gc; 24 | EBI.SDRAMCTRLB = EBI_MRDLY_1CLK_gc | EBI_ROWCYCDLY_1CLK_gc | EBI_RPDLY_1CLK_gc; 25 | EBI.SDRAMCTRLC = EBI_WRDLY_1CLK_gc | EBI_ESRDLY_1CLK_gc | EBI_ROWCOLDLY_1CLK_gc; 26 | 27 | EBI.CS3.CTRLA = (0xF << 2) | 0x3; // 8M bytes, SDRAM (must use CS3 for SDRAM) 28 | } 29 | 30 | -------------------------------------------------------------------------------- /dkebi.h: -------------------------------------------------------------------------------- 1 | 2 | void dk_ebi_init( void ); 3 | -------------------------------------------------------------------------------- /dkfile.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | /* 3 | - this is implementing some of what should be in stdio.h 4 | */ 5 | //-------------------------------------------------------------------- 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #include "dkfile.h" 14 | #include "dkfile_uart.h" 15 | //#include "dkfile_twi.h" 16 | //#include "dkfile_spi.h" 17 | //#include "dkfile_eeprom.h" 18 | //#include "dkfile_flash.h" 19 | //#include "dkfile_ps2kbd.h" 20 | //#include "dkbasic.h" 21 | #include "dkterm.h" 22 | 23 | //-------------------------------------------------------------------- 24 | 25 | 26 | DKFILE *_dkfile_list=NULL; // linked list of open DKFILEs 27 | 28 | 29 | //-------------------------------------------------------------------- 30 | // return a pointer to DKFILE with BASIC filenum 31 | DKFILE *dkfilebynum( int filenum ) 32 | { 33 | DKFILE *stream; 34 | 35 | 36 | stream = _dkfile_list; // point to start of DKFILEs list 37 | if( !stream ) 38 | return NULL; // no files in open list 39 | 40 | while( stream->next ) 41 | { 42 | if( stream->filenum == filenum ) 43 | break; 44 | stream = stream->next; // follow list to end 45 | } 46 | 47 | if( stream->filenum != filenum ) 48 | return NULL; 49 | 50 | 51 | return stream; 52 | } 53 | 54 | 55 | //-------------------------------------------------------------------- 56 | 57 | DKFILE *dkfopen(const char *filename, const char *mode) 58 | { 59 | DKFILE *file_list; 60 | DKFILE *stream; 61 | int i=0; 62 | char devicestr[4]; 63 | 64 | // TODO: split this into str_to_comconfig ? 65 | 66 | stream = (DKFILE *)malloc( sizeof(DKFILE) ); 67 | if( !stream ) 68 | return NULL; // memory error! 69 | 70 | // initialize new FILE struct 71 | stream->next = NULL; 72 | stream->fd = i; // fd = index into open file chain of this stream 73 | stream->filenum = 0; 74 | stream->filename = (char *)malloc( strlen(filename)+1 ); 75 | if( !stream->filename ) 76 | return NULL; // memory error! 77 | strcpy( stream->filename, filename ); 78 | stream->_flag = 0; 79 | stream->io = NULL; 80 | 81 | 82 | while( (*mode) ) 83 | { 84 | switch( tolower( (*mode) ) ) 85 | { 86 | case 'r': 87 | stream->_flag |= DKFILE_FLAG_READ; 88 | break; 89 | 90 | case 'w': 91 | stream->_flag |= DKFILE_FLAG_WRITE; 92 | break; 93 | 94 | case 'a': 95 | stream->_flag |= DKFILE_FLAG_READ; 96 | stream->_flag |= DKFILE_FLAG_WRITE; 97 | // start at end of file 98 | break; 99 | 100 | case '+': // TODO: handle r+ / w+ modes properly 101 | stream->_flag |= DKFILE_FLAG_READ; 102 | stream->_flag |= DKFILE_FLAG_WRITE; 103 | break; 104 | 105 | 106 | case 't': 107 | case 'b': 108 | break; 109 | } 110 | mode++; 111 | } 112 | 113 | 114 | // TODO: parse filename to determine type (UART/EEPROM/FLASH/FAT) 115 | // look for a : anywhere in the string? 116 | 117 | 118 | if( !strchr( filename, ':' ) ) 119 | { // no : found - no device name, use default path 120 | } 121 | else 122 | { 123 | strncpy( devicestr, filename, 3 ); 124 | devicestr[3] = '\0'; // add null terminator to 3-character device name 125 | strlwr( devicestr ); // convert device name to lowercase for comparison 126 | 127 | if( !strcmp_P( devicestr, PSTR("com") ) ) 128 | stream->_flag |= DKFILE_FLAG_UART; 129 | else if( (!strcmp_P( devicestr, PSTR("i2c") )) || (!strcmp_P( devicestr, PSTR("twi") )) ) 130 | stream->_flag |= DKFILE_FLAG_TWI; 131 | else if( !strcmp_P( devicestr, PSTR("spi") ) ) 132 | stream->_flag |= DKFILE_FLAG_SPI; 133 | else if( !strcmp_P( devicestr, PSTR("eep") ) ) 134 | stream->_flag |= DKFILE_FLAG_EEPROM; 135 | else if( !strcmp_P( devicestr, PSTR("fla") ) ) 136 | stream->_flag |= DKFILE_FLAG_FLASH; 137 | else if( !strcmp_P( devicestr, PSTR("kbd") ) ) 138 | stream->_flag |= DKFILE_FLAG_KBD; 139 | } 140 | 141 | 142 | 143 | // select deviceio interface to use for file depending on type (UART/EEPROM/FLASH/FAT) 144 | if( stream->_flag & DKFILE_FLAG_UART ) // handle as UART file 145 | stream->io = &uartdeviceio; 146 | // else if( stream->_flag & DKFILE_FLAG_TWI ) // handle as TWI file 147 | // stream->io = &twideviceio; 148 | // else if( stream->_flag & DKFILE_FLAG_SPI ) // handle as SPI file 149 | // stream->io = &spideviceio; 150 | // else if( stream->_flag & DKFILE_FLAG_EEPROM ) // handle as EEP file 151 | // stream->io = &eepromdeviceio; 152 | // else if( stream->_flag & DKFILE_FLAG_FLASH ) // handle as FLASH file 153 | // stream->io = &flashdeviceio; 154 | // else if( stream->_flag & DKFILE_FLAG_KBD ) // handle as PS2 keyboard 155 | // stream->io = &ps2kbddeviceio; 156 | 157 | 158 | if( !stream->io ) // didn't match an io device with this file, can't open it 159 | { 160 | free( stream ); 161 | return NULL; 162 | } 163 | 164 | 165 | if( stream->io->open( stream ) ) 166 | { // error returned from stream->io->open() 167 | free( stream ); 168 | return NULL; 169 | } 170 | 171 | 172 | file_list = _dkfile_list; // point to start of DKFILEs list 173 | if( file_list ) 174 | { 175 | i++; 176 | while( file_list->next ) 177 | { 178 | file_list = file_list->next; // follow list to end 179 | i++; 180 | } 181 | 182 | file_list->next = stream; // add new stream to end of _dkfile_list 183 | } 184 | else 185 | _dkfile_list = stream; 186 | 187 | 188 | return stream; 189 | } 190 | 191 | 192 | //-------------------------------------------------------------------- 193 | 194 | int dkfclose(DKFILE *stream) 195 | { 196 | DKFILE *fileptr; 197 | 198 | 199 | stream->io->close( stream->info ); // close stream 200 | 201 | fileptr = _dkfile_list; // point to start of DKFILEs list 202 | if( !fileptr ) 203 | return -1; // error FILE struct not found in _dkfile_list (no files open) 204 | 205 | while( fileptr->next && fileptr->next!=stream ) 206 | fileptr = fileptr->next; 207 | 208 | if( fileptr == stream ) 209 | _dkfile_list = stream->next; 210 | else if( fileptr->next!=stream ) 211 | return -1; // error - FILE struct not found in _dkfile_list 212 | else 213 | fileptr->next = stream->next; // unlink stream from _dkfile_list 214 | 215 | if( stream->filename ) 216 | free( stream->filename ); 217 | free( stream ); 218 | 219 | 220 | return 0; 221 | } 222 | 223 | 224 | //-------------------------------------------------------------------- 225 | 226 | int dkfseek(DKFILE *stream, off_t offset, int whence) 227 | { 228 | return stream->io->seek( stream->info, offset, whence ); 229 | } 230 | 231 | 232 | //-------------------------------------------------------------------- 233 | 234 | long dkftell(DKFILE *stream) 235 | { 236 | return stream->io->pos( stream->info ); 237 | } 238 | 239 | 240 | //-------------------------------------------------------------------- 241 | 242 | int dkfgetc(DKFILE *stream) 243 | { 244 | return stream->io->read_byte( stream->info ); 245 | } 246 | 247 | 248 | //-------------------------------------------------------------------- 249 | 250 | int dkfputc(int c, DKFILE *stream) 251 | { 252 | return stream->io->write_byte( stream->info, c ); 253 | } 254 | 255 | 256 | //-------------------------------------------------------------------- 257 | //char *fgets(char *restrict s, int n, FILE *restrict stream) 258 | char *dkfgets(char *s, int n, DKFILE *stream) 259 | { 260 | return NULL; 261 | } 262 | 263 | 264 | //-------------------------------------------------------------------- 265 | //size_t fread(void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream) 266 | size_t dkfread(void *ptr, size_t size, size_t nitems, DKFILE *stream) 267 | { 268 | int n; 269 | 270 | 271 | for( n=0; nio->read_bytes( stream->info, size, ptr+(n*size) ); 273 | 274 | 275 | return n; 276 | } 277 | 278 | 279 | //-------------------------------------------------------------------- 280 | //size_t fwrite(const void *restrict ptr, size_t size, size_t nitems, FILE *restrict stream) 281 | size_t dkfwrite(const void *ptr, size_t size, size_t nitems, DKFILE *stream) 282 | { 283 | int n; 284 | 285 | 286 | for( n=0; nio->write_bytes( stream->info, size, (void *)ptr+(n*size) ); 293 | } 294 | 295 | 296 | return n; 297 | } 298 | 299 | 300 | //-------------------------------------------------------------------- 301 | 302 | int dkfeof(DKFILE *stream) 303 | { 304 | return stream->io->eof( stream->info ); 305 | } 306 | 307 | 308 | //-------------------------------------------------------------------- 309 | 310 | int dkferror(DKFILE *stream) 311 | { 312 | return stream->io->error( stream->info ); 313 | } 314 | 315 | //-------------------------------------------------------------------- 316 | -------------------------------------------------------------------------------- /dkfile.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #ifndef _dkfile_h 3 | #define _dkfile_h 4 | //-------------------------------------------------------------------- 5 | 6 | #include 7 | 8 | 9 | //-------------------------------------------------------------------- 10 | 11 | typedef uint16_t fpos_t; 12 | typedef uint32_t off_t; 13 | 14 | 15 | #define FILENAME_MAX 255 16 | //#define DKFOPEN_MAX 32 17 | 18 | typedef struct _dkfile DKFILE; 19 | 20 | // struct _dkdeviceio contains functions for dealing with each low-level device 21 | struct _dkdeviceio 22 | { 23 | int (*open)(DKFILE *stream); 24 | int (*close)(void *deviceinfo); 25 | 26 | int (*read_byte)(void *deviceinfo); 27 | int (*write_byte)(void *deviceinfo, int c); 28 | int (*read_bytes)(void *deviceinfo, int c, void *ptr ); 29 | int (*write_bytes)(void *deviceinfo, int c, void *ptr ); 30 | int (*seek)(void *deviceinfo, off_t offset, int whence); 31 | fpos_t (*pos)(void *deviceinfo); 32 | 33 | int (*eof)(void *deviceinfo); 34 | int (*error)(void *deviceinfo); 35 | }; 36 | 37 | 38 | // struct _dkfile is used as DKFILE (equivalent to FILE from stdio.h) 39 | struct _dkfile 40 | { 41 | int fd; // file descriptor (0=stdin/1=stdout/2=stderr) 42 | int filenum; // BASIC file number (starting at 1) 43 | char *filename; // name of this file 44 | uint16_t _flag; // flags for this file (input/output/both/type of file?) 45 | 46 | void *info; // device-specific information structure 47 | struct _dkdeviceio *io; 48 | 49 | 50 | struct _dkfile *next; // the next DKFILE in the linked list 51 | }; 52 | 53 | 54 | 55 | extern DKFILE *_dkfile_list; // linked list of open DKFILEs 56 | 57 | //-------------------------------------------------------------------- 58 | 59 | #define DKFILE_FLAG_READ (1<<0) // read access 60 | #define DKFILE_FLAG_WRITE (1<<1) // write access 61 | 62 | #define DKFILE_FLAG_UART (1<<2) // UART COM port 63 | #define DKFILE_FLAG_EEPROM (1<<3) // file in avr eeprom 64 | #define DKFILE_FLAG_FLASH (1<<4) // file in avr flash 65 | #define DKFILE_FLAG_FAT (1<<5) // fatfs, file on SD card 66 | #define DKFILE_FLAG_TWI (1<<6) // TWI (i2c) device (port+address) 67 | #define DKFILE_FLAG_SPI (1<<7) // SPI port 68 | #define DKFILE_FLAG_KBD (1<<8) // PS2 keyboard 69 | 70 | //#define DKFILE_FLAG_KEYBOARD 71 | 72 | //-------------------------------------------------------------------- 73 | 74 | extern DKFILE *dkfopen(const char *filename, const char *mode); 75 | extern int dkfclose(DKFILE *stream); 76 | extern int dkfseek(DKFILE *stream, off_t offset, int whence); 77 | extern long dkftell(DKFILE *stream); 78 | extern int dkfgetc(DKFILE *stream); 79 | extern int dkfputc(int c, DKFILE *stream); 80 | extern char *dkfgets(char *s, int n, DKFILE *stream); 81 | extern size_t dkfread(void *ptr, size_t size, size_t nitems, DKFILE *stream); 82 | extern size_t dkfwrite(const void *ptr, size_t size, size_t nitems, DKFILE *stream); 83 | extern int dkfeof(DKFILE *stream); 84 | extern int dkferror(DKFILE *stream); 85 | 86 | 87 | extern DKFILE *dkfilebynum( int filenum ); // return a pointer to DKFILE with BASIC filenum 88 | 89 | 90 | //-------------------------------------------------------------------- 91 | #endif // !_dkfile_h 92 | //-------------------------------------------------------------------- 93 | -------------------------------------------------------------------------------- /dkfile_uart.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include 10 | #include 11 | 12 | //#include "dkbasic.h" 13 | #include "dkfile_uart.h" 14 | #include "dkstring.h" 15 | #include "dkterm.h" 16 | //#include "dkevents.h" 17 | 18 | 19 | //-------------------------------------------------------------------- 20 | 21 | struct _dkdeviceio uartdeviceio = 22 | { 23 | dkuart_open, 24 | dkuart_close, 25 | dkuart_read_byte, 26 | dkuart_write_byte, 27 | dkuart_read_bytes, 28 | dkuart_write_bytes, 29 | dkuart_seek, 30 | dkuart_pos, 31 | dkuart_eof, 32 | dkuart_error 33 | }; 34 | 35 | 36 | //-------------------------------------------------------------------- 37 | 38 | struct _dk_uart dkuart[2]; // dkuart[0] == USARTC0, dkuart[1] == USARTF0 39 | 40 | 41 | //-------------------------------------------------------------------- 42 | // parse filename for port #, speed, etc 43 | //OPEN "COM[n]:[speed][,parity][,data] [,stop][,RS][,CS[n]][,DS[n]][,CD[n]][,LF] [,PE]" AS [#]filenum [LEN=number] 44 | int dkuart_open( DKFILE *stream ) 45 | { 46 | char t[MAX_TOKEN_LENGTH]; // used for token parsing with dkgettoken() 47 | char *filename; 48 | struct _dk_uart uartconfig; 49 | uint16_t new_BSEL; 50 | 51 | // fill in deviceinfo with defaults then update it with values from filenaem 52 | uartconfig.portnum=-1; 53 | uartconfig.speed=57600; 54 | uartconfig.parity=DK_PARITY_NONE; 55 | uartconfig.data=8; 56 | uartconfig.stop=1; 57 | uartconfig.flowctrl = DK_FLOWCTRL_CTSRTS; 58 | uartconfig._flag=0; 59 | 60 | uartconfig.rx_buflen = 512; 61 | uartconfig.rx_buflimit = 448; 62 | 63 | 64 | filename = stream->filename; 65 | 66 | filename += 3; // skip past "COM" 67 | 68 | filename = dkgettoken( filename, t ); // get [n] as token 69 | 70 | if( isdigit( *t ) ) 71 | uartconfig.portnum = atoi( t ); 72 | else 73 | return 1; // error in filename (no port #) 74 | 75 | 76 | filename = dkgettoken( filename, t ); // get : as token 77 | 78 | if( (*t) != ':' ) 79 | return 1; // error in filename! (or filename done?) 80 | 81 | 82 | filename = dkgettoken( filename, t ); // get [speed] as token 83 | if( t[0] != ',' && t[0] ) 84 | { // got a speed token 85 | uartconfig.speed = atol( t ); // use (*t) speed token 86 | 87 | filename = dkgettoken( filename, t ); // get , as token 88 | 89 | if( t[0] && ( t[0] != ',' ) ) 90 | return 1; // error in filename (or filename done) 91 | } 92 | 93 | 94 | filename = dkgettoken( filename, t ); // get [parity] as token 95 | if( t[0] != ',' && t[0] ) 96 | { // got a parity token 97 | switch( tolower((*t)) ) // use (*t) speed token 98 | { 99 | case 'n': 100 | uartconfig.parity = DK_PARITY_NONE; 101 | break; 102 | 103 | case 'o': 104 | uartconfig.parity = DK_PARITY_ODD; 105 | break; 106 | 107 | case 'e': 108 | uartconfig.parity = DK_PARITY_EVEN; 109 | break; 110 | } 111 | 112 | filename = dkgettoken( filename, t ); // get , as token 113 | 114 | if( (*t) && ( (*t) != ',' ) ) 115 | return 1; // error in filename (or filename done) 116 | } 117 | 118 | 119 | filename = dkgettoken( filename, t ); // get [data] as token 120 | if( t[0] != ',' && t[0] ) 121 | { // got a data token 122 | 123 | uartconfig.data = atoi( t ); // use (*t) data token 124 | 125 | filename = dkgettoken( filename, t ); // get , as token 126 | 127 | if( (*t) && ( (*t) != ',' ) ) 128 | return 1; // error in filename (or filename done) 129 | } 130 | 131 | 132 | filename = dkgettoken( filename, t ); // get [stop] as token 133 | if( t[0] != ',' && t[0] ) 134 | { // got a stop token 135 | 136 | uartconfig.stop = atoi( t ); // use (*t) stop token 137 | 138 | filename = dkgettoken( filename, t ); // get , as token 139 | 140 | if( (*t) && ( (*t) != ',' ) ) 141 | return 1; // error in filename (or filename done) 142 | } 143 | 144 | 145 | 146 | uartconfig.rx_buffer = (uint8_t *)malloc( uartconfig.rx_buflen ); // allocate space for rx buffer 147 | 148 | 149 | switch( uartconfig.portnum ) 150 | { 151 | case 0: // init UART0 152 | dkuart[0].portnum = uartconfig.portnum; 153 | dkuart[0].speed = uartconfig.speed; 154 | dkuart[0].parity = uartconfig.parity; 155 | dkuart[0].data = uartconfig.data; 156 | dkuart[0].stop = uartconfig.stop; 157 | dkuart[0].flowctrl = uartconfig.flowctrl; 158 | dkuart[0]._flag = uartconfig._flag; 159 | 160 | dkuart[0].rx_buflen = uartconfig.rx_buflen; 161 | dkuart[0].rx_buflimit = uartconfig.rx_buflimit; 162 | 163 | if( dkuart[0].rx_buffer ) 164 | free( dkuart[0].rx_buffer ); // free previous rx_buffer if it existed 165 | dkuart[0].rx_buffer = uartconfig.rx_buffer; 166 | 167 | dkuart[0].rx_wr_ptr=0; 168 | dkuart[0].rx_rd_ptr=0; 169 | 170 | stream->info = &dkuart[0]; 171 | 172 | 173 | // PORTCFG_VPCTRLA = 0x23; // map PORTC to virtual port 1, PORTD to virtual port 0 174 | 175 | // set PORTC output for txd 176 | // VPORT1_OUT |= 0x08; 177 | // VPORT1_DIR |= 0x08; 178 | PORTC.OUT |= (1<<3); // set PC3 (TXD) to 1 179 | PORTC.DIR |= (1<<3); // set PC3 (TXD) as output 180 | 181 | 182 | // UBRR0 = ( F_CPU / (double)(16 * uartconfig.speed) + 0.5 ) - 1; 183 | // UCSR0A = (0<>8) & 0x0F); 194 | 195 | 196 | // USARTC0_BAUDCTRLA = 0x13; // 57.6 kbps @ 2 MHz 197 | // USARTC0_BAUDCTRLB = 0xC0; // BSEL = 19, BSCALE=-4 198 | 199 | 200 | USARTC0_CTRLA = (1<info = &dkuart[1]; 251 | 252 | 253 | // PORTCFG_VPCTRLA = 0x23; // map PORTC to virtual port 1, PORTD to virtual port 0 254 | 255 | // set PORTC output for txd 256 | // VPORT1_OUT |= 0x08; 257 | // VPORT1_DIR |= 0x08; 258 | PORTF.OUT |= (1<<3); // set PF3 (TXD) to 1 259 | PORTF.DIR |= (1<<3); // set PF3 (TXD) as output 260 | 261 | 262 | // UBRR0 = ( F_CPU / (double)(16 * uartconfig.speed) + 0.5 ) - 1; 263 | // UCSR0A = (0<>8) & 0x0F); 274 | 275 | 276 | // USARTC0_BAUDCTRLA = 0x13; // 57.6 kbps @ 2 MHz 277 | // USARTC0_BAUDCTRLB = 0xC0; // BSEL = 19, BSCALE=-4 278 | 279 | 280 | USARTF0_CTRLA = (1<info, 1 ); // set flow control = ready for data 312 | 313 | sei(); 314 | 315 | return 0; 316 | } 317 | 318 | //-------------------------------------------------------------------- 319 | int dkuart_close( void *deviceinfo ) 320 | { 321 | //stop UART - disable RX interrupt 322 | // destroy rx buffer? 323 | 324 | 325 | dkuart_flowctrl( deviceinfo, 0 ); // set flow control = not ready for data 326 | 327 | switch( ((struct _dk_uart *)deviceinfo)->portnum ) 328 | { 329 | case 0: // stop UART0 330 | // UCSR0B = (0<rx_buffer ) 341 | { 342 | free( ((struct _dk_uart *)deviceinfo)->rx_buffer ); 343 | ((struct _dk_uart *)deviceinfo)->rx_buffer = NULL; 344 | } 345 | 346 | 347 | return 0; 348 | } 349 | 350 | //-------------------------------------------------------------------- 351 | int dkuart_read_byte(void *deviceinfo) 352 | { 353 | int c; 354 | 355 | 356 | if( ((struct _dk_uart *)deviceinfo)->rx_wr_ptr == ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) 357 | dkuart_flowctrl( deviceinfo, 1 ); // set flow control = ready for data 358 | else if( ((struct _dk_uart *)deviceinfo)->rx_wr_ptr > ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) 359 | { 360 | if( ( ((struct _dk_uart *)deviceinfo)->rx_wr_ptr - ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) < ((struct _dk_uart *)deviceinfo)->rx_buflimit ) 361 | dkuart_flowctrl( deviceinfo, 1 ); // set flow control = ready for data 362 | } 363 | else 364 | { 365 | if( ((struct _dk_uart *)deviceinfo)->rx_buflen - ( ((struct _dk_uart *)deviceinfo)->rx_rd_ptr - ((struct _dk_uart *)deviceinfo)->rx_wr_ptr ) < ((struct _dk_uart *)deviceinfo)->rx_buflimit ) 366 | dkuart_flowctrl( deviceinfo, 1 ); // set flow control = ready for data 367 | } 368 | 369 | 370 | while( ((struct _dk_uart *)deviceinfo)->rx_wr_ptr == ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) 371 | { // wait until character(s) in buffer 372 | if( io_ctrl_char==3) 373 | return -1; 374 | } 375 | 376 | c = (int)((struct _dk_uart *)deviceinfo)->rx_buffer[ ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ]; 377 | ( ((struct _dk_uart *)deviceinfo)->rx_rd_ptr )++; 378 | 379 | if( ( ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) >= ((struct _dk_uart *)deviceinfo)->rx_buflen ) 380 | ( ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) -= ((struct _dk_uart *)deviceinfo)->rx_buflen; 381 | 382 | 383 | return c; 384 | } 385 | //-------------------------------------------------------------------- 386 | int dkuart_write_byte(void *deviceinfo, int c) 387 | { 388 | switch( ((struct _dk_uart *)deviceinfo)->portnum ) 389 | { 390 | case 0: // send byte out UART0 391 | // while( ! (UCSR0A & (1<rx_wr_ptr ) - (* ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) )) %((struct _dk_uart *)deviceinfo)->rx_buflen; 449 | if( ((struct _dk_uart *)deviceinfo)->rx_wr_ptr == ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) 450 | return 0; 451 | else if( ((struct _dk_uart *)deviceinfo)->rx_wr_ptr > ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) 452 | return ((struct _dk_uart *)deviceinfo)->rx_wr_ptr - ((struct _dk_uart *)deviceinfo)->rx_rd_ptr; 453 | else 454 | return ((struct _dk_uart *)deviceinfo)->rx_buflen - ( ((struct _dk_uart *)deviceinfo)->rx_rd_ptr - ((struct _dk_uart *)deviceinfo)->rx_wr_ptr ); 455 | } 456 | //-------------------------------------------------------------------- 457 | int dkuart_eof(void *deviceinfo) 458 | { 459 | if( ((struct _dk_uart *)deviceinfo)->rx_wr_ptr != ((struct _dk_uart *)deviceinfo)->rx_rd_ptr ) 460 | return 0; 461 | 462 | return -1; 463 | } 464 | //-------------------------------------------------------------------- 465 | int dkuart_error(void *deviceinfo) 466 | { 467 | return 0; 468 | } 469 | 470 | //-------------------------------------------------------------------- 471 | // 0 = stop, 1 = start 472 | int dkuart_flowctrl( void *deviceinfo, int status ) 473 | { 474 | switch( status ) 475 | { 476 | case 0: // stop flow 477 | if( ((struct _dk_uart *)deviceinfo)->flowctrl & DK_FLOWCTRL_CTSRTS ) 478 | { 479 | switch( ((struct _dk_uart *)deviceinfo)->portnum ) 480 | { 481 | case 0: 482 | // PORTE |= (1<<2); 483 | break; 484 | 485 | case 1: 486 | // PORTD |= (1<<4); 487 | break; 488 | } 489 | } 490 | break; 491 | 492 | case 1: // start flow 493 | if( ((struct _dk_uart *)deviceinfo)->flowctrl & DK_FLOWCTRL_CTSRTS ) 494 | { 495 | switch( ((struct _dk_uart *)deviceinfo)->portnum ) 496 | { 497 | case 0: 498 | // PORTE &= (~(1<<2)); 499 | break; 500 | 501 | case 1: 502 | // PORTD &= (~(1<<4)); 503 | break; 504 | } 505 | } 506 | break; 507 | } 508 | 509 | 510 | return 0; 511 | } 512 | //-------------------------------------------------------------------- 513 | // this ISR is just slightly too long for data @ 115.2k @ 3.68 MHz 514 | //ISR(USART0_RX_vect) 515 | ISR(USARTC0_RXC_vect) 516 | { 517 | uint8_t data; 518 | 519 | 520 | // if( UCSR0A & (_BV(FE0)|_BV(DOR0)) ) 521 | // { 522 | // data = UDR0; 523 | // return; 524 | // } 525 | 526 | if( USARTC0_STATUS & (USART_FERR_bm|USART_BUFOVF_bm|USART_PERR_bm) ) 527 | { 528 | data = USARTC0_DATA; 529 | return; 530 | } 531 | 532 | data = USARTC0_DATA; 533 | 534 | if( dkuart[0].rx_buffer ) // if rx_buffer isn't allocated, the received byte will be lost 535 | { 536 | dkuart[0].rx_buffer[ dkuart[0].rx_wr_ptr ] = data; 537 | 538 | dkuart[0].rx_wr_ptr++; 539 | if( dkuart[0].rx_wr_ptr >= dkuart[0].rx_buflen ) 540 | dkuart[0].rx_wr_ptr -= dkuart[0].rx_buflen; 541 | 542 | if( ((dkuart[0].rx_wr_ptr-dkuart[0].rx_rd_ptr) % dkuart[0].rx_buflen ) >= (dkuart[0].rx_buflimit) ) 543 | dkuart_flowctrl( &dkuart[0], 0 ); 544 | } 545 | 546 | if( data == '\x03' ) 547 | { 548 | if ( dkuart[0]._flag&DKUART_FLAG_TERMINAL ) 549 | io_ctrl_char = data; // ctrl-c has been received WHY IS THIS FUCKING ME UP 550 | } 551 | else if( data == '\x1A' ) 552 | { 553 | if ( dkuart[0]._flag&DKUART_FLAG_TERMINAL ) 554 | { 555 | if( io_ctrl_char != DKKEY_PAUSE ) 556 | io_ctrl_char = DKKEY_PAUSE; // pause (ctrl-z) has been received 557 | else 558 | io_ctrl_char = 0; // pause was received a second time - unpause 559 | } 560 | } 561 | 562 | // dkeventflags |= (1<<0); // bits set to indicate which COM event fired 563 | } 564 | 565 | //-------------------------------------------------------------------- 566 | // this ISR is just slightly too long for data @ 115.2k @ 3.68 MHz 567 | //ISR(USART0_RX_vect) 568 | ISR(USARTF0_RXC_vect) 569 | { 570 | uint8_t data; 571 | 572 | 573 | // if( UCSR0A & (_BV(FE0)|_BV(DOR0)) ) 574 | // { 575 | // data = UDR0; 576 | // return; 577 | // } 578 | 579 | if( USARTF0_STATUS & (USART_FERR_bm|USART_BUFOVF_bm|USART_PERR_bm) ) 580 | { 581 | data = USARTF0_DATA; 582 | return; 583 | } 584 | 585 | data = USARTF0_DATA; 586 | 587 | if( dkuart[1].rx_buffer ) // if rx_buffer isn't allocated, the received byte will be lost 588 | { 589 | dkuart[1].rx_buffer[ dkuart[1].rx_wr_ptr ] = data; 590 | 591 | dkuart[1].rx_wr_ptr++; 592 | if( dkuart[1].rx_wr_ptr >= dkuart[1].rx_buflen ) 593 | dkuart[1].rx_wr_ptr -= dkuart[1].rx_buflen; 594 | 595 | if( ((dkuart[1].rx_wr_ptr-dkuart[1].rx_rd_ptr) % dkuart[1].rx_buflen ) >= (dkuart[1].rx_buflimit) ) 596 | dkuart_flowctrl( &dkuart[1], 0 ); 597 | } 598 | 599 | if( data == '\x03' ) 600 | { 601 | if ( dkuart[1]._flag&DKUART_FLAG_TERMINAL ) 602 | io_ctrl_char = data; // ctrl-c has been received WHY IS THIS FUCKING ME UP 603 | } 604 | else if( data == '\x1A' ) 605 | { 606 | if ( dkuart[1]._flag&DKUART_FLAG_TERMINAL ) 607 | { 608 | if( io_ctrl_char != DKKEY_PAUSE ) 609 | io_ctrl_char = DKKEY_PAUSE; // pause (ctrl-z) has been received 610 | else 611 | io_ctrl_char = 0; // pause was received a second time - unpause 612 | } 613 | } 614 | 615 | // dkeventflags |= (1<<0); // bits set to indicate which COM event fired 616 | } 617 | 618 | //-------------------------------------------------------------------- 619 | 620 | /* 621 | ISR(USART1_RX_vect) 622 | { 623 | uint8_t data; 624 | 625 | 626 | if( UCSR1A & _BV(FE1) ) 627 | { 628 | data = UDR1; 629 | return; 630 | } 631 | if( UCSR1A & _BV(DOR1) ) 632 | { 633 | data = UDR1; 634 | return; 635 | } 636 | 637 | data = UDR1; 638 | 639 | if( data == '\x03' && (dkuart[1]._flag&DKUART_FLAG_TERMINAL) ) 640 | io_ctrl_char = data; // ctrl-c has been received 641 | 642 | if( dkuart[1].rx_buffer ) // if rx_buffer isn't allocated, the received byte will be lost 643 | { 644 | dkuart[1].rx_buffer[ dkuart[1].rx_wr_ptr ] = data; 645 | 646 | dkuart[1].rx_wr_ptr++; 647 | if( dkuart[1].rx_wr_ptr >= dkuart[1].rx_buflen ) 648 | dkuart[1].rx_wr_ptr -= dkuart[1].rx_buflen; 649 | 650 | if( ((dkuart[1].rx_wr_ptr-dkuart[1].rx_rd_ptr) % (dkuart[1].rx_buflen+1) ) >= (dkuart[1].rx_buflimit) ) 651 | dkuart_flowctrl( &dkuart[1], 0 ); 652 | } 653 | 654 | dkeventflags |= (1<<1); // bits set to indicate which COM event fired 655 | } 656 | */ 657 | //-------------------------------------------------------------------- 658 | 659 | int dkuart_stuff_string( int idx, char *data ) 660 | { 661 | int n; 662 | 663 | for( n=0; data[n]; n++ ) 664 | dkuart_stuff_byte( idx, data[n] ); 665 | 666 | return n; 667 | } 668 | 669 | //-------------------------------------------------------------------- 670 | 671 | void dkuart_stuff_byte( int idx, uint8_t data ) 672 | { 673 | if( dkuart[idx].rx_buffer ) // if rx_buffer isn't allocated, the received byte will be lost 674 | { 675 | dkuart[idx].rx_buffer[ dkuart[idx].rx_wr_ptr ] = data; 676 | 677 | dkuart[idx].rx_wr_ptr++; 678 | if( dkuart[idx].rx_wr_ptr >= dkuart[idx].rx_buflen ) 679 | dkuart[idx].rx_wr_ptr -= dkuart[idx].rx_buflen; 680 | 681 | if( ((dkuart[idx].rx_wr_ptr-dkuart[idx].rx_rd_ptr) % dkuart[idx].rx_buflen ) >= (dkuart[idx].rx_buflimit) ) 682 | dkuart_flowctrl( &dkuart[idx], 0 ); 683 | } 684 | 685 | return; 686 | } 687 | 688 | //-------------------------------------------------------------------- 689 | -------------------------------------------------------------------------------- /dkfile_uart.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #ifndef _dkfile_uart_h 3 | #define _dkfile_uart_h 4 | //-------------------------------------------------------------------- 5 | 6 | #include "dkfile.h" 7 | 8 | //-------------------------------------------------------------------- 9 | 10 | #define DK_PARITY_NONE 0 11 | #define DK_PARITY_ODD 1 12 | #define DK_PARITY_EVEN 2 13 | 14 | #define DK_FLOWCTRL_CTSRTS (1<<0) 15 | #define DK_FLOWCTRL_XONXOFF (1<<1) 16 | 17 | 18 | 19 | #define DKUART_FLAG_TERMINAL (1<<0) // this device is active for terminal io 20 | 21 | 22 | struct _dk_uart 23 | { 24 | uint8_t portnum; 25 | uint32_t speed; 26 | uint8_t parity; 27 | uint8_t data; 28 | uint8_t stop; 29 | uint8_t flowctrl; // what type of flow control to use - bitmapped 30 | uint8_t _flag; 31 | 32 | uint16_t rx_buflen; // total size of rx buffer (in bytes) 33 | uint16_t rx_buflimit; // limit in number of bytes at which to assert flow control 34 | uint8_t *rx_buffer; // circular buffer for received data (note: if this is changed from 128 byte len, code requires changes elsewhere also) 35 | volatile uint16_t rx_wr_ptr, rx_rd_ptr; // will be pointed at dkuart0_rx_buffer, dkuart0_rx_wr_ptr, dkuart0_rx_rd_ptr, etc 36 | }; 37 | 38 | 39 | 40 | // isr's should already be installed for all available COM ports 41 | // just need to set TXEN/RXEN/RXCIEx? 42 | // for max flexibility, the isr's should be same as for console io 43 | // - can detach console and open from basic app 44 | // - can stop telly 45 | // - dktelly should go through generic dkuart character interface 46 | // use pointer for rxbuffer on each com port? or hardcoded buffer lengths? 47 | 48 | extern int dkuart_open( DKFILE *stream ); 49 | extern int dkuart_close( void *deviceinfo ); 50 | extern int dkuart_read_byte(void *deviceinfo); 51 | extern int dkuart_write_byte(void *deviceinfo, int c); 52 | extern int dkuart_read_bytes(void *deviceinfo, int n, void *ptr); 53 | extern int dkuart_write_bytes(void *deviceinfo, int n, void *ptr ); 54 | extern int dkuart_seek(void *deviceinfo, off_t offset, int whence); 55 | extern fpos_t dkuart_pos(void *deviceinfo); 56 | extern int dkuart_eof(void *deviceinfo); 57 | extern int dkuart_error(void *deviceinfo); 58 | 59 | extern int dkuart_flowctrl(void *deviceinfo, int status ); 60 | 61 | extern void dkuart_stuff_byte( int idx, uint8_t data ); 62 | extern int dkuart_stuff_string( int idx, char *data ); 63 | 64 | 65 | extern struct _dkdeviceio uartdeviceio; 66 | extern struct _dk_uart dkuart[]; 67 | 68 | 69 | //-------------------------------------------------------------------- 70 | #endif // !_dkfile_uart_h 71 | //-------------------------------------------------------------------- 72 | -------------------------------------------------------------------------------- /dkinteractive.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "dkterm.h" 11 | #include "dkvt100.h" 12 | #include "dkstring.h" 13 | #include "dktables.h" 14 | 15 | 16 | //-------------------------------------------------------------------- 17 | void dkinteractive(void) 18 | { 19 | char line[MAX_LINE_LENGTH+1]; 20 | char token[MAX_TOKEN_LENGTH+1]; 21 | char *lptr; 22 | char * (*actionhandler)(char *str) = NULL; 23 | 24 | 25 | printf_P( PSTR("\n\n") ); 26 | dkterm_clearscreen(); 27 | printf_P( PSTR("INTERACTIVE GLITCHER %1.2f %s %s\n"), _GLITCHER_VERSION_NUM/100.0, __DATE__, __TIME__ ); 28 | 29 | 30 | while( 1 ) // loop forever in interpreter 31 | { 32 | if( io_ctrl_char == DKKEY_CTRLC ) 33 | { 34 | io_ctrl_char = 0; // unset ctrl-c signal 35 | _flushuntil( DKKEY_CTRLC ); // flush everything up to and including ctrl-c from input buffer 36 | printf_P( PSTR("\n") ); 37 | } 38 | 39 | 40 | printf_P( PSTR("> ") ); // display prompt 41 | 42 | dkgets( line ); 43 | 44 | printf_P( PSTR("\n") ); 45 | 46 | if( !strlen( line ) ) 47 | continue; 48 | 49 | lptr = dkgettoken( line, token ); 50 | if( !strlen(token) ) 51 | continue; 52 | 53 | if( !strlen( token) ) 54 | continue; 55 | 56 | actionhandler = dkfindaction( token ); 57 | if( actionhandler ) 58 | { 59 | lptr = actionhandler( lptr ); 60 | } 61 | else 62 | { 63 | printf_P( PSTR("Unknown action \"%s\".\n"), token ); 64 | } 65 | 66 | } 67 | } 68 | 69 | -------------------------------------------------------------------------------- /dkinteractive.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | 3 | void dkinteractive(void); 4 | 5 | //-------------------------------------------------------------------- 6 | -------------------------------------------------------------------------------- /dkstring.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "dkstring.h" 10 | #include "dkterm.h" 11 | #include "actions/hotkey.h" 12 | 13 | 14 | //-------------------------------------------------------------------- 15 | void dkgets( char *s ) 16 | { 17 | s[0] = '\0'; 18 | dkpregets( s ); 19 | 20 | return; 21 | } 22 | 23 | //-------------------------------------------------------------------- 24 | void dkpregets( char *s ) 25 | { 26 | int i=0; 27 | 28 | dkpregetsi( s, i ); 29 | 30 | return; 31 | } 32 | //-------------------------------------------------------------------- 33 | void dkpregetsi( char *s, int i ) 34 | { 35 | uint16_t l=0; // length of s 36 | uint16_t t; 37 | uint16_t c; 38 | uint16_t n; 39 | static uint8_t insertmode=0; // TODO: make insertmode global? 40 | 41 | 42 | l = strlen(s); 43 | if( l ) 44 | { 45 | printf_P( PSTR("%s"), s ); 46 | for( i=l; i; i-- ) 47 | _putch('\b'); 48 | } 49 | 50 | while(1) 51 | { 52 | c=_getch(); 53 | 54 | if( c == 0x1B ) // esc received 55 | c = dkvt102input(); 56 | 57 | switch(c) 58 | { 59 | case '\n': 60 | continue; 61 | 62 | case '\r': 63 | return; 64 | 65 | case '\b': 66 | if(i) 67 | { 68 | if( i < l ) 69 | { 70 | for( t=i; tt ; i-- ) 163 | _putch('\b'); 164 | continue; 165 | 166 | case DKKEY_PGUP: // ESC [ 5 ~ PGUP 167 | case DKKEY_PGDN: // ESC [ 6 ~ PGDN 168 | continue; 169 | } 170 | 171 | if( c >= DKKEY_F1 && c <= DKKEY_F10 ) 172 | { // handle function keys (F1-F10 'keys' shortcuts) 173 | n = strlen( dk_hotkeys[c-DKKEY_F1] ); 174 | if( !n ) 175 | continue; 176 | 177 | if( dk_hotkeys[c-DKKEY_F1][n-1] == '\r' ) 178 | n--; 179 | 180 | strncpy( s+i, dk_hotkeys[c-DKKEY_F1], n ); 181 | 182 | for( t=0 ; t l ) 186 | l = i; 187 | s[l] = '\0'; // null-terminate string 188 | 189 | if( dk_hotkeys[c-DKKEY_F1][n] == '\r' ) 190 | return; 191 | 192 | continue; 193 | } 194 | 195 | 196 | // if( c > 0x7E || c < 0x20 ) 197 | // continue; // ignore any characters >0x7E (DEL or anything with high bit set - extended chars) 198 | 199 | 200 | 201 | if( c < 0x20 ) 202 | continue; // ignore any characters <0x20 203 | // { 204 | // _putch( 0x2F ); // debug display 205 | // _putch( c+0x30 ); 206 | // _putch( 0x2F ); 207 | // } 208 | 209 | if( insertmode && i=i && t; t-- ) // shift right part of s over one position 213 | s[t] = s[t-1]; 214 | if( l < MAX_LINE_LENGTH ) // only increment length if string hasn't reached MAX_LINE_LENGTH 215 | l++; // length increments by one (insert mode) 216 | for( t=i+1; t l ) 226 | { 227 | if( l < MAX_LINE_LENGTH ) 228 | l++; // increment line length 229 | else 230 | { 231 | i = l; // max line length reached, don't increment length or i 232 | _putch( '\b' ); 233 | } 234 | } 235 | } 236 | s[l] = '\0'; 237 | _putch(c); 238 | } 239 | } 240 | 241 | 242 | 243 | //-------------------------------------------------------------------- 244 | uint8_t dkvt102input(void) 245 | { 246 | uint8_t c=0x1B; 247 | uint8_t modifiers=0; 248 | 249 | 250 | if( !_kbhit() ) 251 | _delay_ms(11); // 11 ms is just enough time for next byte @ 9600bps 252 | if( _kbhit() ) 253 | { // get key following ESC 254 | c = _getch(); 255 | 256 | if( c == 0x1B ) // received ESC ESC - this is vt100 telling us alt-key is pressed with arrow keys 257 | { 258 | modifiers |= 1; // alt-key pressed 259 | 260 | if( !_kbhit() ) 261 | _delay_ms(11); 262 | if( !_kbhit() ) 263 | return c; 264 | 265 | c = _getch(); 266 | } 267 | 268 | if( c == '[' || c == 'O' ) 269 | { // received ESC [ (or ESC O for end key) 270 | if( !_kbhit() ) 271 | _delay_ms(11); 272 | if( _kbhit() ) 273 | { 274 | c = _getch(); // get byte after ESC [ 275 | 276 | switch( c ) 277 | { 278 | case 'A': // up arrow 279 | c = DKKEY_UP; 280 | break; 281 | 282 | case 'D': // left arrow 283 | c = DKKEY_LEFT; 284 | break; 285 | 286 | case 'B': // down arrow 287 | c = DKKEY_DOWN; 288 | break; 289 | 290 | case 'C': // right arrow 291 | c = DKKEY_RIGHT; 292 | break; 293 | 294 | case '1': // ESC [ 1 ~ home 295 | if( !_kbhit() ) 296 | _delay_ms(11); 297 | if( _kbhit() ) 298 | _getch(); // get trailing ~ 299 | c = DKKEY_HOME; 300 | break; 301 | 302 | case 'F': // ESC O F end 303 | c = DKKEY_END; 304 | break; 305 | 306 | case '4': // ESC [ 4 ~ END 307 | if( !_kbhit() ) 308 | _delay_ms(11); 309 | if( _kbhit() ) 310 | _getch(); // get trailing ~ 311 | c = DKKEY_END; 312 | break; 313 | 314 | case '2': // ESC [ 2 ~ INS 315 | if( !_kbhit() ) 316 | _delay_ms(11); 317 | if( _kbhit() ) 318 | _getch(); // get trailing ~ 319 | c = DKKEY_INS; 320 | break; 321 | 322 | case '3': // ESC [ 3 ~ DEL 323 | if( !_kbhit() ) 324 | _delay_ms(11); 325 | if( _kbhit() ) 326 | _getch(); // get trailing ~ 327 | c = DKKEY_DEL; 328 | break; 329 | 330 | case '5': // ESC [ 5 ~ PGUP 331 | if( !_kbhit() ) 332 | _delay_ms(11); 333 | if( _kbhit() ) 334 | _getch(); // get trailing ~ 335 | c = DKKEY_PGUP; 336 | break; 337 | 338 | case '6': // ESC [ 6 ~ PGDN 339 | if( !_kbhit() ) 340 | _delay_ms(11); 341 | if( _kbhit() ) 342 | _getch(); // get trailing ~ 343 | c = DKKEY_PGDN; 344 | break; 345 | 346 | case 'P': // ESC [ P F1 347 | case 'Q': 348 | case 'R': 349 | case 'S': 350 | case 'T': 351 | case 'U': 352 | case 'V': 353 | case 'W': 354 | case 'X': 355 | case 'Y': 356 | case 'Z': 357 | case '[': 358 | c = DKKEY_F1 + c-'P'; 359 | break; 360 | } 361 | 362 | return c; 363 | } 364 | } 365 | } 366 | 367 | return c; 368 | } 369 | 370 | 371 | //-------------------------------------------------------------------- 372 | //get next token - note: t must be already allocated 373 | char *dkgettoken( char *expstring, char *t ) 374 | { 375 | uint16_t tidx=0; 376 | uint8_t inquote=0; 377 | 378 | 379 | t[0] = '\0'; // start token string (t) as empty string 380 | 381 | 382 | while( (*expstring) && tidx='A'&&(*expstring)<='Z') || ((*expstring)>='a'&&(*expstring)<='z') || 385 | ((*expstring)=='.') || ((*expstring)=='_') || ((*expstring)>='0'&&(*expstring)<='9') ) 386 | { 387 | t[ tidx++ ] = (*expstring); 388 | t[ tidx ] = '\0'; 389 | } 390 | else if( (*expstring)=='\"' ) // quote 391 | { 392 | if( inquote ) 393 | { // got closing quote 394 | t[ tidx++ ] = (*expstring++); 395 | t[ tidx ] ='\0'; 396 | return expstring; 397 | } 398 | inquote=1; // got opening quote 399 | t[ tidx++ ] = (*expstring); 400 | t[ tidx ] ='\0'; 401 | } 402 | else if( inquote ) 403 | { 404 | t[ tidx++ ] = (*expstring); 405 | t[ tidx ] = '\0'; 406 | } 407 | else if( ((*expstring)==' ') || ((*expstring)=='\t') ) 408 | { // whitespace, not inside quotes 409 | if( tidx ) 410 | return expstring; 411 | } 412 | else if( (*expstring)=='\'' ) 413 | { 414 | return expstring+strlen(expstring); 415 | } 416 | else // symbol 417 | { 418 | if( tidx ) 419 | return expstring; 420 | t[ tidx ] = (*expstring++); 421 | if( t[tidx] == '<' && expstring[0] == '=' ) 422 | { // got <= 423 | expstring++; 424 | t[ ++tidx ] = '='; 425 | } 426 | else if( t[tidx] == '>' && expstring[0] == '=' ) 427 | { // got >= 428 | expstring++; 429 | t[ ++tidx ] = '='; 430 | } 431 | else if( t[tidx] == '<' && expstring[0] == '>' ) 432 | { // got <> 433 | expstring++; 434 | t[ ++tidx ] = '>'; 435 | } 436 | t[ ++tidx ] = '\0'; 437 | return expstring; 438 | } 439 | expstring++; 440 | } 441 | 442 | return expstring; 443 | } 444 | 445 | /* 446 | //-------------------------------------------------------------------- 447 | // char *dkgetnameflags( char *expstring, uint16_t *flags ) 448 | // flags is updated by this function 449 | // expstring - string to read name from ('expression string') 450 | // flags - pointer to flags word - must point to a valid word 451 | // returns: pointer to expstring 452 | char *dkgetnameflags( char *expstring, uint16_t *flags ) 453 | { 454 | char t[ MAX_TOKEN_LENGTH+1 ]; // space for token parsed by dkgettoken() 455 | char *strptr=NULL; 456 | 457 | (*flags) = 0; 458 | 459 | while( expstring[0] ) // loop until end of string (or end of type specifiers) 460 | { 461 | strptr = dkgettoken( expstring, t ); 462 | switch( t[0] ) 463 | { 464 | case '(': // parenthesis - array or function 465 | (*flags) |= DKNAME_PAREN; 466 | return expstring; 467 | 468 | case '$': // string 469 | if( (*flags) ) 470 | return expstring; // if there's already a type specifier, ignore this character 471 | (*flags) |= DKNAME_STRING; 472 | expstring = strptr; 473 | break; 474 | 475 | case '%': // integer 476 | if( (*flags) ) 477 | return expstring; // if there's already a type specifier, ignore this character 478 | (*flags) |= DKNAME_INTEGER; 479 | expstring = strptr; 480 | break; 481 | 482 | case '!': // single precision 483 | if( (*flags) ) 484 | return expstring; // if there's already a type specifier, ignore this character 485 | (*flags) |= DKNAME_FLOATSINGLE; 486 | expstring = strptr; 487 | break; 488 | 489 | case '#': // double precision 490 | if( (*flags) ) 491 | return expstring; // if there's already a type specifier, ignore this character 492 | (*flags) |= DKNAME_FLOATDOUBLE; 493 | expstring = strptr; 494 | break; 495 | 496 | case '@': // byte (DK-BASIC custom) 497 | if( (*flags) ) 498 | return expstring; // if there's already a type specifier, ignore this character 499 | (*flags) |= DKNAME_BYTE; 500 | expstring = strptr; 501 | break; 502 | 503 | default: // token is not a type specifier 504 | return expstring; 505 | } 506 | } 507 | 508 | return expstring; 509 | } 510 | */ 511 | 512 | //-------------------------------------------------------------------- 513 | 514 | double dkstrtonum( char *s ) 515 | { 516 | uint16_t intval; 517 | uint8_t i; 518 | 519 | 520 | if( s[0] == '&' ) 521 | { 522 | if( s[1]=='h' || s[1]=='H' ) 523 | sscanf( s+2, "%x", &intval ); 524 | else if( s[1]=='o' || s[1]=='O' ) 525 | sscanf( s+2, "%o", &intval ); 526 | else if( s[1]=='b' || s[1]=='B' ) 527 | { 528 | intval = 0; 529 | for( i=2; s[i]=='0' || s[i]=='1'; i++ ) 530 | { 531 | intval<<=1; 532 | if( s[i]=='1' ) 533 | intval |= 1; 534 | } 535 | } 536 | else 537 | sscanf( s+1, "%o", &intval ); 538 | 539 | return intval; 540 | } 541 | else 542 | { 543 | return atof( s ); 544 | } 545 | } 546 | 547 | /* 548 | //-------------------------------------------------------------------- 549 | // read next expression for a function - expects to see , then expression or ) if no more expressions 550 | // returns NULL when ) reached 551 | dkexpression *dkgetnextexpression( char * line ) 552 | { 553 | dkexpression *e; 554 | char t[ MAX_TOKEN_LENGTH+1 ]; 555 | 556 | 557 | line = dkgettoken( line, t ); 558 | expstr = line; 559 | 560 | if( t[0] == ')' ) 561 | return NULL; // reached end of function parameters 562 | 563 | if( t[0] != ',' ) 564 | return NULL; // error: syntax error (missing closing parenthesis) 565 | 566 | e = expression( line ); // process expression @line 567 | if( !e ) 568 | return NULL; // error: missing operand 569 | 570 | 571 | return e; 572 | } 573 | 574 | 575 | //-------------------------------------------------------------------- 576 | // read one expression for a function - expects to see opening parenthesis ( 577 | dkexpression *dkgetfirstexpression( char * line ) 578 | { 579 | dkexpression *e; 580 | char t[ MAX_TOKEN_LENGTH+1 ]; 581 | 582 | 583 | line = dkgettoken( line, t ); // get token - ( 584 | if( t[0] != '(' ) 585 | return NULL; // error: syntax error (missing closing parenthesis) 586 | 587 | e = expression( line ); // process expression @line 588 | if( !e ) 589 | return NULL; // error: missing operand 590 | 591 | 592 | return e; 593 | } 594 | */ 595 | 596 | //-------------------------------------------------------------------- 597 | // remove leading and trailing quotes if they exist 598 | char *dkdequote( char *t ) 599 | { 600 | if( strlen(t) > 1 && t[ 0 ] =='\"' ) 601 | { 602 | if( t[ strlen(t)-1 ] == '\"' ) 603 | t[ strlen(t)-1 ] = '\0'; // remove trailing " 604 | return t+1; // skip over leading " 605 | } 606 | return t; 607 | } 608 | 609 | //-------------------------------------------------------------------- 610 | 611 | char *dkunescape( char *t ) 612 | { 613 | int i; 614 | 615 | if( !t[0] ) 616 | return t; // null string 617 | 618 | for( i=0; t[i+1]; i++ ) 619 | { 620 | if( t[i] == '\\' ) 621 | { 622 | switch( t[i+1] ) 623 | { 624 | case '\\': 625 | i++; 626 | strcpy( t+i, t+i+1 ); 627 | break; 628 | 629 | case 'n': 630 | case 'r': 631 | t[i] = '\r'; 632 | i++; 633 | strcpy( t+i, t+i+1 ); 634 | break; 635 | } 636 | } 637 | } 638 | 639 | return t; 640 | } 641 | 642 | //-------------------------------------------------------------------- 643 | -------------------------------------------------------------------------------- /dkstring.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #ifndef _dkstring_h 3 | #define _dkstring_h 4 | //-------------------------------------------------------------------- 5 | //#include "dkexpression.h" 6 | 7 | 8 | // http://www.computer-engineering.org/ps2keyboard/scancodes2.html 9 | 10 | // 0xAA is value returned by keyboard after reset and BAT 11 | #define DKKEY_BATOK 0xAA 12 | 13 | 14 | #define DKKEY_NUMLOCK 0x77 15 | #define DKKEY_SCROLL 0x7E 16 | 17 | #define DKKEY_PAUSE (0x80+0x7A) 18 | #define DKKEY_PRTSCR (0x80+0x7B) 19 | #define DKKEY_SYSRQ (0x80+0x7C) 20 | //#define DKKEY_BREAK (0x80+0x7E) 21 | // BREAK is same as ctrl-C 22 | #define DKKEY_BREAK (0x03) 23 | 24 | #define DKKEY_NUM_9 (0x80+0x19) 25 | #define DKKEY_NUM_8 (0x80+0x18) 26 | #define DKKEY_NUM_7 (0x80+0x17) 27 | #define DKKEY_NUM_6 (0x80+0x16) 28 | #define DKKEY_NUM_5 (0x80+0x15) 29 | #define DKKEY_NUM_4 (0x80+0x14) 30 | #define DKKEY_NUM_3 (0x80+0x13) 31 | #define DKKEY_NUM_2 (0x80+0x12) 32 | #define DKKEY_NUM_1 (0x80+0x11) 33 | #define DKKEY_NUM_0 (0x80+0x10) 34 | #define DKKEY_NUM_PER (0x80+0x0E) 35 | 36 | #define DKKEY_DEL (0x80+0x6E) 37 | #define DKKEY_INS (0x80+0x70) 38 | #define DKKEY_END (0x80+0x71) 39 | #define DKKEY_DOWN (0x80+0x72) 40 | #define DKKEY_PGDN (0x80+0x73) 41 | #define DKKEY_LEFT (0x80+0x74) 42 | #define DKKEY_RIGHT (0x80+0x76) 43 | #define DKKEY_HOME (0x80+0x77) 44 | #define DKKEY_UP (0x80+0x78) 45 | #define DKKEY_PGUP (0x80+0x79) 46 | 47 | 48 | #define DKKEY_F1 (0x80+0x01) 49 | #define DKKEY_F2 (0x80+0x02) 50 | #define DKKEY_F3 (0x80+0x03) 51 | #define DKKEY_F4 (0x80+0x04) 52 | #define DKKEY_F5 (0x80+0x05) 53 | #define DKKEY_F6 (0x80+0x06) 54 | #define DKKEY_F7 (0x80+0x07) 55 | #define DKKEY_F8 (0x80+0x08) 56 | #define DKKEY_F9 (0x80+0x09) 57 | #define DKKEY_F10 (0x80+0x0A) 58 | #define DKKEY_F11 (0x80+0x0B) 59 | #define DKKEY_F12 (0x80+0x0C) 60 | 61 | 62 | #define DKKEY_APPS (0x80+0x2F) 63 | 64 | 65 | // ACPI scan codes 66 | #define DKKEY_POWER (0x80+0x37) 67 | #define DKKEY_SLEEP (0x80+0x3F) 68 | #define DKKEY_WAKE (0x80+0x5E) 69 | 70 | // Windows Multimedia Scan Codes: (from http://www.computer-engineering.org/ps2keyboard/scancodes2.html) 71 | #define DKKEY_NEXTTRACK (0x80+0x4D) 72 | #define DKKEY_PREVTRACK (0x80+0x15) /// 73 | #define DKKEY_STOP (0x80+0x3B) 74 | #define DKKEY_PLAYPAUSE (0x80+0x34) 75 | #define DKKEY_MOUTE (0x80+0x23) 76 | #define DKKEY_VOLUP (0x80+0x32) 77 | #define DKKEY_VOLDOWN (0x80+0x21) 78 | #define DKKEY_MEDIA (0x80+0x50) 79 | #define DKKEY_EMAIL (0x80+0x48) 80 | #define DKKEY_CALCULATOR (0x80+0x2B) 81 | #define DKKEY_MYCOMPUTER (0x80+0x40) 82 | #define DKKEY_WWWSEARCH (0x80+0x10) ///// 83 | #define DKKEY_WWWHOME (0x80+0x3A) 84 | #define DKKEY_WWWBACK (0x80+0x38) 85 | #define DKKEY_WWWFORWARD (0x80+0x30) 86 | #define DKKEY_WWWSTOP (0x80+0x28) 87 | #define DKKEY_WWWREFRESH (0x80+0x20) 88 | #define DKKEY_WWWFAVORITES (0x80+0x18) ///// 89 | 90 | #define DKKEY_CTRLC (0x03) 91 | 92 | //-------------------------------------------------------------------- 93 | // KEY definitions (for F1-F10) 94 | 95 | extern char dk_funckeystr[10][16]; 96 | 97 | 98 | 99 | // note: always allocate one extra byte (for NULL terminator) 100 | #define MAX_LINE_LENGTH 512 101 | 102 | // note: MAX_TOKEN_LENGTH limits the length of "" strings! (TODO: pass dynamic max string length to dkgettoken) 103 | #define MAX_TOKEN_LENGTH 48 104 | 105 | 106 | 107 | //-------------------------------------------------------------------- 108 | 109 | void dkgets( char *s ); 110 | // dkpregets - like gets, but the string s can be pre-filled 111 | void dkpregets( char *s ); 112 | void dkpregetsi( char *s, int i ); 113 | 114 | // dkvt102input() - return 'c' scancode value converted from VT102 escape sequence 115 | uint8_t dkvt102input(void); 116 | 117 | char *dkgettoken( char *expstring, char *t ); 118 | 119 | //extern char *dkgetnameflags( char *expstring, uint16_t *flags ); 120 | 121 | double dkstrtonum( char *s ); 122 | 123 | //extern dkexpression *dkgetnextexpression( char * line ); 124 | //extern dkexpression *dkgetfirstexpression( char * line ); 125 | 126 | char *dkdequote( char *t ); // remove " " from ends of string 127 | 128 | char *dkunescape( char *t ); 129 | 130 | 131 | //-------------------------------------------------------------------- 132 | #endif // !_dkstring_h 133 | //-------------------------------------------------------------------- 134 | 135 | -------------------------------------------------------------------------------- /dktables.S: -------------------------------------------------------------------------------- 1 | ;--------------------------------------------------------------------- 2 | ; dktables.S - for DK-INTERACTIVE - Chris Gerlinsky, 2011 3 | ;--------------------------------------------------------------------- 4 | 5 | .nolist 6 | #include // Include device specific definitions. 7 | .list 8 | 9 | 10 | ;--------------------------------------------------------------------- 11 | ; FLASH - code 12 | .section .text 13 | 14 | 15 | ;--------------------------------------------------------------------- 16 | ; dksearchtable 17 | ; r25:r24 in = ptr to string in ram 18 | ; r23:r22 in = ptr to start of table in flash 19 | ; r25:r24 out = ptr to statment handler function 20 | ; note: side effect: string is converted to lowercase 21 | 22 | .func dksearchtable 23 | .global dksearchtable 24 | dksearchtable: 25 | push r2 ; save call-saved registers 26 | push r3 ; save param passed to us in r3:r2 27 | push r4 ; save Z in r5:r4 28 | push r5 29 | 30 | 31 | movw r4, r22 ; temporarily save param2 (ptr to table in flash) in r5:r4 32 | movw r2, r24 ; save param in r2 33 | call strlwr ; convert string to lowercase 34 | movw r24, r2 35 | movw ZL, r4 ; copy param2 (ptr to table in flash) into Z 36 | 37 | 2: 38 | lpm r21, Z ; read first byte of entry name from flash 39 | cpi r21, 0 40 | brne 1f 41 | clr r24 ; name = NULL, end of table was reached 42 | clr r25 43 | rjmp 3f 44 | 1: 45 | 46 | movw r22, ZL ; r23:r22 points to string in flash (setup strcmp_P call) 47 | movw r24, r2 ; r25:r24 points to string in RAM 48 | 49 | movw r4, ZL 50 | call strcmp_P ; compare string in RAM to string in FLASH 51 | movw ZL, r4 52 | 53 | 1: 54 | lpm r21, Z+ ; adjust Z to point to end of item name in table (point to next item in table) 55 | cpi r21, 0 56 | brne 1b 57 | 58 | cpi r24, 0 ; check for successful string compare 59 | breq 1f 60 | 61 | adiw ZL, 2 ; push Z past address of prev handler 62 | rjmp 2b ; continue loop to check next entry in table 63 | 64 | 65 | 1: 66 | lpm r24, Z+ ; read 16-bit address of handler 67 | lpm r25, Z+ 68 | ; lsr r25 ; shift address to the right (adjust from byte address to word address) 69 | ; ror r24 70 | 3: 71 | pop r5 ; restore call-saved registers 72 | pop r4 73 | pop r3 74 | pop r2 75 | ret 76 | 77 | .endfunc 78 | 79 | 80 | ;--------------------------------------------------------------------- 81 | 82 | -------------------------------------------------------------------------------- /dktables.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #ifndef _dktables_h 3 | #define _dktables_h 4 | //-------------------------------------------------------------------- 5 | #include 6 | 7 | 8 | // this routine is in dkactiontable.S 9 | extern char * (*dkfindaction( char *str ))(char *str ); 10 | 11 | 12 | // this routine is in dktables.S (used by dkfindstatement/dkfindfunction) 13 | extern void (*dksearchtable( char *str, PGM_P ))(char *str ); 14 | 15 | 16 | extern uint8_t * dkactiontable; 17 | 18 | //-------------------------------------------------------------------- 19 | #endif // !_dktables_h 20 | //-------------------------------------------------------------------- 21 | 22 | -------------------------------------------------------------------------------- /dkterm.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "dkterm.h" 8 | #include "dkstring.h" 9 | #include "dkfile_uart.h" 10 | #include "dkvt100.h" 11 | //-------------------------------------------------------------------- 12 | 13 | volatile uint8_t io_ctrl_char; // control character if received (chars 0x01-0x1F) 14 | 15 | // uart_str is used to setup stdin/stdout 16 | FILE stdiostream = FDEV_SETUP_STREAM(dkterm_put, dkterm_get, _FDEV_SETUP_RW); 17 | 18 | 19 | struct _dkscreen dkscreen; 20 | 21 | struct _dkterm_interfaces *dkterm_interfaces=NULL; // list of active terminal interfaces 22 | 23 | 24 | //-------------------------------------------------------------------- 25 | int dkterm_init(void) 26 | { 27 | struct _dkterm_interfaces *newinterface; 28 | 29 | 30 | io_ctrl_char = 0; // no ctrl char has been received 31 | 32 | stdout = stdin = &stdiostream; // setup stdout and stdin streams 33 | 34 | dkterm_interfaces = NULL; // default to no active interfaces (_init functions will setup dkterm_interfaces) 35 | 36 | dkscreen.row = 1; // set initial values for dkscreen 37 | dkscreen.col = 1; 38 | 39 | dkscreen.width = 80; // regular terminal is 80 cols wide 40 | // dkscreen.width = 38; // tellymate is 38 cols wide 41 | dkscreen.height = 25; 42 | 43 | dkscreen.scrolltop = 1; // define top and bottom of scrolling area (1-25 = entire screen scrolls) 44 | dkscreen.scrollbot = 25; // note: using a smaller scrolling area results in slower scrolling 45 | // note: scrolling is tellymate-only 46 | 47 | //#ifdef _DK_USE_UART0 48 | // printf_P( PSTR("\nInit UART0... ") ); 49 | 50 | newinterface = (struct _dkterm_interfaces *)malloc( sizeof( struct _dkterm_interfaces ) ); 51 | newinterface->next = NULL; 52 | 53 | newinterface->devfile = dkfopen( "COM0:115200,N,8,1", "r+" ); 54 | ((struct _dk_uart *)newinterface->devfile->info)->_flag |= DKUART_FLAG_TERMINAL; 55 | newinterface->terminal = &dkterm_vt100; // indicate that VT100 terminal mode is active 56 | 57 | dkterm_interfaces = newinterface; // link new _dkterm_interfaces item into list 58 | 59 | // printf_P( PSTR("\rInit UART... OK\n") ); 60 | //#endif // _DK_USE_UART0 61 | 62 | 63 | return 1; 64 | } 65 | 66 | //-------------------------------------------------------------------- 67 | 68 | int dkterm_put( char c, FILE *unused ) 69 | { 70 | struct _dkterm_interfaces *ifaces; 71 | 72 | 73 | while( io_ctrl_char == DKKEY_PAUSE ) 74 | ; // pause received, wait until that signal removed 75 | 76 | 77 | for( ifaces=dkterm_interfaces; ifaces; ifaces=ifaces->next ) 78 | ifaces->terminal->put( c, ifaces->devfile ); 79 | 80 | if( dkterm_interfaces && ((struct _dk_uart *)dkterm_interfaces->devfile->info)->_flag & DKUART_FLAG_TERMINAL ) 81 | { 82 | switch( c ) 83 | { 84 | case '\n': 85 | dkscreen.row++; 86 | if( dkscreen.row > dkscreen.height ) 87 | dkscreen.row = dkscreen.height; 88 | dkterm_put( '\r', NULL ); // send CR with LF 89 | break; 90 | 91 | case '\r': 92 | dkscreen.col = 1; 93 | break; 94 | 95 | case '\b': 96 | dkscreen.col--; 97 | if( dkscreen.col < 1 ) 98 | dkscreen.col = 1; 99 | break; 100 | 101 | default: 102 | dkscreen.col++; 103 | break; 104 | } 105 | 106 | if( dkscreen.col > dkscreen.width ) // print newline after col80 107 | { 108 | dkterm_put( '\n', NULL ); 109 | return 0; 110 | } 111 | } 112 | 113 | return 0; 114 | 115 | /* 116 | if( dkterm_interfaces & dkterm_TELLY ) 117 | { 118 | if( dkscreen.row < dkscreen.scrollbot ) 119 | { 120 | dkscreen.row++; 121 | telly_put('\n'); 122 | } 123 | else 124 | { // note: handling the tellymate scrolling here isn't very clean - should be in dktelly.c 125 | if( dkscreen.scrolltop > 1 ) 126 | { 127 | if( topregion ) 128 | free( topregion ); 129 | topregion = (char *)malloc( (dkscreen.scrolltop-1) * dkscreen.width ); 130 | if( !topregion ) // malloc error! 131 | return 0; 132 | 133 | telly_put(0x1B); // turn cursor off 134 | telly_put('f'); 135 | 136 | telly_goto( 1, 1 ); 137 | for( i = 0 ; i+1 < dkscreen.scrolltop; i++ ) 138 | { 139 | for( n = 0; n < dkscreen.width; n++ ) 140 | { // save line from screen 141 | topregion[ (i*dkscreen.width) + n ] = telly_charhere(); 142 | telly_put(0x1B); // advance cursor 143 | telly_put('C'); // if we overwrite with a space now, there is a lot of flicker in non-scroll region 144 | } 145 | telly_put('\n'); 146 | } 147 | telly_goto( dkscreen.scrollbot, 1 ); 148 | } 149 | 150 | 151 | if( dkscreen.height-dkscreen.scrollbot ) 152 | { 153 | botregion = (char *)malloc( (dkscreen.height-dkscreen.scrollbot) * dkscreen.width ); 154 | if( !botregion ) // malloc error! 155 | { 156 | if( topregion ) 157 | free( topregion ); 158 | return 0; 159 | } 160 | 161 | telly_put(0x1B); // turn cursor off 162 | telly_put('f'); 163 | // _delay_ms(10); // a short delay is required here for cursor to turn off 164 | 165 | 166 | telly_goto( dkscreen.scrollbot, 1 ); 167 | for( i = 0 ; i+dkscreen.scrollbot+1 <= dkscreen.height; i++ ) 168 | { 169 | telly_put('\n'); 170 | for( n = 0; n < dkscreen.width; n++ ) 171 | { // save line from screen 172 | botregion[ (i*dkscreen.width) + n ] = telly_charhere(); 173 | telly_put(0x1B); // advance cursor 174 | telly_put('C'); // if we overwrite with a space now, there is a lot of flicker in non-scroll region 175 | } 176 | } 177 | // scroll screen 178 | 179 | 180 | 181 | // reprint lines saved from screen 182 | telly_goto( dkscreen.scrollbot+1, 1 ); 183 | for( i = 0 ; i+dkscreen.scrollbot+1 <= dkscreen.height; i++ ) 184 | { 185 | telly_put(0x1B); // clear line 186 | telly_put('l'); 187 | telly_put('\n'); 188 | for( n = 0; n < dkscreen.width; n++ ) 189 | { 190 | if( botregion[ (i*dkscreen.width) + n ] ) 191 | telly_put( botregion[ (i*dkscreen.width) + n ] ); 192 | else 193 | telly_put( ' ' ); 194 | } 195 | } 196 | 197 | free( botregion ); 198 | 199 | telly_goto( dkscreen.scrollbot-1, 1 ); 200 | telly_put(0x1B); // clear line 201 | telly_put('l'); 202 | 203 | // telly_put(0x1B); // turn cursor on 204 | // telly_put('e'); 205 | } 206 | else 207 | telly_put( '\n' ); 208 | 209 | if( dkscreen.scrolltop > 1 ) 210 | { 211 | // reprint lines saved from screen 212 | telly_goto( 1, 1 ); 213 | for( i = 0 ; i+1 < dkscreen.scrolltop; i++ ) 214 | { 215 | telly_put(0x1B); // clear line 216 | telly_put('l'); 217 | 218 | for( n = 0; n < dkscreen.width; n++ ) 219 | { // save line from screen 220 | if( topregion[ (i*dkscreen.width) + n ] ) 221 | telly_put( topregion[ (i*dkscreen.width) + n ] ); 222 | else 223 | telly_put( ' ' ); 224 | } 225 | telly_put('\n'); 226 | } 227 | 228 | free( topregion ); 229 | 230 | telly_goto( dkscreen.scrollbot-1, 1 ); 231 | 232 | // telly_put(0x1B); // turn cursor on 233 | // telly_put('e'); 234 | } 235 | telly_put(0x1B); // turn cursor on 236 | telly_put('e'); 237 | } 238 | }// if( dkterm_interfaces & dkterm_TELLY ) 239 | */ 240 | 241 | } 242 | 243 | //-------------------------------------------------------------------- 244 | int dkterm_get( FILE *unused ) 245 | { 246 | struct _dkterm_interfaces *ifaces; 247 | 248 | 249 | while( 1 ) // loop until ctrl-c received or byte received 250 | { 251 | for( ifaces=dkterm_interfaces; ifaces; ifaces=ifaces->next ) 252 | { 253 | if( ifaces->terminal->kbhit( ifaces->devfile ) ) 254 | return ifaces->terminal->get( ifaces->devfile ); 255 | } 256 | } 257 | 258 | return -1; 259 | } 260 | 261 | //-------------------------------------------------------------------- 262 | int _kbhit(void) 263 | { 264 | struct _dkterm_interfaces *ifaces; 265 | 266 | 267 | for( ifaces=dkterm_interfaces; ifaces; ifaces=ifaces->next ) 268 | { 269 | if( ifaces->terminal->kbhit( ifaces->devfile ) ) 270 | return 1; 271 | } 272 | 273 | 274 | return 0; 275 | } 276 | 277 | 278 | //-------------------------------------------------------------------- 279 | int _getch(void) 280 | { 281 | return dkterm_get( NULL ); 282 | } 283 | 284 | 285 | //-------------------------------------------------------------------- 286 | void _putch( char c ) 287 | { 288 | dkterm_put( c, NULL ); 289 | 290 | return; 291 | } 292 | 293 | //-------------------------------------------------------------------- 294 | 295 | //- standard dkio interface functions for gotoxy, getfromscreen, clearscreen, etc 296 | int dkterm_gotoxy( int x, int y ) 297 | { 298 | struct _dkterm_interfaces *ifaces; 299 | 300 | 301 | for( ifaces=dkterm_interfaces; ifaces; ifaces=ifaces->next ) 302 | ifaces->terminal->gotoxy( x, y, ifaces->devfile ); 303 | 304 | dkscreen.col=x; 305 | dkscreen.row=y; 306 | 307 | 308 | return 0; 309 | } 310 | 311 | //-------------------------------------------------------------------- 312 | int dkterm_clearscreen( void ) 313 | { 314 | struct _dkterm_interfaces *ifaces; 315 | 316 | 317 | for( ifaces=dkterm_interfaces; ifaces; ifaces=ifaces->next ) 318 | ifaces->terminal->clearscreen( ifaces->devfile ); 319 | 320 | return 0; 321 | } 322 | //-------------------------------------------------------------------- 323 | void _flushuntil( char c ) // flush input buffer up to and including c 324 | { 325 | while( _kbhit() ) // flush everything in buffer up to and including c 326 | { 327 | if( _getch() == c ) 328 | break; 329 | } 330 | } 331 | //-------------------------------------------------------------------- 332 | -------------------------------------------------------------------------------- /dkterm.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #ifndef _dkterm_h 3 | #define _dkterm_h 4 | //-------------------------------------------------------------------- 5 | #include 6 | #include "dkfile.h" 7 | 8 | //-------------------------------------------------------------------- 9 | // bitmasks for dkterm_interfaces 10 | #define DKTERM_VT100 1 11 | 12 | //-------------------------------------------------------------------- 13 | 14 | struct _dkscreen 15 | { 16 | uint8_t row; 17 | uint8_t col; 18 | 19 | uint8_t width; 20 | uint8_t height; 21 | 22 | uint8_t scrolltop; 23 | uint8_t scrollbot; 24 | }; 25 | 26 | //-------------------------------------------------------------------- 27 | 28 | struct _dkterminal 29 | { 30 | char name[8]; 31 | 32 | int (*put)( char c, DKFILE *devfile ); 33 | int (*get)( DKFILE *devfile ); 34 | int (*kbhit)( DKFILE *devfile ); 35 | int (*gotoxy)( int x, int y, DKFILE *devfile ); 36 | int (*clearscreen)( DKFILE *devfile); 37 | }; 38 | 39 | 40 | struct _dkterm_interfaces 41 | { 42 | DKFILE *devfile; 43 | struct _dkterminal *terminal; 44 | struct _dkterm_interfaces *next; 45 | }; 46 | 47 | extern struct _dkscreen dkscreen; 48 | 49 | //extern uint8_t rx_buffer[128]; // circular buffer for received data 50 | //extern uint16_t rx_buflen; 51 | //extern volatile uint8_t rx_wr_ptr, rx_rd_ptr; // pointers into rx_buffer 52 | 53 | extern volatile uint8_t io_ctrl_char; // control character if received (chars 0x01-0x1F) 54 | 55 | // uart_str is used to setup stdin/stdout 56 | extern FILE stdiostream; 57 | 58 | extern struct _dkterm_interfaces *dkterm_interfaces; // list of active terminal interfaces 59 | 60 | //-------------------------------------------------------------------- 61 | 62 | extern int _kbhit(void); 63 | extern int _getch(void); 64 | extern void _putch( char c ); 65 | 66 | extern void _flushuntil( char c ); // flush input buffer up to and including c 67 | 68 | //-------------------------------------------------------------------- 69 | extern int dkterm_init(void); 70 | extern int dkterm_put( char c, FILE *unused ); 71 | extern int dkterm_get( FILE *unused ); 72 | extern int dkterm_gotoxy( int x, int y ); 73 | extern int dkterm_clearscreen( void ); 74 | //-------------------------------------------------------------------- 75 | #endif // !_term_h 76 | //-------------------------------------------------------------------- 77 | -------------------------------------------------------------------------------- /dkvt100.c: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #include 3 | #include 4 | 5 | #include "dkvt100.h" 6 | #include "dkfile.h" 7 | //-------------------------------------------------------------------- 8 | 9 | struct _dkterminal dkterm_vt100 = 10 | { 11 | "VT100", 12 | dkvt100_put, 13 | dkvt100_get, 14 | dkvt100_kbhit, 15 | dkvt100_gotoxy, 16 | dkvt100_clearscreen 17 | }; 18 | 19 | 20 | 21 | //-------------------------------------------------------------------- 22 | int dkvt100_put( char c, DKFILE *devfile ) 23 | { 24 | dkfputc( c, devfile ); 25 | 26 | 27 | return 0; 28 | } 29 | //-------------------------------------------------------------------- 30 | int dkvt100_get( DKFILE *devfile ) 31 | { 32 | return dkfgetc( devfile ); 33 | } 34 | //-------------------------------------------------------------------- 35 | int dkvt100_kbhit( DKFILE *devfile ) 36 | { 37 | return !dkfeof( devfile ); 38 | } 39 | //-------------------------------------------------------------------- 40 | int dkvt100_gotoxy( int x, int y, DKFILE *devfile ) 41 | { 42 | char tempstr[6]; // temporary string used for itoa 43 | int i; 44 | 45 | 46 | dkfputc( 0x1B, devfile ); 47 | dkfputc( '[', devfile ); 48 | itoa( y, tempstr, 10 ); 49 | for( i=0; tempstr[i]; i++ ) 50 | dkfputc( tempstr[i], devfile ); 51 | dkfputc( ';', devfile ); 52 | itoa( x, tempstr, 10 ); 53 | for( i=0; tempstr[i]; i++ ) 54 | dkfputc( tempstr[i], devfile ); 55 | dkfputc( 'f', devfile ); 56 | 57 | 58 | return 0; 59 | } 60 | 61 | //-------------------------------------------------------------------- 62 | int dkvt100_clearscreen( DKFILE *devfile) 63 | { 64 | dkfputc( 0x1B, devfile ); // ANSI clear screen and home cursor 65 | dkfputc( '[', devfile ); 66 | dkfputc( '2', devfile ); 67 | dkfputc( 'J', devfile ); 68 | 69 | 70 | return 0; 71 | } 72 | //-------------------------------------------------------------------- 73 | -------------------------------------------------------------------------------- /dkvt100.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #ifndef _dkvt100_h 3 | #define _dkvt100_h 4 | //-------------------------------------------------------------------- 5 | #include "dkterm.h" 6 | 7 | //-------------------------------------------------------------------- 8 | extern int dkvt100_put( char c, DKFILE *devfile ); 9 | extern int dkvt100_get( DKFILE *devfile ); 10 | extern int dkvt100_kbhit( DKFILE *devfile ); 11 | extern int dkvt100_gotoxy( int x, int y, DKFILE *devfile ); 12 | extern int dkvt100_clearscreen( DKFILE *devfile); 13 | 14 | 15 | extern struct _dkterminal dkterm_vt100; 16 | 17 | 18 | //-------------------------------------------------------------------- 19 | #endif // !_dkvt100_h 20 | //-------------------------------------------------------------------- 21 | -------------------------------------------------------------------------------- /hardware.h: -------------------------------------------------------------------------------- 1 | //-------------------------------------------------------------------- 2 | #ifndef _HARDWARE_H 3 | #define _HARDWARE_H 4 | //-------------------------------------------------------------------- 5 | #include 6 | 7 | 8 | #define GVCC_PORT PORTA 9 | #define GVCC_SW 0 10 | #define GVCC_EN 3 11 | 12 | 13 | #define G2981_PORT PORTA 14 | #define G2981_SW 5 15 | 16 | 17 | #define TRST_PORT PORTF 18 | #define TRST_BIT 0 19 | 20 | 21 | #define TISP_PORT PORTF 22 | #define TISP_BIT 1 23 | 24 | 25 | //-------------------------------------------------------------------- 26 | #endif // #ifndef _HARDWARE_H 27 | //-------------------------------------------------------------------- 28 | -------------------------------------------------------------------------------- /readme.txt: -------------------------------------------------------------------------------- 1 | Source files: 2 | -------------- 3 | dkactiontable.S Table of all supported action functions 4 | dkclock.c Clock configuration (Xmega oscillator) 5 | dkclock.h 6 | dkebi.c EBI configuration (external memory - 8MB SDRAM on Xplained board) 7 | dkebi.h 8 | dkfile.c File interface (used for stdio support and dkfopen() etc functions) 9 | dkfile.h 10 | dkfile_uart.c UART file interface (used by terminal emulation) 11 | dkfile_uart.h 12 | dkinteractive.c Interactive shell 13 | dkinteractive.h 14 | dkstring.c String manipulation functions 15 | dkstring.h 16 | dktables.h 17 | dktables.S Flash table manipulation 18 | dkterm.c Terminal emulation interface (uses dkfile.c file interface) 19 | dkterm.h 20 | dkvt100.c VT-100 terminal emulation 21 | dkvt100.h 22 | Makefile 23 | xplainer.c main() function 24 | actions/beep.c BEEP action - make a loud beep with the Xplained speaker 25 | actions/button0.c action executed when Button0 (SW0) pressed 26 | actions/button1.c action executed when Button1 (SW1) pressed 27 | actions/button2.c action executed when Button2 (SW2) pressed 28 | actions/button3.c action executed when Button3 (SW3) pressed 29 | actions/button4.c action executed when Button4 (SW4) pressed 30 | actions/button5.c action executed when Button5 (SW5) pressed 31 | actions/button6.c action executed when Button6 (SW6) pressed 32 | actions/button7.c action executed when Button7 (SW7) pressed 33 | actions/disco.c DISCO action 34 | actions/help.c HELP action 35 | actions/hotbutton.c HOTBUTTON action - set commands performed when buttons (SW0-SW7) pressed 36 | actions/hotkey.c HOTKEY action - set commands peformed when hotkeys (F1-F12) pressed 37 | actions/led.c LED action - turn on/off LED0-LED8 38 | actions/peek.c PEEK action - read byte from a memory address 39 | actions/poke.c POKE action - write byte to a memory address 40 | 41 | Compiled files: 42 | ---------------- 43 | xplainer.eep Generated EEPROM contents for ATxmega128A1 44 | xplainer.hex Generated FLASH contents for ATxmega128A1 45 | 46 | In progress: 47 | ------------- 48 | actions/temp.c TEMP action - read temperature from NTC, using ADCB.0 49 | 50 | 51 | Compiling: 52 | ----------- 53 | Type 'make' build Makefile. 54 | 'make clean' will remove object and linked binaries. 55 | 'make prog' will make clean, make, and use avrdude to program the target device. 56 | 57 | 58 | In the Makefile: 59 | ----------------- 60 | DEFS = -DF_CPU=32000000 -D_GLITCHER_VERSION_NUM=2 61 | 62 | -DF_CPU=32000000 63 | The 32MHz RC oscillator is selected by dk_clock_init() in xplainer.c. 64 | If oscillator settings are changed, this should be adjusted to match. 65 | 66 | -D_DK_VERSION_NUM=2 67 | The version number for the compiled project. 68 | 69 | 70 | Adding an action: 71 | ------------------ 72 | 1) create actions/new.c with "char *dkaction_new( char *line )" function 73 | - return value isn't actually used, but unprocessed remnant of line should be returned 74 | 2) add action to dkactiontable in dkactiontable.S 75 | .string "new" 76 | .word dkaction_new 77 | 3) add actions/new.c to CSRC line of Makefile 78 | 4) add description and usage to actions/help.c 79 | 80 | 81 | "Hello, world!" example action: 82 | -------------------------------- 83 | 1) All action program code is in actions/hello.c 84 | 85 | 2) Add to dkactiontable: (dkactiontable.S): 86 | .string "hello" ; keyword "hello" - "Hello, world!" example 87 | .word dkaction_hello ; dkaction_hello() in actions/hello.c 88 | 89 | 3) Add actions/hello.c to CSRC = in Makefile 90 | 91 | 4) Add to printf_P() in dkaction_help() (actions/help.c): 92 | "HELLO (\"Hello, world!\" example action)\n" 93 | 94 | 95 | Hardware usage: 96 | ---------------- 97 | (as per Xmega-A1 Xplained board (blue PCB), 2011-05-22) 98 | 99 | EBI (SDRAM - 3-port EBI) 100 | PORTK.DIR = 0xFF; 101 | PORTJ.DIR = 0xFF; 102 | PORTH.DIR = 0xFF; 103 | 104 | LEDs (LED0-LED7) 105 | PORTE.DIR = 0xFF; 106 | 107 | buttons (SW0-SW7) 108 | PORTD 0-5 (inputs, pullup enabled) 109 | PORTR 0-2 (inputs, pullup enabled) 110 | 111 | thermsistor (NTC) 112 | PORTB 0 (ADC) 113 | PORTB 3 [NTC_EN] 114 | 115 | light sensor 116 | PORTB 1 (ADC) 117 | 118 | speaker 119 | PORTB 2 (DAC) 120 | PORTQ 3 [AUDIO_SD] 121 | 122 | dataflash (optional) 123 | SPIC PORTC 5-7 124 | PORTQ 2 [DATAFLASH_CS] 125 | 126 | USB serial adapter (32UC3B1256) 127 | USARTC0 (PC2=RXD, PC3=TXD) 128 | 128-byte buffer for incoming data (96-byte limit before flow control kicks in) 129 | flow control disabled (not supported by 32uc3) 130 | 57600 8-n-1 comm to 32uc3 131 | 132 | JTAG 133 | PORTB 4-7 134 | 135 | J1 = PORTF (shared with board controller spi/board controller twi) 136 | J2 = PORTA 137 | J3 = PORTD 0-5, PORTR 0-1 (shared with buttons) 138 | J4 = PORTC (PC2/PC3 USARTC shared with board controller) 139 | 140 | 141 | 142 | VPORT configs 143 | no vports needed/utilized 144 | 145 | 146 | interrupts: 147 | global interrupt enabled 148 | PMIC = LOLVLEX 149 | enabled interrupts: 150 | USARTC0_RXCINTLVL 151 | button presses 152 | 153 | 154 | Interactive interface: 155 | ----------------------- 156 | VT100 terminal emulation (cursor keys, insert/delete, function keys) 157 | 158 | Lines are terminated with carriage return (\r). 159 | On input, newlines (\n) are ignored. 160 | On output, newlines (\n) may be converted to carriage return (\r) 161 | - or expanded into CRLF (\r\n) sequence. 162 | 163 | NOTE: ctrl-Z works as pause! 164 | 165 | 166 | Terminal software: 167 | ------------------- 168 | Tested using minicom in Linux and PuTTY in Windows 7 using PJRC generic CDC ACM driver 169 | Settings: 170 | - 115200 8-N-1 171 | - VT100 terminal emulation 172 | 173 | 174 | -------------------------------------------------------------------------------- /timeout.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | //-------------------------------------------------------------------- 6 | // clk for timer1 for target timeout is / 1024 (TC_CLKSEL_DIV1024_gc) 7 | #define T_TIMEOUT_DIV 1024L 8 | 9 | int t_timeout_ticks = F_CPU / T_TIMEOUT_DIV; // 1 second @ 16 MHz / 1024 is 15625 ticks 10 | 11 | 12 | // start target timeout, use global 't_timeout_ticks' as time when TIFR.OCF1A will be set to indicate timeout 13 | void t_timeout_start(void) 14 | { 15 | // stop the timer while configuring it 16 | TCC0.CTRLB = 0; 17 | 18 | // reset timer count to 0 19 | TCC0.CNT = 0; 20 | TCC0.PER = t_timeout_ticks; 21 | TCC0.CTRLA = TC_CLKSEL_DIV1024_gc; 22 | // TCC0.INTCTRLA = TC_OVFINTLVL_LO_gc; 23 | TCC0.INTCTRLA = 0; 24 | TCC0.INTFLAGS = 0x01; // clear the OVFIF flag 25 | 26 | // start timer by selecting clock source 27 | TCC0.CTRLB = TC_WGMODE_NORMAL_gc; 28 | } 29 | 30 | 31 | void t_timeout_stop(void) 32 | { 33 | // stop the timer while configuring it 34 | TCC0.CTRLB = 0; 35 | 36 | TCC0.INTFLAGS = 0x01; // clear the OVFIF flag 37 | } 38 | 39 | 40 | void t_timeout_after_ms(int t_ms) 41 | { 42 | t_timeout_ticks = ((unsigned long)t_ms * (F_CPU/1000)) / T_TIMEOUT_DIV; 43 | t_timeout_start(); 44 | } 45 | 46 | 47 | // returns 1 if t_timeout has expired 48 | int t_timeout_check(void) 49 | { 50 | if( TCC0.INTFLAGS & 0x01 ) 51 | return 1; 52 | else 53 | return 0; 54 | } 55 | 56 | 57 | void t_timeout_clear(void) 58 | { 59 | TCC0.INTFLAGS = 0x01; // clear the OVFIF flag 60 | } 61 | 62 | -------------------------------------------------------------------------------- /timeout.h: -------------------------------------------------------------------------------- 1 | #ifndef __TIMER_H 2 | #define __TIMER_H 3 | 4 | // start target timeout, use global 't_timeout_ticks' as time when TIFR.OCF1A will be set to indicate timeout 5 | void t_timeout_start(void); 6 | 7 | void t_timeout_stop(void); 8 | 9 | void t_timeout_after_ms(int t_ms); 10 | 11 | // returns 1 if t_timeout has expired 12 | int t_timeout_check(void); 13 | 14 | void t_timeout_clear(void); 15 | 16 | #endif // __TIMER_H 17 | -------------------------------------------------------------------------------- /xplainer.c: -------------------------------------------------------------------------------- 1 | ////////////////////////////////////////////////////////////////////// 2 | // software for Xmega-A1 Xplained board (blue PCB) 3 | // Chris Gerlinsky, 2010-2016 4 | ////////////////////////////////////////////////////////////////////// 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "hardware.h" 11 | #include "dkterm.h" 12 | #include "dkvt100.h" 13 | #include "dkstring.h" 14 | #include "dkinteractive.h" 15 | #include "dkbuttons.h" 16 | #include "dkebi.h" 17 | #include "dkclock.h" 18 | 19 | 20 | ////////////////////////////////////////////////////////////////////// 21 | 22 | int main( void ) 23 | { 24 | uint8_t led_pattern[] = {0xFE, 0xFD, 0xFB, 0xF7, 0xFF, 0xFF, 0x7F, 0xBF, 0xDF, 0xEF, 0xFF, 0xFF, 0xFE}; 25 | int i; 26 | 27 | 28 | dk_clock_init(); // initialize clock (32 MHz RC oscillator) 29 | 30 | // _delay_ms(2000); // wait 2 seconds for USB to connect 31 | 32 | PORTE.DIR = 0xFF; // set PORTE as output (LEDs) 33 | 34 | for( i=0; i < sizeof(led_pattern); i++ ) 35 | { 36 | PORTE.OUT = led_pattern[i]; // set LEDs to pattern 37 | _delay_ms( 50 ); 38 | } 39 | 40 | 41 | dk_ebi_init(); // initialize the EBI memory 42 | dkterm_init(); // initialize dkterm functions (inits dkfile_uart) 43 | // dkbuttons_init(); // initialize buttons (PD0-PD6,PR0-PR1) and interrupts 44 | 45 | 46 | 47 | G2981_PORT.OUTCLR = (1<