///////////////////////////////////////////////////////////////////////////// //! Sends the System Reset SPI command to the Ethernet controller. //! It resets all register contents (except for ECOCON) and returns the //! device to the power on default state. //! //! \return < 0 on errors ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_ENC28J60_SendSystemReset(void) { s32 status = 0; #if 0 // sequence taken from SendSystemReset() of Microchip driver // Note: The power save feature may prevent the reset from executing, so // we must make sure that the device is not in power save before issuing // a reset. if( (status=MIOS32_ENC28J60_BFCReg(ECON2, ECON2_PWRSV)) < 0 ) return status; // Give some opportunity for the regulator to reach normal regulation and // have all clocks running MIOS32_DELAY_Wait_uS(1000); // 1 mS #endif // Execute the System Reset command status = 0; CSN_0; status |= MIOS32_SPI_TransferByte(MIOS32_ENC28J60_SPI, SR); CSN_1; if( status < 0 ) return status; // Wait for the oscillator start up timer and PHY to become ready MIOS32_DELAY_Wait_uS(1000); // 1 mS return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Initializes application specific LCD driver // IN: <mode>: optional configuration // OUT: returns < 0 if initialisation failed ///////////////////////////////////////////////////////////////////////////// s32 APP_LCD_Init(u32 mode) { // currently only mode 0 supported if( mode != 0 ) return -1; // unsupported mode if( MIOS32_BOARD_J15_PortInit(APP_LCD_OUTPUT_MODE) < 0 ) return -2; // failed to initialize J15 // enable display by default display_available |= (1 << mios32_lcd_device); // set LCD type mios32_lcd_parameters.lcd_type = MIOS32_LCD_TYPE_GLCD_CUSTOM; mios32_lcd_parameters.num_x = APP_LCD_NUM_X; mios32_lcd_parameters.width = APP_LCD_WIDTH; mios32_lcd_parameters.num_x = APP_LCD_NUM_Y; mios32_lcd_parameters.height = APP_LCD_HEIGHT; mios32_lcd_parameters.colour_depth = APP_LCD_COLOUR_DEPTH; // initialize LCD #ifdef MIOS32_DONT_USE_DELAY u32 delay; for(delay=0; delay<50000; ++delay) MIOS32_BOARD_J15_RW_Set(0); // ca. 50 mS Delay #else MIOS32_DELAY_Wait_uS(50000); // exact 50 mS delay #endif APP_LCD_Cmd(0xf1); APP_LCD_Cmd(0x67); APP_LCD_Cmd(0xc0); APP_LCD_Cmd(0x40); APP_LCD_Cmd(0x50); APP_LCD_Cmd(0x2b); APP_LCD_Cmd(0xeb); APP_LCD_Cmd(0x81); APP_LCD_Cmd(0x58); // contrast(0x00-0xff Default 0x5f APP_LCD_Cmd(0x89); //APP_LCD_Cmd(0xd0); //Greyscale control APP_LCD_Cmd(0xaf); return (display_available & (1 << mios32_lcd_device)) ? 0 : -1; // return -1 if display not available }
///////////////////////////////////////////////////////////////////////////// //! Initializes LCD driver //! \param[in] mode currently only mode 0 supported //! \return < 0 if initialisation failed ///////////////////////////////////////////////////////////////////////////// s32 MIOS32_LCD_Init(u32 mode) { s32 ret; // currently only mode 0 supported if( mode != 0 ) return -1; // unsupported mode // fetch config from BSL info range MIOS32_LCD_ParametersFetchFromBslInfoRange(); // disable font bitmap font_bitmap.width = 0; // set initial cursor map for character LCDs u8 cursor_map[] = {0x00, 0x40, 0x14, 0x54}; // offset line 0/1/2/3 MIOS32_LCD_CursorMapSet(cursor_map); // note: this has to be done before APP_LCD_Init() is called, so that // the driver is able to modify the default cursor mapping // usage example: "dog" LCDs #if !defined(MIOS32_FAMILY_EMULATION) // initial delay - some LCDs need this! MIOS32_DELAY_Wait_uS(50000); #endif // call application specific init function if( (ret=APP_LCD_Init(mode)) < 0 ) return ret; // clear screen MIOS32_LCD_Clear(); // set character and graphical cursor to initial position MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_GCursorSet(0, 0); return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { int num_lcds = mios32_lcd_parameters.num_x * mios32_lcd_parameters.num_y; // print configured LCD parameters MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("Multi-CLCD Demo started."); MIOS32_MIDI_SendDebugMessage("Configured LCD Parameters in MIOS32 Bootloader Info Range:\n"); MIOS32_MIDI_SendDebugMessage("lcd_type: 0x%02x (%s)\n", mios32_lcd_parameters.lcd_type, MIOS32_LCD_LcdTypeName(mios32_lcd_parameters.lcd_type)); MIOS32_MIDI_SendDebugMessage("num_x: %4d\n", mios32_lcd_parameters.num_x); MIOS32_MIDI_SendDebugMessage("num_y: %4d\n", mios32_lcd_parameters.num_y); MIOS32_MIDI_SendDebugMessage("width: %4d\n", mios32_lcd_parameters.width); MIOS32_MIDI_SendDebugMessage("height: %4d\n", mios32_lcd_parameters.height); if( mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_CLCD && mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_CLCD_DOG ) { // print warning if correct LCD hasn't been selected MIOS32_MIDI_SendDebugMessage("WARNING: your core module hasn't been configured for CLCD or CLCD_DOG!\n"); MIOS32_MIDI_SendDebugMessage("Please do this with the bootloader update application!\n"); } // initialize all LCDs (although programming_models/traditional/main.c will only initialize the first two) int lcd; for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_MIDI_SendDebugMessage("Initialize LCD #%d\n", lcd+1); MIOS32_LCD_DeviceSet(lcd); if( MIOS32_LCD_Init(0) < 0 ) { MIOS32_MIDI_SendDebugMessage("Failed - no response from LCD #%d.%d\n", (lcd % mios32_lcd_parameters.num_x) + 1, (lcd / mios32_lcd_parameters.num_x) + 1); } } // init special characters for all LCDs for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_LCD_DeviceSet(lcd); MIOS32_LCD_SpecialCharsInit((u8 *)charset_vert_bars); MIOS32_LCD_Clear(); } // print text on all LCDs for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_LCD_DeviceSet(lcd); MIOS32_LCD_CursorSet(0, 0); MIOS32_LCD_PrintFormattedString("LCD #%d.%d", (lcd % mios32_lcd_parameters.num_x) + 1, (lcd / mios32_lcd_parameters.num_x) + 1); MIOS32_LCD_CursorSet(0, 1); MIOS32_LCD_PrintFormattedString("READY."); } // print animated vertical bar while( 1 ) { int i, j; for(i=0; i<8; ++i) { // print vertical bars depending on i for(lcd=0; lcd<num_lcds; ++lcd) { MIOS32_LCD_DeviceSet(lcd); MIOS32_LCD_CursorSet(12, 0); for(j=0; j<8; ++j) { u8 c = (i + j) % 8; MIOS32_LCD_PrintChar(c); } } // wait for 100 mS for(j=0; j<100; ++j) MIOS32_DELAY_Wait_uS(1000); } } }
///////////////////////////////////////////////////////////////////////////// //! Parser for a complete line - also used by shell.c for telnet ///////////////////////////////////////////////////////////////////////////// s32 TERMINAL_ParseLine(char *input, void *_output_function) { void (*out)(char *format, ...) = _output_function; char *separators = " \t"; char *brkt; char *parameter; if( UIP_TERMINAL_ParseLine(input, _output_function) > 0 ) return 0; // command parsed by UIP Terminal if( KEYBOARD_TerminalParseLine(input, _output_function) > 0 ) return 0; // command parsed by Keyboard Terminal if( MIDIMON_TerminalParseLine(input, _output_function) > 0 ) return 0; // command parsed if( MIDI_ROUTER_TerminalParseLine(input, _output_function) > 0 ) return 0; // command parsed #if !defined(MIOS32_FAMILY_EMULATION) if( AOUT_TerminalParseLine(input, _output_function) >= 1 ) return 0; // command parsed #endif #ifdef MIOS32_LCD_universal if( APP_LCD_TerminalParseLine(input, _output_function) >= 1 ) return 0; // command parsed #endif if( (parameter = strtok_r(input, separators, &brkt)) ) { if( strcmp(parameter, "help") == 0 ) { out("Welcome to " MIOS32_LCD_BOOT_MSG_LINE1 "!"); out("Following commands are available:"); out(" system: print system info"); out(" memory: print memory allocation info\n"); out(" sdcard: print SD Card info\n"); out(" sdcard_format: formats the SD Card (you will be asked for confirmation)\n"); UIP_TERMINAL_Help(_output_function); KEYBOARD_TerminalHelp(_output_function); MIDIMON_TerminalHelp(_output_function); MIDI_ROUTER_TerminalHelp(_output_function); AOUT_TerminalHelp(_output_function); #ifdef MIOS32_LCD_universal APP_LCD_TerminalHelp(_output_function); #endif out(" set dout <pin> <0|1>: directly sets DOUT (all or 0..%d) to given level (1 or 0)", MIOS32_SRIO_NUM_SR*8 - 1); out(" show douts: prints the current DOUT patterns"); out(" set debug <on|off>: enables debug messages (current: %s)", debug_verbose_level ? "on" : "off"); out(" set autoload <on|off>: enables autoload after filebrowser upload (current: %s)", autoload_enabled ? "on" : "off"); out(" save <name>: stores current config on SD Card"); out(" load <name>: restores config from SD Card"); out(" show file: shows the current configuration file"); out(" show pool: shows the items of the event pool"); out(" show poolbin: shows the event pool in binary format"); out(" show id <element>:<id> shows informations about the given element id (e.g. BUTTON:1)"); out(" show hw_id <element>:<hw_id> shows informations about the given element hw_id (e.g. BUTTON:1)"); out(" show ngr_tokens: shows .NGR token information"); out(" lcd <string>: directly prints a string on LCD (can be formatted!)"); out(" run [<section>] [<value>]: executes the .NGR script with the optional section and value"); out(" ngr_value: value used for 'run' (without parameter) and 'ngr' (is: %d)", ngr_value); out(" ngr_section: section used for 'run' (without parameter) and 'ngr' (is: %d)", ngr_section); out(" ngr <command>: directly executes a NGR command"); out(" ngc <command>: directly executes a NGC command"); out(" msd <on|off>: enables Mass Storage Device driver"); out(" reset: resets the MIDIbox (!)\n"); out(" help: this page"); out(" exit: (telnet only) exits the terminal"); } else if( strcmp(parameter, "system") == 0 ) { TERMINAL_PrintSystem(_output_function); } else if( strcmp(parameter, "memory") == 0 ) { TERMINAL_PrintMemoryInfo(out); } else if( strcmp(parameter, "sdcard") == 0 ) { TERMINAL_PrintSdCardInfo(out); } else if( strcmp(parameter, "sdcard_format") == 0 ) { if( !brkt || strcasecmp(brkt, "yes, I'm sure") != 0 ) { out("ATTENTION: this command will format your SD Card!!!"); out(" ALL DATA WILL BE DELETED FOREVER!!!"); out(" Check the current content with the 'sdcard' command"); out(" Create a backup on your computer if necessary!"); out("To start formatting, please enter: sdcard_format yes, I'm sure"); if( brkt ) { out("('%s' wasn't the right \"password\")", brkt); } } else { MUTEX_SDCARD_TAKE; out("Formatting SD Card..."); FRESULT res; if( (res=f_mkfs(0,0,0)) != FR_OK ) { out("Formatting failed with error code: %d!", res); } else { out("...with success!"); MBNG_FILE_UnloadAllFiles(); MBNG_FILE_CreateDefaultFiles(); } MUTEX_SDCARD_GIVE; } } else if( strcmp(parameter, "msd") == 0 ) { char *arg = NULL; if( (arg = strtok_r(NULL, separators, &brkt)) ) { if( strcmp(arg, "on") == 0 ) { if( TASK_MSD_EnableGet() ) { out("Mass Storage Device Mode already activated!\n"); } else { out("Mass Storage Device Mode activated - USB MIDI will be disabled!!!\n"); // wait a second to ensure that this message is print in MIOS Terminal int d; for(d=0; d<1000; ++d) MIOS32_DELAY_Wait_uS(1000); // activate MSD mode TASK_MSD_EnableSet(1); } } else if( strcmp(arg, "off") == 0 ) { if( !TASK_MSD_EnableGet() ) { out("Mass Storage Device Mode already deactivated!\n"); } else { out("Mass Storage Device Mode deactivated - USB MIDI will be available again\n"); TASK_MSD_EnableSet(0); } } else arg = NULL; } if( arg == NULL ) { out("Please enter 'msd on' or 'msd off'\n"); } } else if( strcmp(parameter, "lcd") == 0 ) { if( !brkt || !strlen(brkt) ) { out("Please specify string (can be optionally formatted)"); } else { out("Print '%s'", brkt); MUTEX_LCD_TAKE; // print from a dummy item mbng_event_item_t item; MBNG_EVENT_ItemInit(&item, MBNG_EVENT_CONTROLLER_DISABLED); item.label = brkt; MBNG_LCD_PrintItemLabel(&item, NULL, 0); MUTEX_LCD_GIVE; } } else if( strcmp(parameter, "run") == 0 ) { s32 section, value; if( (parameter = strtok_r(NULL, separators, &brkt)) ) { if( (section=get_dec(parameter)) < 0 || section >= 256 ) { out("Section number should be between 0..255!"); } else { ngr_section = section; } if( (parameter = strtok_r(NULL, separators, &brkt)) ) { if( (value=get_dec(parameter)) < -16384 || value >= 16383 ) { out("Value should be between -16384..16383!"); } else { ngr_value = value; } } } if( !MBNG_FILE_R_Valid() ) { out("ERROR: can't execute - missing %s.NGR file!", mbng_file_r_script_name); } else { out("Executing %s.NGR with ^section==%d ^value==%d", mbng_file_r_script_name, ngr_section, ngr_value); MBNG_FILE_R_ReadRequest(NULL, ngr_section, ngr_value, 1); } } else if( strcmp(parameter, "runstop") == 0 ) { if( MBNG_FILE_R_RunStop() > 0 ) { out("Stopped the execution of %s.NGR", mbng_file_r_script_name); } else { out("%s.NGR script not running.", mbng_file_r_script_name); } } else if( strcasecmp(parameter, "ngr_section") == 0 ) { s32 section; if( !(parameter = strtok_r(NULL, separators, &brkt)) ) { out("Please specify <ngr-section>! Current value: %d", ngr_section); } else if( (section=get_dec(parameter)) < 0 || section >= 256 ) { out("Section number should be between 0..255!"); } else { ngr_section = section; out(".NGR section set to %d", ngr_section); } } else if( strcasecmp(parameter, "ngr_value") == 0 ) { s32 value; if( !(parameter = strtok_r(NULL, separators, &brkt)) ) { out("Please specify <ngr-value>! Current value: %d", ngr_value); } else if( (value=get_dec(parameter)) < -16384 || value >= 16383 ) { out("Value should be between -16384..16383!"); } else { ngr_value = value; out(".NGR value set to %d", ngr_value); } } else if( strcasecmp(parameter, "ngr") == 0 ) { if( brkt == NULL ) { out("Please specify command!"); } else { char load_filename[9]; load_filename[0] = 0; MBNG_FILE_R_VarSectionSet(ngr_section); MBNG_FILE_R_VarValueSet(ngr_value); MBNG_FILE_R_Parser(0, brkt, NULL, NULL, load_filename, 0); out("Executed command with ^section==%d ^value==%d", ngr_section, ngr_value); if( load_filename[0] ) { s32 status = MBNG_PATCH_Load(parameter); if( status < 0 ) { out("ERROR: failed to load patch '%s' on SD Card (status %d)!", parameter, status); } } } } else if( strcasecmp(parameter, "ngc") == 0 ) { if( brkt == NULL ) { out("Please specify command!"); } else { u8 got_first_event_item = 0; MBNG_FILE_C_Parser(0, brkt, &got_first_event_item); out("Executed command."); } } else if( strcmp(parameter, "save") == 0 ) { if( !(parameter = strtok_r(NULL, separators, &brkt)) ) { out("ERROR: please specify filename for patch (up to 8 characters)!"); } else { if( strlen(parameter) > 8 ) { out("ERROR: 8 characters maximum!"); } else { s32 status = MBNG_PATCH_Store(parameter); if( status >= 0 ) { out("Patch '%s' stored on SD Card!", parameter); } else { out("ERROR: failed to store patch '%s' on SD Card (status %d)!", parameter, status); } } } } else if( strcmp(parameter, "load") == 0 ) { if( !(parameter = strtok_r(NULL, separators, &brkt)) ) { out("ERROR: please specify filename for patch (up to 8 characters)!"); } else { if( strlen(parameter) > 8 ) { out("ERROR: 8 characters maximum!"); } else { s32 status = MBNG_PATCH_Load(parameter); if( status >= 0 ) { out("Patch '%s' loaded from SD Card!", parameter); } else { out("ERROR: failed to load patch '%s' on SD Card (status %d)!", parameter, status); } } } } else if( strcmp(parameter, "show") == 0 ) { if( !(parameter = strtok_r(NULL, separators, &brkt)) ) { out("ERROR: please specify the item which should be displayed!"); } else { if( strcmp(parameter, "file") == 0 ) { MBNG_FILE_C_Debug(); } else if( strcmp(parameter, "douts") == 0 ) { int page; for(page=0; page<MIOS32_SRIO_NUM_DOUT_PAGES; ++page) { char buffer[3*MIOS32_SRIO_NUM_SR + 20]; sprintf(buffer, "Page %2d:", page+0); int i; for(i=0; i<MIOS32_SRIO_NUM_SR; ++i) { sprintf((char *)&buffer[8+i*3], " %02x", mios32_srio_dout[page][MIOS32_SRIO_NUM_SR-i-1]); } MIOS32_MIDI_SendDebugString(buffer); } } else if( strcmp(parameter, "ngr_tokens") == 0 || strcmp(parameter, "ngrtokens") == 0 ) { MBNG_FILE_R_TokenMemPrint(); } else if( strcmp(parameter, "poolbin") == 0 ) { MBNG_EVENT_PoolPrint(); } else if( strcmp(parameter, "pool") == 0 ) { MBNG_EVENT_PoolItemsPrint(); MBNG_EVENT_PoolMapsPrint(); } else if( strcmp(parameter, "id") == 0 || strcmp(parameter, "hw_id") == 0 ) { u8 search_hw_id = strcmp(parameter, "hw_id") == 0; const char *separator_colon = ":"; char *id_str = brkt; if( id_str == NULL || !strlen(id_str) ) { out("Please specify <element>:<id> (e.g. LED:1)!"); } else { char *values_str; mbng_event_item_id_t id; if( !(values_str = strtok_r(NULL, separator_colon, &brkt)) || (id=MBNG_EVENT_ItemIdFromControllerStrGet(values_str)) == MBNG_EVENT_CONTROLLER_DISABLED ) { out("Invalid element name '%s'!", id_str); } else { char *id_lower_str = brkt; int id_lower = 0; if( !(values_str = strtok_r(NULL, separator_colon, &brkt)) || (id_lower=get_dec(values_str)) < 1 || id_lower > 0xfff ) { out("Invalid element %s '%s:%s' (expecting %s:1 .. %s:4095)!", search_hw_id ? "hw_id" : "id", id_str, id_lower_str, id_str, id_str); } else { id = id | id_lower; if( search_hw_id ) { u8 num = MBNG_EVENT_ItemSearchByHwIdAndPrint(id); if( num < 1 ) { out("No items found which are assigned to this hw_id!"); } } else { u8 num = MBNG_EVENT_ItemSearchByIdAndPrint(id); if( num < 1 ) { out("No items found which are assigned to this id!"); } } } } } } else { out("ERROR: invalid item which should be showed - see 'show pool' for available items!"); } } } else if( strcmp(parameter, "reset") == 0 ) { MIOS32_SYS_Reset(); } else if( strcmp(parameter, "set") == 0 ) { if( (parameter = strtok_r(NULL, separators, &brkt)) ) { if( strcmp(parameter, "dout") == 0 ) { s32 pin = -1; if( (parameter = strtok_r(NULL, separators, &brkt)) ) { if( strcmp(parameter, "all") == 0 ) { pin = -42; } else { pin = get_dec(parameter); } } if( (pin < 0 && pin != -42) || pin >= (MIOS32_SRIO_NUM_SR*8) ) { out("Pin number should be between 0..%d", MIOS32_SRIO_NUM_SR*8 - 1); } else { s32 value = -1; if( (parameter = strtok_r(NULL, separators, &brkt)) ) value = get_dec(parameter); if( value < 0 || value > 1 ) { out("Expecting value 1 or 0 for DOUT pin %d", pin); } else { if( pin == -42 ) { for(pin=0; pin<(MIOS32_SRIO_NUM_SR*8); ++pin) MIOS32_DOUT_PinSet(pin, value); out("All DOUT pins set to %d", value); } else { MIOS32_DOUT_PinSet(pin, value); out("DOUT Pin %d (SR#%d.D%d) set to %d", pin, (pin/8)+1, 7-(pin%8), value); } } } } else if( strcmp(parameter, "debug") == 0 ) { int on_off = -1; if( (parameter = strtok_r(NULL, separators, &brkt)) ) on_off = get_on_off(parameter); if( on_off < 0 ) { out("Expecting 'on' or 'off'"); } else { debug_verbose_level = on_off ? DEBUG_VERBOSE_LEVEL_INFO : DEBUG_VERBOSE_LEVEL_ERROR; out("Debug mode turned %s", on_off ? "on" : "off"); } } else if( strcmp(parameter, "autoload") == 0 ) { int on_off = -1; if( (parameter = strtok_r(NULL, separators, &brkt)) ) on_off = get_on_off(parameter); if( on_off < 0 ) { out("Expecting 'on' or 'off'"); } else { autoload_enabled = on_off; out("Autoload of .NGC file after filebrowser upload %s", on_off ? "on" : "off"); } } else { out("Unknown set parameter: '%s'!", parameter); } } else { out("Missing parameter after 'set'!"); } } else { out("Unknown command - type 'help' to list available commands!"); } } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // Parser for a complete line - also used by shell.c for telnet ///////////////////////////////////////////////////////////////////////////// s32 TERMINAL_ParseLine(char *input, void *_output_function) { void (*out)(char *format, ...) = _output_function; char *separators = " \t"; char *brkt; char *parameter; if( UIP_TERMINAL_ParseLine(input, _output_function) > 0 ) return 0; // command parsed by UIP Terminal if( MIDIMON_TerminalParseLine(input, _output_function) > 0 ) return 0; // command parsed if( MIDI_ROUTER_TerminalParseLine(input, _output_function) > 0 ) return 0; // command parsed if( AOUT_TerminalParseLine(input, _output_function) > 0 ) return 0; // command parsed #ifdef MIOS32_LCD_universal if( APP_LCD_TerminalParseLine(input, _output_function) >= 1 ) return 0; // command parsed #endif if( (parameter = strtok_r(input, separators, &brkt)) ) { if( strcmp(parameter, "help") == 0 ) { out("Welcome to " MIOS32_LCD_BOOT_MSG_LINE1 "!"); out("Following commands are available:"); out(" system: print system info"); out(" memory: print memory allocation info\n"); out(" sdcard: print SD Card info\n"); out(" sdcard_format: formats the SD Card (you will be asked for confirmation)\n"); UIP_TERMINAL_Help(_output_function); MIDIMON_TerminalHelp(_output_function); MIDI_ROUTER_TerminalHelp(_output_function); out(" set dout <pin> <0|1>: directly sets DOUT (all or 0..%d) to given level (1 or 0)", MIOS32_SRIO_NUM_SR*8 - 1); out(" set update_rate <1..%d>: sets update rate of sound engine (factor*500 Hz), current: %d\n", APP_CV_UPDATE_RATE_FACTOR_MAX, APP_CvUpdateRateFactorGet()); AOUT_TerminalHelp(_output_function); #ifdef MIOS32_LCD_universal APP_LCD_TerminalHelp(_output_function); #endif out(" save <name>: stores current config on SD Card"); out(" load <name>: restores config from SD Card"); out(" show: shows the current configuration file"); out(" nrpn: shows the current NRPN parameters"); out(" msd <on|off>: enables Mass Storage Device driver"); out(" reset: resets the MIDIbox (!)\n"); out(" help: this page"); out(" exit: (telnet only) exits the terminal"); } else if( strcmp(parameter, "system") == 0 ) { TERMINAL_PrintSystem(_output_function); } else if( strcmp(parameter, "memory") == 0 ) { TERMINAL_PrintMemoryInfo(out); } else if( strcmp(parameter, "sdcard") == 0 ) { TERMINAL_PrintSdCardInfo(out); } else if( strcmp(parameter, "sdcard_format") == 0 ) { if( !brkt || strcasecmp(brkt, "yes, I'm sure") != 0 ) { out("ATTENTION: this command will format your SD Card!!!"); out(" ALL DATA WILL BE DELETED FOREVER!!!"); out(" Check the current content with the 'sdcard' command"); out(" Create a backup on your computer if necessary!"); out("To start formatting, please enter: sdcard_format yes, I'm sure"); if( brkt ) { out("('%s' wasn't the right \"password\")", brkt); } } else { MUTEX_SDCARD_TAKE; out("Formatting SD Card..."); FRESULT res; if( (res=f_mkfs(0,0,0)) != FR_OK ) { out("Formatting failed with error code: %d!", res); } else { out("...with success!"); MBCV_FILE_UnloadAllFiles(); MBCV_FILE_CreateDefaultFiles(); } MUTEX_SDCARD_GIVE; } } else if( strcmp(parameter, "msd") == 0 ) { char *arg = NULL; if( (arg = strtok_r(NULL, separators, &brkt)) ) { if( strcmp(arg, "on") == 0 ) { if( TASK_MSD_EnableGet() ) { out("Mass Storage Device Mode already activated!\n"); } else { out("Mass Storage Device Mode activated - USB MIDI will be disabled!!!\n"); // wait a second to ensure that this message is print in MIOS Terminal int d; for(d=0; d<1000; ++d) MIOS32_DELAY_Wait_uS(1000); // activate MSD mode TASK_MSD_EnableSet(1); } } else if( strcmp(arg, "off") == 0 ) { if( !TASK_MSD_EnableGet() ) { out("Mass Storage Device Mode already deactivated!\n"); } else { out("Mass Storage Device Mode deactivated - USB MIDI will be available again.n"); TASK_MSD_EnableSet(0); } } else arg = NULL; } if( arg == NULL ) { out("Please enter 'msd on' or 'msd off'\n"); } } else if( strcmp(parameter, "save") == 0 ) { if( !(parameter = strtok_r(NULL, separators, &brkt)) ) { out("ERROR: please specify filename for patch (up to 8 characters)!"); } else { if( strlen(parameter) > 8 ) { out("ERROR: 8 characters maximum!"); } else { s32 status = MBCV_PATCH_StoreGlobal(parameter); if( status >= 0 ) { out("Patch '%s' stored on SD Card!", parameter); } else { out("ERROR: failed to store patch '%s' on SD Card (status %d)!", parameter, status); } } } } else if( strcmp(parameter, "load") == 0 ) { if( !(parameter = strtok_r(NULL, separators, &brkt)) ) { out("ERROR: please specify filename for patch (up to 8 characters)!"); } else { if( strlen(parameter) > 8 ) { out("ERROR: 8 characters maximum!"); } else { s32 status = MBCV_PATCH_LoadGlobal(parameter); if( status >= 0 ) { out("Patch '%s' loaded from SD Card!", parameter); } else { out("ERROR: failed to load patch '%s' on SD Card (status %d)!", parameter, status); } } } } else if( strcmp(parameter, "show") == 0 ) { MBCV_FILE_P_Debug(); } else if( strcmp(parameter, "nrpn") == 0 || strcmp(parameter, "nrpns") == 0 ) { TERMINAL_ShowNrpns(out); } else if( strcmp(parameter, "reset") == 0 ) { MIOS32_SYS_Reset(); } else if( strcmp(parameter, "set") == 0 ) { if( (parameter = strtok_r(NULL, separators, &brkt)) ) { if( strcmp(parameter, "dout") == 0 ) { s32 pin = -1; if( (parameter = strtok_r(NULL, separators, &brkt)) ) { if( strcmp(parameter, "all") == 0 ) { pin = -42; } else { pin = get_dec(parameter); } } if( (pin < 0 && pin != -42) || pin >= (MIOS32_SRIO_NUM_SR*8) ) { out("Pin number should be between 0..%d", MIOS32_SRIO_NUM_SR*8 - 1); } else { s32 value = -1; if( (parameter = strtok_r(NULL, separators, &brkt)) ) value = get_dec(parameter); if( value < 0 || value > 1 ) { out("Expecting value 1 or 0 for DOUT pin %d", pin); } else { if( pin == -42 ) { for(pin=0; pin<(MIOS32_SRIO_NUM_SR*8); ++pin) MIOS32_DOUT_PinSet(pin, value); out("All DOUT pins set to %d", value); } else { MIOS32_DOUT_PinSet(pin, value); out("DOUT Pin %d (SR#%d.D%d) set to %d", pin, (pin/8)+1, 7-(pin%8), value); } } } } else if( strcmp(parameter, "update_rate") == 0 ) { s32 factor = -1; if( (parameter = strtok_r(NULL, separators, &brkt)) ) { factor = get_dec(parameter); } if( (factor < 1 || factor > APP_CV_UPDATE_RATE_FACTOR_MAX) ) { out("Update Rate should be between 1..%d!", APP_CV_UPDATE_RATE_FACTOR_MAX); } else { APP_CvUpdateRateFactorSet(factor); out("Update Rate set to %d Hz (factor %d)", 500*APP_CvUpdateRateFactorGet(), APP_CvUpdateRateFactorGet()); } } else { out("Unknown set parameter: '%s'!", parameter); } } else { out("Missing parameter after 'set'!"); } } else { out("Unknown command - type 'help' to list available commands!"); } } return 0; // no error }
///////////////////////////////////////////////////////////////////////////// // This task is running endless in background ///////////////////////////////////////////////////////////////////////////// void APP_Background(void) { #define MAX_LCDS 16 int num_lcds = mios32_lcd_parameters.num_x * mios32_lcd_parameters.num_y; if( num_lcds > MAX_LCDS ) { MIOS32_MIDI_SendDebugMessage("WARNING: this application only supports up to 16 displays!\n"); num_lcds = MAX_LCDS; } // clear LCDs { u8 n; for(n=0; n<num_lcds; ++n) { MIOS32_LCD_DeviceSet(n); MIOS32_LCD_Clear(); } } u8 vmeter_icon_ctr[MAX_LCDS][2] = {{0,5},{3,14},{7,1},{3,9},{13,6},{10,2},{1,4},{6,2},{13,6},{10,2},{1,4},{6,2},{1,2},{13,14},{5,5},{6,1}}; // memo: 28 icons (14 used) u8 vmeter_icon_dir[MAX_LCDS][2] = {{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1},{1,1}}; u8 vmeter_icon_delay_ctr[MAX_LCDS][2] = {{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4},{1,4}}; const u8 vmeter_icon_x[2] = {0, 120}; // memo: icon width 8 const u8 vmeter_icon_y[2] = {12, 12}; // memo: icon height 32 u8 hmeter_icon_ctr[MAX_LCDS][2] = {{6,11},{2,27},{23,1},{15,6},{18,9},{10,12},{3,25},{26,7},{18,9},{10,12},{3,25},{26,7},{6,9},{18,18},{20,10},{3,10}}; // memo: 28 icons (14 used) u8 hmeter_icon_dir[MAX_LCDS][2] = {{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0},{1,0}}; u8 hmeter_icon_delay_ctr[MAX_LCDS][2] = {{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2},{4,2}}; const u8 hmeter_icon_x[2] = {20, 80}; // memo: icon width 28 const u8 hmeter_icon_y[2] = {60, 60}; // memo: icon height 8 // print configured LCD parameters MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("\n"); MIOS32_MIDI_SendDebugMessage("SSD1306 Demo started."); MIOS32_MIDI_SendDebugMessage("Configured LCD Parameters in MIOS32 Bootloader Info Range:\n"); MIOS32_MIDI_SendDebugMessage("lcd_type: 0x%02x (%s)\n", mios32_lcd_parameters.lcd_type, MIOS32_LCD_LcdTypeName(mios32_lcd_parameters.lcd_type)); MIOS32_MIDI_SendDebugMessage("num_x: %4d\n", mios32_lcd_parameters.num_x); MIOS32_MIDI_SendDebugMessage("num_y: %4d\n", mios32_lcd_parameters.num_y); MIOS32_MIDI_SendDebugMessage("width: %4d\n", mios32_lcd_parameters.width); MIOS32_MIDI_SendDebugMessage("height: %4d\n", mios32_lcd_parameters.height); MIOS32_MIDI_SendDebugMessage("Testing %d LCDs\n", num_lcds); if( mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_GLCD_SSD1306 && mios32_lcd_parameters.lcd_type != MIOS32_LCD_TYPE_GLCD_SSD1306_ROTATED ) { // print warning if correct LCD hasn't been selected MIOS32_MIDI_SendDebugMessage("WARNING: your core module hasn't been configured for the SSD1306 GLCD!\n"); MIOS32_MIDI_SendDebugMessage("Please do this with the bootloader update application!\n"); } // print static screen MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); // endless loop - LED will flicker on each iteration while( 1 ) { // wait some mS MIOS32_DELAY_Wait_uS(10000); // toggle the state of all LEDs (allows to measure the execution speed with a scope) MIOS32_BOARD_LED_Set(0xffffffff, ~MIOS32_BOARD_LED_Get()); u8 n; for(n=0; n<num_lcds; ++n) { int i; #if 0 // X/Y "position" of displays const u8 lcd_x[MAX_LCDS] = {0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}; // CS#0..7 const u8 lcd_y[MAX_LCDS] = {0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7}; // X/Y "position" of displays u8 x_offset = 128*lcd_x[n]; u8 y_offset = 64*lcd_y[n]; #else // TK: expired! LCDs now addressed via MIOS32_LCD_DeviceSet() u8 x_offset = 0; u8 y_offset = 0; MIOS32_LCD_DeviceSet(n); #endif // print text MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); MIOS32_LCD_GCursorSet(x_offset + 6*6, y_offset + 1*8); MIOS32_LCD_PrintFormattedString("SSD1306 #%d", n+1); MIOS32_LCD_GCursorSet(x_offset + 6*6, y_offset + 2*8); MIOS32_LCD_PrintString("powered by "); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_BIG); MIOS32_LCD_GCursorSet(x_offset + 3*6, y_offset + 3*8); MIOS32_LCD_PrintString("MIOS32"); // print vmeter icons MIOS32_LCD_FontInit((u8 *)GLCD_FONT_METER_ICONS_V); // memo: 28 icons, 14 used, icon size: 8x32 for(i=0; i<2; ++i) { if( ++vmeter_icon_delay_ctr[n][i] ) { vmeter_icon_delay_ctr[n][i] = 0; if( vmeter_icon_dir[n][i] ) { if( ++vmeter_icon_ctr[n][i] >= 13 ) vmeter_icon_dir[n][i] = 0; } else { if( --vmeter_icon_ctr[n][i] < 1 ) vmeter_icon_dir[n][i] = 1; } } MIOS32_LCD_GCursorSet(vmeter_icon_x[i]+x_offset, vmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintChar(vmeter_icon_ctr[n][i]); } // print hmeter icons for(i=0; i<2; ++i) { MIOS32_LCD_FontInit((u8 *)GLCD_FONT_METER_ICONS_H); // memo: 28 icons, 14 used, icon size: 28x8 if( ++hmeter_icon_delay_ctr[n][i] > 7 ) { hmeter_icon_delay_ctr[n][i] = 0; if( hmeter_icon_dir[n][i] ) { if( ++hmeter_icon_ctr[n][i] >= 13 ) hmeter_icon_dir[n][i] = 0; } else { if( --hmeter_icon_ctr[n][i] < 1 ) hmeter_icon_dir[n][i] = 1; } } MIOS32_LCD_GCursorSet(hmeter_icon_x[i]+x_offset, hmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintChar(hmeter_icon_ctr[n][i]); MIOS32_LCD_FontInit((u8 *)GLCD_FONT_NORMAL); if( i == 0 ) { MIOS32_LCD_GCursorSet(0+x_offset, hmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintFormattedString("%d", hmeter_icon_ctr[n][i]*4); } else { MIOS32_LCD_GCursorSet(128-3*6+x_offset, hmeter_icon_y[i]+y_offset); MIOS32_LCD_PrintFormattedString("%3d", hmeter_icon_ctr[n][i]*4); } } } } }
///////////////////////////////////////////////////////////////////////////// // This hook is called when a MIDI package has been received ///////////////////////////////////////////////////////////////////////////// void APP_MIDI_NotifyPackage(mios32_midi_port_t port, mios32_midi_package_t midi_package) { if( midi_package.type == NoteOn && midi_package.velocity > 0 ) { // determine test number (use note number, remove octave) u8 test_number = midi_package.note % 12; // set the tested port and RS optimisation switch( test_number ) { case 0: tested_port = USB0; MIOS32_MIDI_RS_OptimisationSet(tested_port, 0); MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (USB0) with RS disabled\n", tested_port); break; case 1: tested_port = USB0; MIOS32_MIDI_RS_OptimisationSet(tested_port, 1); MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (USB0) with RS enabled\n", tested_port); break; case 2: tested_port = UART0; MIOS32_MIDI_RS_OptimisationSet(tested_port, 0); MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (UART0) with RS disabled\n", tested_port); break; case 3: tested_port = UART0; MIOS32_MIDI_RS_OptimisationSet(tested_port, 1); MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (UART0) with RS enabled\n", tested_port); break; case 4: tested_port = IIC0; MIOS32_MIDI_RS_OptimisationSet(tested_port, 0); MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (IIC0) with RS disabled\n", tested_port); break; case 5: tested_port = IIC0; MIOS32_MIDI_RS_OptimisationSet(tested_port, 1); MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (IIC0) with RS enabled\n", tested_port); break; case 6: tested_port = 0xf0; // forwarded to OSC, see NOTIFY_MIDI_Tx() MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (OSC), one datagram per event\n", tested_port); break; case 7: tested_port = 0xf1; // forwarded to OSC, see NOTIFY_MIDI_Tx() MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (OSC), 8 events bundled in a datagram\n", tested_port); break; case 8: tested_port = SPIM0; MIOS32_MIDI_SendDebugMessage("Testing Port 0x%02x (SPI0)\n", tested_port); break; default: MIOS32_MIDI_SendDebugMessage("This note isn't mapped to a test function.\n", tested_port); return; } // add some delay to ensure that there a no USB background traffic caused by the debug message MIOS32_DELAY_Wait_uS(50000); // reset benchmark BENCHMARK_Reset(); portENTER_CRITICAL(); // port specific FreeRTOS function to disable tasks (nested) // turn on LED (e.g. for measurements with a scope) MIOS32_BOARD_LED_Set(0xffffffff, 1); // reset stopwatch MIOS32_STOPWATCH_Reset(); // start benchmark BENCHMARK_Start(tested_port); // capture counter value benchmark_cycles = MIOS32_STOPWATCH_ValueGet(); // turn off LED MIOS32_BOARD_LED_Set(0xffffffff, 0); portEXIT_CRITICAL(); // port specific FreeRTOS function to enable tasks (nested) // print result on MIOS terminal if( benchmark_cycles == 0xffffffff ) MIOS32_MIDI_SendDebugMessage("Time: overrun!\n"); else MIOS32_MIDI_SendDebugMessage("Time: %5d.%d mS\n", benchmark_cycles/10, benchmark_cycles%10); // print status screen print_msg = PRINT_MSG_STATUS; } }
///////////////////////////////////////////////////////////////////////////// // Main function ///////////////////////////////////////////////////////////////////////////// int main(void) { // initialize hardware and MIOS32 modules #ifndef MIOS32_DONT_USE_SYS MIOS32_SYS_Init(0); #endif #ifndef MIOS32_DONT_USE_DELAY MIOS32_DELAY_Init(0); #endif #ifndef MIOS32_DONT_USE_TIMESTAMP MIOS32_TIMESTAMP_Init(0); #endif #ifndef MIOS32_DONT_USE_BOARD MIOS32_BOARD_Init(0); #endif #ifndef MIOS32_DONT_USE_SPI MIOS32_SPI_Init(0); #endif #ifndef MIOS32_DONT_USE_SRIO MIOS32_SRIO_Init(0); #endif #if !defined(MIOS32_DONT_USE_DIN) && !defined(MIOS32_DONT_USE_SRIO) MIOS32_DIN_Init(0); #endif #if !defined(MIOS32_DONT_USE_DOUT) && !defined(MIOS32_DONT_USE_SRIO) MIOS32_DOUT_Init(0); #endif #if !defined(MIOS32_DONT_USE_ENC) && !defined(MIOS32_DONT_USE_SRIO) MIOS32_ENC_Init(0); #endif #if !defined(MIOS32_DONT_USE_MF) MIOS32_MF_Init(0); #endif #if !defined(MIOS32_DONT_USE_AIN) MIOS32_AIN_Init(0); #endif #ifndef MIOS32_DONT_USE_IIC_BS MIOS32_IIC_BS_Init(0); #endif #ifndef MIOS32_DONT_USE_MIDI MIOS32_MIDI_Init(0); #endif #ifndef MIOS32_DONT_USE_USB MIOS32_USB_Init(0); #endif #ifndef MIOS32_DONT_USE_OSC MIOS32_OSC_Init(0); #endif #ifndef MIOS32_DONT_USE_COM MIOS32_COM_Init(0); #endif #ifndef MIOS32_DONT_USE_LCD MIOS32_LCD_Init(0); # if defined(MIOS32_BOARD_MBHP_CORE_STM32) || defined(MIOS32_BOARD_MBHP_CORE_LPC17) || defined(MIOS32_BOARD_STM32F4DISCOVERY) || defined(MIOS32_BOARD_MBHP_CORE_STM32F4) // init second LCD as well (if available) MIOS32_LCD_DeviceSet(1); APP_LCD_Init(0); MIOS32_LCD_DeviceSet(0); # endif #endif #ifdef MIOS32_USE_I2S MIOS32_I2S_Init(0); #endif // call C++ constructors __libc_init_array(); // initialize application APP_Init(); #if MIOS32_LCD_BOOT_MSG_DELAY // print boot message # ifndef MIOS32_DONT_USE_LCD MIOS32_LCD_PrintBootMessage(); # endif // wait for given delay (usually 2 seconds) # ifndef MIOS32_DONT_USE_DELAY int delay = 0; for(delay=0; delay<MIOS32_LCD_BOOT_MSG_DELAY; ++delay) MIOS32_DELAY_Wait_uS(1000); # endif #endif // start the task which calls the application hooks xTaskCreate(TASK_Hooks, (signed portCHAR *)"Hooks", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_HOOKS, NULL); #if !defined(MIOS32_DONT_USE_MIDI) xTaskCreate(TASK_MIDI_Hooks, (signed portCHAR *)"MIDI_Hooks", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_HOOKS, NULL); #endif // start the scheduler vTaskStartScheduler(); // Will only get here if there was not enough heap space to create the idle task return 0; }
static void TASK_MatrixScan(void *pvParameters) { while( 1 ) { // wait for next timesplice (1 mS) vTaskDelay(1 / portTICK_RATE_MS); // determine timestamp (we need it for delay measurements) mios32_sys_time_t t = MIOS32_SYS_TimeGet(); u32 timestamp = 1000*t.seconds + t.fraction_ms; // loop: // - latch DIN/DOUT values // - shift selection pattern for *next* row to DOUT registers // - read DIN values of previously selected row // since we need to select the first row before the first DIN values are latched, we loop from -1 // to handle the initial state int row; for(row=-1; row<MATRIX_NUM_ROWS; ++row) { if( row >= 0 ) { // not required for initial scan // latch DIN values MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 0); // spi, rc_pin, pin_value MIOS32_DELAY_Wait_uS(1); MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 1); // spi, rc_pin, pin_value } // determine selection mask for next row (written into DOUT registers while reading DIN registers) u16 select_row_pattern = ~(1 << (row+1)); #if MATRIX_DOUT_HAS_SINK_DRIVERS select_row_pattern ^= 0xffff; // invert selection pattern if sink drivers are connected to DOUT pins #endif // read DIN, write DOUT u8 din0 = MIOS32_SPI_TransferByte(MIOS32_SRIO_SPI, (select_row_pattern >> 8) & 0xff); u8 din1 = MIOS32_SPI_TransferByte(MIOS32_SRIO_SPI, (select_row_pattern >> 0) & 0xff); // latch new DOUT value MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 0); // spi, rc_pin, pin_value MIOS32_DELAY_Wait_uS(1); MIOS32_SPI_RC_PinSet(MIOS32_SRIO_SPI, MIOS32_SRIO_SPI_RC_PIN, 1); // spi, rc_pin, pin_value if( row >= 0 ) { // combine read DIN bytes to 16bit value u16 din_pattern = (din1 << 8) | din0; // check if values have been changed via XOR combination with previously scanned value u16 changed = din_pattern ^ din_value[row]; if( changed ) { // store changed value din_value[row] = din_pattern; // notify changed value int column; for(column=0; column<16; ++column) { u16 mask = 1 << column; if( changed & mask ) BUTTON_NotifyToggle(row, column, (din_pattern & mask) ? 1 : 0, timestamp); } } } } } }