diff --git a/firmware/Makefile b/firmware/Makefile index 0309b7b..7f84184 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -1,11 +1,33 @@ -DIRS = lib fw +FW_DIRS = $(wildcard fw_*) +COMMON_DIRS = lib +PROJECT_DEFAULT = atlys +PROJECT_NAME ?= $(PROJECT_DEFAULT) +PROJECT_DIR = fw_$(PROJECT_NAME) +DIRS = $(COMMON_DIRS) $(PROJECT_DIR) -all: - @for dir in $(DIRS); do \ - $(MAKE) -C $$dir || exit 1; \ - done +##### PRINT ################################### +PW=\033[1m\033[0m +GR=\E[40;32m +WH=\E[40;37m +B=\033[1m +pr_info = "$(B) $(GR)[$(1)]\t $(WH)$(2)$(PW)" -clean: - @for dir in $(DIRS); do \ - $(MAKE) -C $$dir clean || exit 1; \ - done +##### BUILD RULES ############################# +.PHONY: help build clean build_all distclean + +help: + @echo -e "$$ make PROJECT_NAME= " + @echo -e "\tprojects (*=default) .. : $(shell echo $(FW_DIRS) | sed 's/fw_//g' | sed 's/$(PROJECT_DEFAULT)/\*$(PROJECT_DEFAULT)/')" + @echo -e "\trule .................. : help build clean build_all distclean" + +build: $(DIRS) + @$(foreach dir,$^, echo -e $(call pr_info,MK,Building $(dir)); $(MAKE) -C $(dir) || exit 1;) + +clean: $(DIRS) + @$(foreach dir,$^, echo -e $(call pr_info,MK,Cleaning $(dir)); $(MAKE) -C $(dir) clean || exit 1;) + +build_all: $(COMMON_DIRS) $(FW_DIRS) + @$(foreach dir,$^, echo -e $(call pr_info,MK,Building $(dir)); $(MAKE) -C $(dir) || exit 1;) + +distclean: $(COMMON_DIRS) $(FW_DIRS) + @$(foreach dir,$^, echo -e $(call pr_info,MK,Cleaning $(dir)); $(MAKE) -C $(dir) clean || exit 1;) diff --git a/firmware/fw/.gitignore b/firmware/fw_atlys/.gitignore similarity index 100% rename from firmware/fw/.gitignore rename to firmware/fw_atlys/.gitignore diff --git a/firmware/fw/Makefile b/firmware/fw_atlys/Makefile similarity index 100% rename from firmware/fw/Makefile rename to firmware/fw_atlys/Makefile diff --git a/firmware/fw/device.c b/firmware/fw_atlys/device.c similarity index 100% rename from firmware/fw/device.c rename to firmware/fw_atlys/device.c diff --git a/firmware/fw/dscr.a51 b/firmware/fw_atlys/dscr.a51 similarity index 100% rename from firmware/fw/dscr.a51 rename to firmware/fw_atlys/dscr.a51 diff --git a/firmware/fw/fw.c b/firmware/fw_atlys/fw.c similarity index 100% rename from firmware/fw/fw.c rename to firmware/fw_atlys/fw.c diff --git a/firmware/fw_dmb/.gitignore b/firmware/fw_dmb/.gitignore new file mode 100644 index 0000000..42e046d --- /dev/null +++ b/firmware/fw_dmb/.gitignore @@ -0,0 +1,9 @@ +*.asm +*.lst +*.rel +*.rst +*.sym +*.map +*.mem +*.bix +*.iic diff --git a/firmware/fw_dmb/Makefile b/firmware/fw_dmb/Makefile new file mode 100644 index 0000000..f7d4b40 --- /dev/null +++ b/firmware/fw_dmb/Makefile @@ -0,0 +1,5 @@ +SOURCES = fw.c device.c +A51_SOURCES = dscr.a51 +BASENAME = firmware + +include ../lib/fx2.mk diff --git a/firmware/fw_dmb/device.c b/firmware/fw_dmb/device.c new file mode 100644 index 0000000..9e4beac --- /dev/null +++ b/firmware/fw_dmb/device.c @@ -0,0 +1,127 @@ +#include +#include + +#ifdef DEBUG_FIRMWARE +#include +#else +#define printf(...) +#endif + +//************************** Configuration Handlers ***************************** +// change to support as many interfaces as you need +//volatile xdata BYTE interface=0; +//volatile xdata BYTE alt=0; // alt interface + +// set *alt_ifc to the current alt interface for ifc +BOOL +handle_get_interface(BYTE ifc, BYTE * alt_ifc) +{ +// *alt_ifc=alt; + return TRUE; +} + +// return TRUE if you set the interface requested +// NOTE this function should reconfigure and reset the endpoints +// according to the interface descriptors you provided. +BOOL +handle_set_interface(BYTE ifc, BYTE alt_ifc) +{ + printf("Set Interface.\n"); + //interface=ifc; + //alt=alt_ifc; + return TRUE; +} + +// handle getting and setting the configuration +// 1 is the default. If you support more than one config +// keep track of the config number and return the correct number +// config numbers are set int the dscr file. +//volatile BYTE config=1; +BYTE +handle_get_configuration() +{ + return 1; +} + +// NOTE changing config requires the device to reset all the endpoints +BOOL +handle_set_configuration(BYTE cfg) +{ + printf("Set Configuration.\n"); + //config=cfg; + return TRUE; +} + +//******************* VENDOR COMMAND HANDLERS ************************** +BOOL +handle_vendorcommand(BYTE cmd) +{ + switch (cmd) { +// case VC_EPSTAT: +// break; + default: + printf ( "Need to implement vendor command: %02x\n", cmd ); + } + + /* not handled by handlers */ + return FALSE; +} + +//******************** INIT *********************** +void +main_init() +{ + SYNCDELAY4; REVCTL = 0x03; + + /* set register default values */ + SYNCDELAY4; PINFLAGSAB = 0x00; + SYNCDELAY4; PINFLAGSCD = 0x00; + SYNCDELAY4; FIFOPINPOLAR = 0x00; + + /* SLAVE FIFO (set bmIFCLKPOL to ensure better setup times) */ + SYNCDELAY4; IFCONFIG = bmIFCLKSRC | bm3048MHZ | bmIFCLKOE | (bmIFCFG1 | bmIFCFG0); + + /* only valid endpoints are 2/6 */ + /* EP2 is DIR=OUT, TYPE=BULK, SIZE=512, BUF=2x (HOST->DEVICE) */ + SYNCDELAY4; EP2CFG = 0xa2; + + /* slave fifo configuration 8bit, autoout */ + //SYNCDELAY4; EP2FIFOCFG &= ~bmWORDWIDE; + SYNCDELAY4; EP2FIFOCFG = bmAUTOOUT; + SYNCDELAY4; EP2AUTOINLENH = 0x00; + SYNCDELAY4; EP2AUTOINLENL = 0x00; + /* EP6 is DIR=IN, TYPE=BULK, SIZE=512, BUF=2x (DEVICE->HOST) */ + SYNCDELAY4; EP6CFG = 0xe2; + /* slave fifo configuration 8bit, autoin, zero length */ + //SYNCDELAY4; EP6FIFOCFG &= ~bmWORDWIDE; + SYNCDELAY4; EP6FIFOCFG = bmAUTOIN | bmZEROLENIN; + /* AUTOIN packet length (512byte) */ + SYNCDELAY4; EP6AUTOINLENH = 0x02; + SYNCDELAY4; EP6AUTOINLENL = 0x00; + + /* unused fifos */ + SYNCDELAY4; EP4FIFOCFG = 0; + SYNCDELAY4; EP8FIFOCFG = 0; + + /* deactive other endpoints */ + SYNCDELAY4; EP1INCFG &= ~bmVALID; + SYNCDELAY4; EP1OUTCFG &= ~bmVALID; + SYNCDELAY4; EP4CFG &= ~bmVALID; + SYNCDELAY4; EP8CFG &= ~bmVALID; + + /* Reset the FIFO */ + SYNCDELAY4; FIFORESET = 0x80; + SYNCDELAY4; FIFORESET = 0x82; + SYNCDELAY4; FIFORESET = 0x84; + SYNCDELAY4; FIFORESET = 0x86; + SYNCDELAY4; FIFORESET = 0x00; + SYNCDELAY4; + + printf("Initialization Done.\n"); +} + +void +main_loop() +{ + // do some work +} diff --git a/firmware/fw_dmb/dscr.a51 b/firmware/fw_dmb/dscr.a51 new file mode 100644 index 0000000..efa0005 --- /dev/null +++ b/firmware/fw_dmb/dscr.a51 @@ -0,0 +1,189 @@ +.module DEV_DSCR + +; descriptor types +; same as setupdat.h +DSCR_DEVICE_TYPE=1 +DSCR_CONFIG_TYPE=2 +DSCR_STRING_TYPE=3 +DSCR_INTERFACE_TYPE=4 +DSCR_ENDPOINT_TYPE=5 +DSCR_DEVQUAL_TYPE=6 + +; for the repeating interfaces +DSCR_INTERFACE_LEN=9 +DSCR_ENDPOINT_LEN=7 + +; endpoint types +ENDPOINT_TYPE_CONTROL=0 +ENDPOINT_TYPE_ISO=1 +ENDPOINT_TYPE_BULK=2 +ENDPOINT_TYPE_INT=3 + + .globl _dev_dscr, _dev_qual_dscr, _highspd_dscr, _fullspd_dscr, _dev_strings, _dev_strings_end +; These need to be in code memory. If +; they aren't you'll have to manully copy them somewhere +; in code memory otherwise SUDPTRH:L don't work right + .area DSCR_AREA (CODE) + +_dev_dscr: + .db dev_dscr_end-_dev_dscr ; len + .db DSCR_DEVICE_TYPE ; type + .dw 0x0002 ; usb 2.0 + .db 0xff ; class (vendor specific) + .db 0xff ; subclass (vendor specific) + .db 0xff ; protocol (vendor specific) + .db 64 ; packet size (ep0) + .dw 0xB404 ; vendor id + .dw 0x4223 ; product id + .dw 0x0100 ; version id + .db 1 ; manufacturure str idx + .db 2 ; product str idx + .db 0 ; serial str idx + .db 1 ; n configurations +dev_dscr_end: + +_dev_qual_dscr: + .db dev_qualdscr_end-_dev_qual_dscr + .db DSCR_DEVQUAL_TYPE + .dw 0x0002 ; usb 2.0 + .db 0xff + .db 0xff + .db 0xff + .db 64 ; max packet + .db 1 ; n configs + .db 0 ; extra reserved byte +dev_qualdscr_end: + +_highspd_dscr: + .db highspd_dscr_end-_highspd_dscr ; dscr len ;; Descriptor length + .db DSCR_CONFIG_TYPE + ; can't use .dw because byte order is different + .db (highspd_dscr_realend-_highspd_dscr) % 256 ; total length of config lsb + .db (highspd_dscr_realend-_highspd_dscr) / 256 ; total length of config msb + .db 1 ; n interfaces + .db 1 ; config number + .db 0 ; config string + .db 0x80 ; attrs = bus powered, no wakeup + .db 0x32 ; max power = 100ma +highspd_dscr_end: + +; all the interfaces next +; NOTE the default TRM actually has more alt interfaces +; but you can add them back in if you need them. +; here, we just use the default alt setting 1 from the trm + .db DSCR_INTERFACE_LEN + .db DSCR_INTERFACE_TYPE + .db 0 ; index + .db 0 ; alt setting idx + .db 2 ; n endpoints + .db 0xff ; class + .db 0xff + .db 0xff + .db 0 ; string index + +; endpoint 2 out + .db DSCR_ENDPOINT_LEN + .db DSCR_ENDPOINT_TYPE + .db 0x02 ; ep2 dir=OUT and address + .db ENDPOINT_TYPE_BULK ; type + .db 0x00 ; max packet LSB + .db 0x02 ; max packet size=512 bytes + .db 0x00 ; polling interval + +; endpoint 6 in + .db DSCR_ENDPOINT_LEN + .db DSCR_ENDPOINT_TYPE + .db 0x86 ; ep6 dir=in and address + .db ENDPOINT_TYPE_BULK ; type + .db 0x00 ; max packet LSB + .db 0x02 ; max packet size=512 bytes + .db 0x00 ; polling interval + +highspd_dscr_realend: + +.even +_fullspd_dscr: + .db fullspd_dscr_end-_fullspd_dscr ; dscr len + .db DSCR_CONFIG_TYPE + ; can't use .dw because byte order is different + .db (fullspd_dscr_realend-_fullspd_dscr) % 256 ; total length of config lsb + .db (fullspd_dscr_realend-_fullspd_dscr) / 256 ; total length of config msb + .db 1 ; n interfaces + .db 1 ; config number + .db 0 ; config string + .db 0x80 ; attrs = bus powered, no wakeup + .db 0x32 ; max power = 100ma +fullspd_dscr_end: + +; all the interfaces next +; NOTE the default TRM actually has more alt interfaces +; but you can add them back in if you need them. +; here, we just use the default alt setting 1 from the trm + .db DSCR_INTERFACE_LEN + .db DSCR_INTERFACE_TYPE + .db 0 ; index + .db 0 ; alt setting idx + .db 2 ; n endpoints + .db 0xff ; class + .db 0xff + .db 0xff + .db 1 ; string index + +; endpoint 2 out + .db DSCR_ENDPOINT_LEN + .db DSCR_ENDPOINT_TYPE + .db 0x02 ; ep2 dir=OUT and address + .db ENDPOINT_TYPE_BULK ; type + .db 0x40 ; max packet LSB + .db 0x00 ; max packet size=64 bytes + .db 0x00 ; polling interval + +; endpoint 6 in + .db DSCR_ENDPOINT_LEN + .db DSCR_ENDPOINT_TYPE + .db 0x86 ; ep6 dir=in and address + .db ENDPOINT_TYPE_BULK ; type + .db 0x40 ; max packet LSB + .db 0x00 ; max packet size=64 bytes + .db 0x00 ; polling interval +fullspd_dscr_realend: + +.even +_dev_strings: +; sample string +_string0: + .db string0end-_string0 ; len + .db DSCR_STRING_TYPE + .db 0x09, 0x04 ; 0x0409 is the language code for English. Possible to add more codes after this. +string0end: +; add more strings here +_string1: + .db _string1end-_string1 ;; len + .db DSCR_STRING_TYPE + .db 'D',00 + .db 'M',00 + .db 'B',00 + .db '',00 + .db 'M',00 + .db 'O',00 + .db 'D',00 + .db 'U',00 + .db 'L',00 + .db 'E',00 +_string1end: +_string2: + .db _string2end-_string2 ;; len + .db DSCR_STRING_TYPE + .db 'V',00 + .db 'E',00 + .db 'R',00 + .db 'S',00 + .db 'I',00 + .db 'O',00 + .db 'N',00 + .db '',00 + .db 'X',00 +_string2end: + +_dev_strings_end: + .dw 0x0000 ; in case you wanted to look at memory between _dev_strings and _dev_strings_end diff --git a/firmware/fw_dmb/fw.c b/firmware/fw_dmb/fw.c new file mode 100644 index 0000000..dc236c5 --- /dev/null +++ b/firmware/fw_dmb/fw.c @@ -0,0 +1,119 @@ +#include +#include +#include +#include +#include + +#ifdef DEBUG_FIRMWARE +#include +#include +#else +#define printf(...) +#endif + +volatile __bit dosud = FALSE; +volatile __bit dosuspend = FALSE; + +// custom functions +extern void main_loop(); +extern void main_init(); + +void +main() +{ + +#ifdef DEBUG_FIRMWARE + SETCPUFREQ(CLK_48M); + // main_init can still set this to whatever you want. + sio0_init(57600); // needed for printf if debug defined +#endif + + main_init(); + + // set up interrupts. + USE_USB_INTS(); + + ENABLE_SUDAV(); + ENABLE_USBRESET(); + ENABLE_HISPEED(); + ENABLE_SUSPEND(); + ENABLE_RESUME(); + + /* global interrupt enable */ + EA = 1; + +// iic files (c2 load) don't need to renumerate/delay +// trm 3.6 +#ifndef NORENUM + RENUMERATE(); +#else + USBCS &= ~bmDISCON; +#endif + + while (TRUE) { + main_loop(); + + if (dosud) { + dosud = FALSE; + handle_setupdata(); + } + + if (dosuspend) { + dosuspend = FALSE; + do { + printf("I'm going to Suspend.\n"); + WAKEUPCS |= bmWU | bmWU2; // make sure ext wakeups are cleared + SUSPEND = 1; + PCON |= 1; + __asm + nop + nop + nop + nop + nop + nop + nop + __endasm; + } while (!remote_wakeup_allowed && REMOTE_WAKEUP()); + printf("I'm going to wake up.\n"); + + // resume + // trm 6.4 + if (REMOTE_WAKEUP()) { + delay(5); + USBCS |= bmSIGRESUME; + delay(15); + USBCS &= ~bmSIGRESUME; + } + } + } +} + +void +resume_isr() __interrupt RESUME_ISR { + CLEAR_RESUME(); +} + +void +sudav_isr() __interrupt SUDAV_ISR { + dosud = TRUE; + CLEAR_SUDAV(); +} + +void +usbreset_isr() __interrupt USBRESET_ISR { + handle_hispeed(FALSE); + CLEAR_USBRESET(); +} + +void +hispeed_isr() __interrupt HISPEED_ISR { + handle_hispeed(TRUE); + CLEAR_HISPEED(); +} + +void +suspend_isr() __interrupt SUSPEND_ISR { + dosuspend = TRUE; + CLEAR_SUSPEND(); +} diff --git a/firmware/lib/fx2.mk b/firmware/lib/fx2.mk index bb0c78d..df97538 100644 --- a/firmware/lib/fx2.mk +++ b/firmware/lib/fx2.mk @@ -87,8 +87,9 @@ load: $(BUILDDIR)/$(BASENAME).bix #fxload -vvv -t fx2 -D /dev/bus/usb/002/003 -I $(BUILDDIR)/$(BASENAME).bix #fxload -vvv -t fx2 -D /dev/bus/usb/002/003 -I build/firmware.ihx +#*.{asm,ihx,lnk,lst,map,mem,rel,rst,sym,adb,cdb,bix} clean: - rm -f $(BUILDDIR)/*.{asm,ihx,lnk,lst,map,mem,rel,rst,sym,adb,cdb,bix} + rm -rf $(BUILDDIR)/ clean-all: clean $(MAKE) -C $(FX2LIBDIR)/lib clean