diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 64ca0c9d3b9..9239c7b2c94 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -34,9 +34,11 @@ import processing.app.debug.TargetPackage; import processing.app.debug.TargetPlatform; import processing.app.helpers.FileUtils; +import processing.app.helpers.Maps; import processing.app.helpers.PreferencesMap; import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyFilesWithExtension; +import processing.app.tools.MapWithSubkeys; import processing.app.tools.ZipDeflater; import processing.core.*; import static processing.app.I18n._; @@ -1121,18 +1123,19 @@ public void onBoardOrPortChange() { editor.onBoardOrPortChange(); } - - public void rebuildBoardsMenu(JMenu boardsMenu, final JMenu cpuTypeMenu, final Editor editor) { + public void rebuildBoardsMenu(JMenu toolsMenu, final Editor editor) { + JMenu boardsMenu = makeOrGetBoardMenu(toolsMenu, "Board"); + String selPackage = Preferences.get("target_package"); String selPlatform = Preferences.get("target_platform"); String selBoard = Preferences.get("board"); - String selBoardContainer = Preferences.get("board_container"); - boardsMenu.removeAll(); boolean first = true; + List menuItemsToClickAfterStartup = new LinkedList(); + ButtonGroup boardsButtonGroup = new ButtonGroup(); - ButtonGroup cpuTypesButtonGroup = new ButtonGroup(); + Map buttonGroupsMap = new HashMap(); // Cycle through all packages for (TargetPackage targetPackage : packages.values()) { @@ -1142,115 +1145,160 @@ public void rebuildBoardsMenu(JMenu boardsMenu, final JMenu cpuTypeMenu, final E for (TargetPlatform targetPlatform : targetPackage.platforms()) { String platformName = targetPlatform.getName(); Map boards = targetPlatform.getBoards(); + + if (targetPlatform.getPreferences().get("name") == null || targetPlatform.getBoards().isEmpty()) { + continue; + } // Add a title for each group of boards - if (!first) + if (!first) { boardsMenu.add(new JSeparator()); - first = false; + } + first = false; + JMenuItem separator = new JMenuItem(targetPlatform.getPreferences().get("name")); separator.setEnabled(false); boardsMenu.add(separator); // For every platform cycle through all boards - for (String boardID : targetPlatform.getOrderedBoards()) { + for (final String boardID : targetPlatform.getBoards().keySet()) { PreferencesMap boardAttributes = boards.get(boardID); - final String boardContainer = boardAttributes.get("container"); - AbstractAction filterCPUTypeMenuAction = new AbstractAction() { + AbstractAction action = new AbstractAction(boardAttributes.get("name")) { @Override public void actionPerformed(ActionEvent e) { - Preferences.set("board_container", (String) getValue("board_container")); - - cpuTypeMenu.setEnabled(true); - - for (int i = 0; i < cpuTypeMenu.getItemCount(); i++) { - JMenuItem cpuTypeMenuItem = cpuTypeMenu.getItem(i); - boolean visible = boardContainer.equals(cpuTypeMenuItem.getAction().getValue("board_container")); - cpuTypeMenuItem.setVisible(visible); - } - - JMenuItem selectSelectedOrFirstVisibleMenuItem = selectVisibleSelectedOrFirstMenuItem(cpuTypeMenu); - selectSelectedOrFirstVisibleMenuItem.doClick(); - } - }; - filterCPUTypeMenuAction.putValue("board_container", boardContainer); - - @SuppressWarnings("serial") - final AbstractAction selectBoardAction = new AbstractAction(boardAttributes.get("cpu")) { - public void actionPerformed(ActionEvent actionevent) { Preferences.set("target_package", (String) getValue("package")); Preferences.set("target_platform", (String) getValue("platform")); Preferences.set("board", (String) getValue("board")); + + filterVisibilityOfSubsequentBoardMenus((String) getValue("board"), 1, e); onBoardOrPortChange(); Sketch.buildSettingChanged(); rebuildImportMenu(Editor.importMenu, editor); rebuildExamplesMenu(Editor.examplesMenu); } + }; - selectBoardAction.putValue("package", packageName); - selectBoardAction.putValue("platform", platformName); - selectBoardAction.putValue("board", boardID); - selectBoardAction.putValue("board_container", boardContainer); + action.putValue("properties", boardAttributes); + action.putValue("board", boardID); + action.putValue("package", packageName); + action.putValue("platform", platformName); - if (boardContainer != null) { - findOrCreateBoardContainerMenu(boardsMenu, boardsButtonGroup, boardContainer, filterCPUTypeMenuAction); + JRadioButtonMenuItem item = new JRadioButtonMenuItem(action); + boardsMenu.add(item); + boardsButtonGroup.add(item); - JMenuItem item = new JRadioButtonMenuItem(selectBoardAction); - cpuTypesButtonGroup.add(item); - cpuTypeMenu.add(item); - } else { - AbstractAction selectBoardWithoutContainerAction = new AbstractAction(boardAttributes.get("name")) { - - @Override - public void actionPerformed(ActionEvent e) { - cpuTypeMenu.setEnabled(false); - Preferences.unset("board_container"); - selectBoardAction.actionPerformed(e); - } - - @Override - public Object getValue(String key) { - return selectBoardAction.getValue(key); - } - - @Override - public void putValue(String key, Object newValue) { - selectBoardAction.putValue(key, newValue); + if (selBoard.equals(action.getValue("board")) && selPackage.equals(action.getValue("package")) + && selPlatform.equals(action.getValue("platform"))) { + menuItemsToClickAfterStartup.add(item); + } + + if (targetPlatform.getCustomMenus() != null) { + List customMenuIDs = new LinkedList(targetPlatform.getCustomMenus().getKeys()); + for (int i = 0; i < customMenuIDs.size(); i++) { + final String customMenuID = customMenuIDs.get(i); + JMenu menu = makeOrGetBoardMenu(toolsMenu, _(targetPlatform.getCustomMenus().getValueOf(customMenuID))); + MapWithSubkeys customMenu = targetPlatform.getCustomMenus().get(customMenuID); + if (customMenu.getKeys().contains(boardID)) { + MapWithSubkeys boardCustomMenu = customMenu.get(boardID); + final int currentIndex = i + 1 + 1; //plus 1 to skip the first board menu, plus 1 to keep the custom menu next to this one + for (final String customMenuOption : boardCustomMenu.getKeys()) { + action = new AbstractAction(_(boardCustomMenu.getValueOf(customMenuOption))) { + + @Override + public void actionPerformed(ActionEvent e) { + Preferences.set("target_package", (String) getValue("package")); + Preferences.set("target_platform", (String) getValue("platform")); + Preferences.set("board", (String) getValue("board")); + Preferences.set("custom_" + customMenuID, boardID + "_" + (String) getValue("custom_menu_option")); + + filterVisibilityOfSubsequentBoardMenus((String) getValue("board"), currentIndex, e); + + onBoardOrPortChange(); + Sketch.buildSettingChanged(); + rebuildImportMenu(Editor.importMenu, editor); + rebuildExamplesMenu(Editor.examplesMenu); + } + }; + action.putValue("properties", boardCustomMenu.getValues()); + action.putValue("board", boardID); + action.putValue("custom_menu_option", customMenuOption); + action.putValue("package", packageName); + action.putValue("platform", platformName); + + if (!buttonGroupsMap.containsKey(customMenuID)) { + buttonGroupsMap.put(customMenuID, new ButtonGroup()); + } + + item = new JRadioButtonMenuItem(action); + menu.add(item); + buttonGroupsMap.get(customMenuID).add(item); + + String selectedCustomMenuEntry = Preferences.get("custom_" + customMenuID); + if (selBoard.equals(boardID) && (boardID + "_" + customMenuOption).equals(selectedCustomMenuEntry)) { + menuItemsToClickAfterStartup.add(item); + } + } } - }; - JMenuItem item = new JRadioButtonMenuItem(selectBoardWithoutContainerAction); - boardsButtonGroup.add(item); - boardsMenu.add(item); + } } } } - } - - JMenuItem selectedBoardMenu = selectMenuItemByBoardContainer(boardsMenu, selBoardContainer); - if (selectedBoardMenu == null) { - selectedBoardMenu = selectMenuItemByBoardPackagePlatform(boardsMenu, selBoard, selPackage, selPlatform); - if (selectedBoardMenu == null) { - selectedBoardMenu = selectFirstEnabledMenuItem(boardsMenu); + + if (menuItemsToClickAfterStartup.isEmpty()) { + menuItemsToClickAfterStartup.add(selectFirstEnabledMenuItem(boardsMenu)); + } + + for (JMenuItem menuItemToClick : menuItemsToClickAfterStartup) { + menuItemToClick.setSelected(true); + menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); } } - selectedBoardMenu.doClick(); + } - if (cpuTypeMenu.isEnabled()) { - JMenuItem selectedCPUTypeMenu; - if (selBoard == null) { - selectedCPUTypeMenu = selectFirstEnabledMenuItem(cpuTypeMenu); - } else { - selectedCPUTypeMenu = selectMenuItemByBoardPackagePlatform(cpuTypeMenu, selBoard, selPackage, selPlatform); - if (selectedCPUTypeMenu == null) { - selectedCPUTypeMenu = selectFirstEnabledMenuItem(cpuTypeMenu); + private static void filterVisibilityOfSubsequentBoardMenus(String boardID, int fromIndex, ActionEvent originatingEvent) { + for (int i = fromIndex; i < Editor.boardsMenus.size(); i++) { + JMenu menu = Editor.boardsMenus.get(i); + for (int m = 0; m < menu.getItemCount(); m++) { + JMenuItem menuItem = menu.getItem(m); + menuItem.setVisible(menuItem.getAction().getValue("board").equals(boardID)); + } + menu.setEnabled(ifThereAreVisibleItemsOn(menu)); + + if (menu.isEnabled()) { + JMenuItem visibleSelectedOrFirstMenuItem = selectVisibleSelectedOrFirstMenuItem(menu); + if (!visibleSelectedOrFirstMenuItem.isSelected()) { + visibleSelectedOrFirstMenuItem.setSelected(true); + visibleSelectedOrFirstMenuItem.getAction().actionPerformed(originatingEvent); } } - selectedCPUTypeMenu.doClick(); } } + + private static boolean ifThereAreVisibleItemsOn(JMenu menu) { + for (int i = 0; i < menu.getItemCount(); i++) { + if (menu.getItem(i).isVisible()) { + return true; + } + } + return false; + } + + private JMenu makeOrGetBoardMenu(JMenu toolsMenu, String label) { + String i18nLabel = _(label); + for (JMenu menu : Editor.boardsMenus) { + if (i18nLabel.equals(menu.getText())) { + return menu; + } + } + JMenu menu = new JMenu(i18nLabel); + Editor.boardsMenus.add(menu); + toolsMenu.add(menu); + return menu; + } private static JMenuItem selectVisibleSelectedOrFirstMenuItem(JMenu menu) { JMenuItem firstVisible = null; @@ -1283,45 +1331,6 @@ private static JMenuItem selectFirstEnabledMenuItem(JMenu menu) { throw new IllegalStateException("Menu has no enabled items"); } - private static JMenuItem selectMenuItemByBoardContainer(JMenu menu, String boardContainer) { - if (boardContainer == null) { - return null; - } - - for (int i = 0; i < menu.getItemCount(); i++) { - JMenuItem item = menu.getItem(i); - if (item != null && item.getAction() != null && boardContainer.equals(item.getAction().getValue("board_container"))) { - return item; - } - } - return null; - } - - private static JMenuItem selectMenuItemByBoardPackagePlatform(JMenu menu, String selBoard, String selPackage, String selPlatform) { - for (int i = 0; i < menu.getItemCount(); i++) { - JMenuItem item = menu.getItem(i); - if (item != null && item.getAction() != null && selBoard.equals(item.getAction().getValue("board")) - && selPackage.equals(item.getAction().getValue("package")) && selPlatform.equals(item.getAction().getValue("platform"))) { - return item; - } - } - return null; - } - - private JMenuItem findOrCreateBoardContainerMenu(JMenu boardsMenu, ButtonGroup boardsButtonGroup, String boardContainerName, AbstractAction boardMenuAction) { - for (int i = 0; i < boardsMenu.getItemCount(); i++ ) { - JMenuItem boardContainer = boardsMenu.getItem(i); - if (boardContainer != null && boardContainerName.equals(boardContainer.getText())) { - return boardContainer; - } - } - JMenuItem item = new JRadioButtonMenuItem(boardMenuAction); - item.setText(boardContainerName); - boardsButtonGroup.add(item); - boardsMenu.add(item); - return item; - } - public void rebuildProgrammerMenu(JMenu menu) { menu.removeAll(); ButtonGroup group = new ButtonGroup(); @@ -1809,10 +1818,22 @@ static public TargetPlatform getCurrentTargetPlatformFromPackage(String pack) { return getTargetPlatform(pack, Preferences.get("target_platform")); } - static public PreferencesMap getBoardPreferences() { + static public Map getBoardPreferences() { TargetPlatform target = getTargetPlatform(); String board = Preferences.get("board"); - return target.getBoards().get(board); + Map boardPreferences = Maps.merge(target.getBoards().get(board), new LinkedHashMap()); + if (target.getCustomMenus() != null) { + for (String customMenuID : target.getCustomMenus().getKeys()) { + MapWithSubkeys boardCustomMenu = target.getCustomMenus().get(customMenuID).get(board); + String selectedCustomMenuEntry = Preferences.get("custom_" + customMenuID); + if (boardCustomMenu != null && selectedCustomMenuEntry != null && selectedCustomMenuEntry.startsWith(board)) { + String menuEntryId = selectedCustomMenuEntry.substring(selectedCustomMenuEntry.indexOf("_") + 1); + Maps.merge(boardCustomMenu.get(menuEntryId).getValues(), boardPreferences); + boardPreferences.put("name", boardPreferences.get("name") + ", " + boardCustomMenu.getValueOf(menuEntryId)); + } + } + } + return boardPreferences; } static public File getSketchbookFolder() { diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 536b36a1313..b5ad9941cb9 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -35,6 +35,7 @@ import java.io.*; import java.net.*; import java.util.*; +import java.util.List; import java.util.zip.*; import javax.swing.*; @@ -95,9 +96,8 @@ public class Editor extends JFrame implements RunnerListener { // these menus are shared so that the board and serial port selections // are the same for all windows (since the board and serial port that are // actually used are determined by the preferences, which are shared) - static JMenu boardsMenu; + static List boardsMenus; static JMenu serialMenu; - static JMenu cpuTypeMenu; static SerialMenuListener serialMenuListener; static SerialMonitor serialMonitor; @@ -178,10 +178,13 @@ public void windowActivated(WindowEvent e) { // re-add the sub-menus that are shared by all windows fileMenu.insert(sketchbookMenu, 2); fileMenu.insert(examplesMenu, 3); - //sketchMenu.insert(importMenu, 4); - toolsMenu.insert(boardsMenu, numTools); - toolsMenu.insert(cpuTypeMenu, numTools + 1); - toolsMenu.insert(serialMenu, numTools + 2); + sketchMenu.insert(importMenu, 4); + int offset = 0; + for (JMenu menu : boardsMenus) { + toolsMenu.insert(menu, numTools + offset); + offset++; + } + toolsMenu.insert(serialMenu, numTools + offset); } // added for 1.0.5 @@ -190,9 +193,10 @@ public void windowDeactivated(WindowEvent e) { // System.err.println("deactivate"); // not coming through fileMenu.remove(sketchbookMenu); fileMenu.remove(examplesMenu); - //sketchMenu.remove(importMenu); - toolsMenu.remove(boardsMenu); - toolsMenu.remove(cpuTypeMenu); + sketchMenu.remove(importMenu); + for (JMenu menu : boardsMenus) { + toolsMenu.remove(menu); + } toolsMenu.remove(serialMenu); } }); @@ -681,16 +685,13 @@ public void actionPerformed(ActionEvent e) { // XXX: DAM: these should probably be implemented using the Tools plugin // API, if possible (i.e. if it supports custom actions, etc.) - if (boardsMenu == null) { - boardsMenu = new JMenu(_("Board")); - cpuTypeMenu = new JMenu(_("Processor")); - base.rebuildBoardsMenu(boardsMenu, cpuTypeMenu, this); + if (boardsMenus == null) { + boardsMenus = new LinkedList(); + base.rebuildBoardsMenu(toolsMenu, this); //Debug: rebuild imports importMenu.removeAll(); base.rebuildImportMenu(importMenu, this); } - menu.add(boardsMenu); - menu.add(cpuTypeMenu); if (serialMenuListener == null) serialMenuListener = new SerialMenuListener(); @@ -2660,7 +2661,7 @@ public void statusEmpty() { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . protected void onBoardOrPortChange() { - Map boardPreferences = Base.getBoardPreferences(); + Map boardPreferences = Base.getBoardPreferences(); lineStatus.setBoardName(boardPreferences.get("name")); lineStatus.setSerialPort(Preferences.get("serial.port")); lineStatus.repaint(); diff --git a/app/src/processing/app/debug/TargetPlatform.java b/app/src/processing/app/debug/TargetPlatform.java index 9fcc51d4318..4eabe9a9530 100644 --- a/app/src/processing/app/debug/TargetPlatform.java +++ b/app/src/processing/app/debug/TargetPlatform.java @@ -24,28 +24,25 @@ package processing.app.debug; import java.io.File; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; import processing.app.helpers.PreferencesMap; -import processing.core.PApplet; +import processing.app.tools.MapWithSubkeys; public class TargetPlatform { private String name; private File folder; private Map boards; - private List boardsOrder; private Map programmers; private PreferencesMap preferences; + private MapWithSubkeys customMenus; public TargetPlatform(String _name, File _folder) { System.out.println("TargetPlatform: constructor start, name: " + _name); name = _name; folder = _folder; boards = new HashMap(); - boardsOrder = new ArrayList(); programmers = new HashMap(); preferences = new PreferencesMap(); @@ -55,9 +52,11 @@ public TargetPlatform(String _name, File _folder) { PreferencesMap boardPreferences = new PreferencesMap(); boardPreferences.load(boardsFile); boards = boardPreferences.createFirstLevelMap(); - boardsOrder = readBoardsOrder(boardsFile); + customMenus = MapWithSubkeys.createFrom(boards.get("menu")); + boards.remove("menu"); } } catch (Exception e) { + e.printStackTrace(); System.err.println("Error loading boards from boards.txt: " + e); } @@ -82,32 +81,6 @@ public TargetPlatform(String _name, File _folder) { } } - /** - * Loads the ordered list of boards as they appears on the boards.txt file - * - * @param boardsFile - * @return - */ - private List readBoardsOrder(File boardsFile) { - String[] strings = PApplet.loadStrings(boardsFile); - - List res = new ArrayList(); - String latestBoard = "-"; - for (String s : strings) { - int dot = s.indexOf('.'); - if (dot == -1) - continue; - String board = s.substring(0, dot); - if (board.equals(latestBoard)) - continue; - if (!boards.containsKey(board)) - continue; - latestBoard = board; - res.add(board); - } - return res; - } - public String getName() { return name; } @@ -119,9 +92,9 @@ public File getFolder() { public Map getBoards() { return boards; } - - public List getOrderedBoards() { - return boardsOrder; + + public MapWithSubkeys getCustomMenus() { + return customMenus; } public Map getProgrammers() { diff --git a/app/src/processing/app/helpers/Maps.java b/app/src/processing/app/helpers/Maps.java new file mode 100644 index 00000000000..439cb6bc5c0 --- /dev/null +++ b/app/src/processing/app/helpers/Maps.java @@ -0,0 +1,15 @@ +package processing.app.helpers; + +import java.util.Map; +import java.util.Map.Entry; + +public class Maps { + + public static Map merge(Map input, Map target) { + for (Entry entry : input.entrySet()) { + target.put(entry.getKey(), entry.getValue()); + } + return target; + } + +} diff --git a/app/src/processing/app/helpers/PreferencesMap.java b/app/src/processing/app/helpers/PreferencesMap.java index 22e3523f241..f83e04b1f34 100644 --- a/app/src/processing/app/helpers/PreferencesMap.java +++ b/app/src/processing/app/helpers/PreferencesMap.java @@ -28,25 +28,17 @@ import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Hashtable; -import java.util.Map; -import java.util.Set; +import java.util.*; import processing.app.Base; import processing.core.PApplet; -public class PreferencesMap extends HashMap { +public class PreferencesMap extends LinkedHashMap { - public PreferencesMap(Hashtable table) { + public PreferencesMap(Map table) { super(table); } - public PreferencesMap(PreferencesMap prefs) { - super(prefs); - } - public PreferencesMap() { super(); } @@ -86,18 +78,18 @@ public void load(InputStream input) throws IOException { Set keys = new HashSet(keySet()); // Override keys that have OS specific versions - for (String k : keys) { + for (String key : keys) { boolean replace = false; - if (Base.isLinux() && k.endsWith(".linux")) + if (Base.isLinux() && key.endsWith(".linux")) replace = true; - if (Base.isWindows() && k.endsWith(".windows")) + if (Base.isWindows() && key.endsWith(".windows")) replace = true; - if (Base.isMacOS() && k.endsWith(".macos")) + if (Base.isMacOS() && key.endsWith(".macos")) replace = true; if (replace) { - int dot = k.lastIndexOf('.'); - String overridenKey = k.substring(0, dot); - put(overridenKey, get(k)); + int dot = key.lastIndexOf('.'); + String overridenKey = key.substring(0, dot); + put(overridenKey, get(key)); } } } @@ -129,7 +121,7 @@ public void load(InputStream input) throws IOException { * @return */ public Map createFirstLevelMap() { - Map res = new HashMap(); + Map res = new LinkedHashMap(); for (String key : keySet()) { int dot = key.indexOf('.'); if (dot == -1) diff --git a/app/src/processing/app/tools/MapWithSubkeys.java b/app/src/processing/app/tools/MapWithSubkeys.java new file mode 100644 index 00000000000..1ad5e4b6222 --- /dev/null +++ b/app/src/processing/app/tools/MapWithSubkeys.java @@ -0,0 +1,66 @@ +package processing.app.tools; + +import java.util.*; +import java.util.Map.Entry; + +public class MapWithSubkeys { + + public static MapWithSubkeys createFrom(Map input) { + if (input == null) { + return null; + } + MapWithSubkeys target = new MapWithSubkeys(); + for (Entry entry : input.entrySet()) { + String[] entryParts = entry.getKey().split("\\."); + if (entryParts.length == 1) { + target.put(entryParts[0], entry.getValue()); + } else if (entryParts.length == 3) { + target.get(entryParts[0]).get(entryParts[1]).put(entryParts[2], entry.getValue()); + } else if (entryParts.length > 3) { + StringBuilder sb = new StringBuilder(); + for (int i = 3; i < entryParts.length; i++) { + sb.append(entryParts[i]).append("."); + } + sb.deleteCharAt(sb.length() - 1); + String key = sb.toString(); + target.get(entryParts[0]).get(entryParts[1]).get(entryParts[2]).put(key, entry.getValue()); + } + } + return target; + } + + private final Map values; + private final Map maps; + + public MapWithSubkeys() { + this.values = new LinkedHashMap(); + this.maps = new LinkedHashMap(); + } + + public Collection getKeys() { + return values.keySet(); + } + + public Map getValues() { + return values; + } + + public String getValueOf(String key) { + return values.get(key); + } + + public MapWithSubkeys get(String key) { + if (!maps.containsKey(key)) { + maps.put(key, new MapWithSubkeys()); + } + if (!values.containsKey(key)) { + put(key, null); + } + return maps.get(key); + } + + public void put(String key, String value) { + values.put(key, value); + } + +} diff --git a/app/test/processing/app/tools/MapWithSubkeysTest.java b/app/test/processing/app/tools/MapWithSubkeysTest.java new file mode 100644 index 00000000000..a602e08f6bc --- /dev/null +++ b/app/test/processing/app/tools/MapWithSubkeysTest.java @@ -0,0 +1,59 @@ +package processing.app.tools; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +import org.junit.Before; +import org.junit.Test; + +public class MapWithSubkeysTest { + + private MapWithSubkeys map; + + @Before + public void setup() throws Exception { + Map input = new HashMap(); + BufferedReader reader = new BufferedReader(new InputStreamReader(MapWithSubkeysTest.class.getResourceAsStream("test_partial_boards.txt"))); + String line = null; + while ((line = reader.readLine()) != null) { + String[] lineParts = line.split("="); + input.put(lineParts[0], lineParts[1]); + } + map = MapWithSubkeys.createFrom(input); + } + + @Test + public void shouldListCustomMenusIDs() { + Collection menusIDs = map.getKeys(); + + assertEquals(2, menusIDs.size()); + assertTrue(menusIDs.contains("cpu")); + assertTrue(menusIDs.contains("speed")); + + assertEquals("Processor", map.getValueOf("cpu")); + + MapWithSubkeys cpu = map.get("cpu"); + + Collection boards = cpu.getKeys(); + assertEquals(1, boards.size()); + assertTrue(boards.contains("nano")); + + Collection cpuNanoProcessors = cpu.get("nano").getKeys(); + assertEquals(2, cpuNanoProcessors.size()); + assertTrue(cpuNanoProcessors.contains("atmega168")); + assertTrue(cpuNanoProcessors.contains("atmega328")); + assertEquals("ATmega168", cpu.get("nano").getValueOf("atmega168")); + assertEquals("ATmega328", cpu.get("nano").getValueOf("atmega328")); + + MapWithSubkeys atmega168Properties = cpu.get("nano").get("atmega168"); + assertEquals(9, atmega168Properties.getKeys().size()); + assertTrue(atmega168Properties.getKeys().contains("bootloader.high_fuses")); + } + +} diff --git a/app/test/processing/app/tools/test_partial_boards.txt b/app/test/processing/app/tools/test_partial_boards.txt new file mode 100644 index 00000000000..ad873c375c5 --- /dev/null +++ b/app/test/processing/app/tools/test_partial_boards.txt @@ -0,0 +1,26 @@ +cpu=Processor +cpu.nano.atmega328=ATmega328 +cpu.nano.atmega328.upload.maximum_size=30720 +cpu.nano.atmega328.upload.speed=57600 +cpu.nano.atmega328.bootloader.low_fuses=0xFF +cpu.nano.atmega328.bootloader.high_fuses=0xDA +cpu.nano.atmega328.bootloader.extended_fuses=0x05 +cpu.nano.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex +cpu.nano.atmega328.bootloader.unlock_bits=0x3F +cpu.nano.atmega328.bootloader.lock_bits=0x0F +cpu.nano.atmega328.build.mcu=atmega328p +cpu.nano.atmega168=ATmega168 +cpu.nano.atmega168.upload.maximum_size=14336 +cpu.nano.atmega168.upload.speed=19200 +cpu.nano.atmega168.bootloader.low_fuses=0xff +cpu.nano.atmega168.bootloader.high_fuses=0xdd +cpu.nano.atmega168.bootloader.extended_fuses=0x00 +cpu.nano.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex +cpu.nano.atmega168.bootloader.unlock_bits=0x3F +cpu.nano.atmega168.bootloader.lock_bits=0x0F +cpu.nano.atmega168.build.mcu=atmega168 +speed=Speed +speed.nano.16=16 MHz +speed.nano.16.build.f_cpu=16000000L +speed.nano.8=8 MHz +speed.nano.8.build.f_cpu=8000000L \ No newline at end of file diff --git a/hardware/arduino/avr/boards.txt b/hardware/arduino/avr/boards.txt index b4b2cae1733..2a68c762fbe 100644 --- a/hardware/arduino/avr/boards.txt +++ b/hardware/arduino/avr/boards.txt @@ -1,5 +1,7 @@ # See: http://code.google.com/p/arduino/wiki/Platforms +menu.cpu=Processor + ############################################################## uno.name=Arduino Uno @@ -23,101 +25,89 @@ uno.build.variant=standard ############################################################## -atmega328.name=Arduino Duemilanove w/ ATmega328 - -atmega328.upload.tool=avrdude -atmega328.upload.protocol=arduino -atmega328.upload.maximum_size=30720 -atmega328.upload.speed=57600 +atmega328diecimila.name=Arduino Duemilanove or Diecimila -atmega328.bootloader.tool=avrdude -atmega328.bootloader.low_fuses=0xFF -atmega328.bootloader.high_fuses=0xDA -atmega328.bootloader.extended_fuses=0x05 -atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex -atmega328.bootloader.unlock_bits=0x3F -atmega328.bootloader.lock_bits=0x0F +atmega328diecimila.upload.tool=avrdude +atmega328diecimila.upload.protocol=arduino -atmega328.build.mcu=atmega328p -atmega328.build.f_cpu=16000000L -atmega328.build.core=arduino -atmega328.build.variant=standard +atmega328diecimila.bootloader.tool=avrdude +atmega328diecimila.bootloader.low_fuses=0xFF +atmega328diecimila.bootloader.unlock_bits=0x3F +atmega328diecimila.bootloader.lock_bits=0x0F -############################################################## +atmega328diecimila.build.f_cpu=16000000L +atmega328diecimila.build.core=arduino +atmega328diecimila.build.variant=standard -diecimila.name=Arduino Diecimila or Duemilanove w/ ATmega168 +## Arduino Duemilanove or Diecimila w/ ATmega328 +menu.cpu.atmega328diecimila.atmega328=ATmega328 -diecimila.upload.tool=avrdude -diecimila.upload.protocol=arduino -diecimila.upload.maximum_size=14336 -diecimila.upload.speed=19200 +menu.cpu.atmega328diecimila.atmega328.upload.maximum_size=30720 +menu.cpu.atmega328diecimila.atmega328.upload.speed=57600 -diecimila.bootloader.tool=avrdude -diecimila.bootloader.low_fuses=0xff -diecimila.bootloader.high_fuses=0xdd -diecimila.bootloader.extended_fuses=0x00 -diecimila.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex -diecimila.bootloader.unlock_bits=0x3F -diecimila.bootloader.lock_bits=0x0F +menu.cpu.atmega328diecimila.atmega328.bootloader.high_fuses=0xDA +menu.cpu.atmega328diecimila.atmega328.bootloader.extended_fuses=0x05 +menu.cpu.atmega328diecimila.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex -diecimila.build.mcu=atmega168 -diecimila.build.f_cpu=16000000L -diecimila.build.core=arduino -diecimila.build.variant=standard - -############################################################## +menu.cpu.atmega328diecimila.atmega328.build.mcu=atmega328p -nano328.name=Arduino Nano w/ ATmega328 -nano328.cpu=ATmega328 -nano328.container=Arduino Nano +## Arduino Duemilanove or Diecimila w/ ATmega168 +menu.cpu.atmega328diecimila.atmega168=ATmega168 -nano328.upload.tool=avrdude -nano328.upload.protocol=arduino -nano328.upload.maximum_size=30720 -nano328.upload.speed=57600 +menu.cpu.atmega328diecimila.atmega168.upload.maximum_size=14336 +menu.cpu.atmega328diecimila.atmega168.upload.speed=19200 -nano328.bootloader.tool=avrdude -nano328.bootloader.low_fuses=0xFF -nano328.bootloader.high_fuses=0xDA -nano328.bootloader.extended_fuses=0x05 -nano328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex -nano328.bootloader.unlock_bits=0x3F -nano328.bootloader.lock_bits=0x0F +menu.cpu.atmega328diecimila.atmega168.bootloader.high_fuses=0xdd +menu.cpu.atmega328diecimila.atmega168.bootloader.extended_fuses=0x00 +menu.cpu.atmega328diecimila.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex -nano328.build.mcu=atmega328p -nano328.build.f_cpu=16000000L -nano328.build.core=arduino -nano328.build.variant=eightanaloginputs +menu.cpu.atmega328diecimila.atmega168.build.mcu=atmega168 ############################################################## -nano.name=Arduino Nano w/ ATmega168 -nano.cpu=ATmega168 -nano.container=Arduino Nano +nano.name=Arduino Nano nano.upload.tool=avrdude nano.upload.protocol=arduino -nano.upload.maximum_size=14336 -nano.upload.speed=19200 nano.bootloader.tool=avrdude -nano.bootloader.low_fuses=0xff -nano.bootloader.high_fuses=0xdd -nano.bootloader.extended_fuses=0x00 -nano.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex nano.bootloader.unlock_bits=0x3F nano.bootloader.lock_bits=0x0F -nano.build.mcu=atmega168 nano.build.f_cpu=16000000L nano.build.core=arduino nano.build.variant=eightanaloginputs +## Arduino Nano w/ ATmega328 +menu.cpu.nano.atmega328=ATmega328 + +menu.cpu.nano.atmega328.upload.maximum_size=30720 +menu.cpu.nano.atmega328.upload.speed=57600 + +menu.cpu.nano.atmega328.bootloader.low_fuses=0xFF +menu.cpu.nano.atmega328.bootloader.high_fuses=0xDA +menu.cpu.nano.atmega328.bootloader.extended_fuses=0x05 +menu.cpu.nano.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex + +menu.cpu.nano.atmega328.build.mcu=atmega328p + +## Arduino Nano w/ ATmega168 +menu.cpu.nano.atmega168=ATmega168 + +menu.cpu.nano.atmega168.upload.maximum_size=14336 +menu.cpu.nano.atmega168.upload.speed=19200 + +menu.cpu.nano.atmega168.bootloader.low_fuses=0xff +menu.cpu.nano.atmega168.bootloader.high_fuses=0xdd +menu.cpu.nano.atmega168.bootloader.extended_fuses=0x00 +menu.cpu.nano.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex + +menu.cpu.nano.atmega168.build.mcu=atmega168 + ############################################################## mega2560.name=Arduino Mega 2560 or Mega ADK mega2560.cpu=2560 or ADK -mega2560.container=Arduino Mega mega2560.upload.tool=avrdude mega2560.upload.protocol=wiring @@ -141,7 +131,6 @@ mega2560.build.variant=mega mega.name=Arduino Mega (ATmega1280) mega.cpu=ATmega1280 -mega.container=Arduino Mega mega.upload.tool=avrdude mega.upload.protocol=arduino @@ -190,52 +179,44 @@ leonardo.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} ############################################################## -mini328.name=Arduino Mini w/ ATmega328 -mini328.cpu=ATmega328 -mini328.container=Arduino Mini - -mini328.upload.tool=avrdude -mini328.upload.protocol=arduino -mini328.upload.maximum_size=28672 -mini328.upload.speed=115200 - -mini328.bootloader.tool=avrdude -mini328.bootloader.low_fuses=0xff -mini328.bootloader.high_fuses=0xd8 -mini328.bootloader.extended_fuses=0x05 -mini328.bootloader.file=optiboot/optiboot_atmega328-Mini.hex -mini328.bootloader.unlock_bits=0x3F -mini328.bootloader.lock_bits=0x0F - -mini328.build.mcu=atmega328p -mini328.build.f_cpu=16000000L -mini328.build.core=arduino -mini328.build.variant=eightanaloginputs - -############################################################## - -mini.name=Arduino Mini w/ ATmega168 -mini.cpu=ATmega168 -mini.container=Arduino Mini +mini.name=Arduino Mini mini.upload.tool=avrdude mini.upload.protocol=arduino -mini.upload.maximum_size=14336 -mini.upload.speed=19200 mini.bootloader.tool=avrdude mini.bootloader.low_fuses=0xff -mini.bootloader.high_fuses=0xdd -mini.bootloader.extended_fuses=0x00 -mini.bootloader.file=atmega/ATmegaBOOT_168_ng.hex mini.bootloader.unlock_bits=0x3F mini.bootloader.lock_bits=0x0F -mini.build.mcu=atmega168 mini.build.f_cpu=16000000L mini.build.core=arduino mini.build.variant=eightanaloginputs +## Arduino Mini w/ ATmega328 +menu.cpu.mini.atmega328=ATmega328 + +menu.cpu.mini.atmega328.upload.maximum_size=28672 +menu.cpu.mini.atmega328.upload.speed=115200 + +menu.cpu.mini.atmega328.bootloader.high_fuses=0xd8 +menu.cpu.mini.atmega328.bootloader.extended_fuses=0x05 +menu.cpu.mini.atmega328.bootloader.file=optiboot/optiboot_atmega328-Mini.hex + +menu.cpu.mini.atmega328.build.mcu=atmega328p + +## Arduino Mini w/ ATmega168 +menu.cpu.mini.atmega168=ATmega168 + +menu.cpu.mini.atmega168.upload.maximum_size=14336 +menu.cpu.mini.atmega168.upload.speed=19200 + +menu.cpu.mini.atmega168.bootloader.high_fuses=0xdd +menu.cpu.mini.atmega168.bootloader.extended_fuses=0x00 +menu.cpu.mini.atmega168.bootloader.file=atmega/ATmegaBOOT_168_ng.hex + +menu.cpu.mini.atmega168.build.mcu=atmega168 + ############################################################## ethernet.name=Arduino Ethernet @@ -282,241 +263,189 @@ fio.build.variant=eightanaloginputs ############################################################## -bt328.name=Arduino BT w/ ATmega328 -bt328.cpu=ATmega328 -bt328.container=Arduino BT - -bt328.upload.tool=avrdude -bt328.upload.protocol=arduino -bt328.upload.maximum_size=28672 -bt328.upload.speed=19200 -bt328.upload.disable_flushing=true - -bt328.bootloader.tool=avrdude -bt328.bootloader.low_fuses=0xff -bt328.bootloader.high_fuses=0xd8 -bt328.bootloader.extended_fuses=0x05 -bt328.bootloader.file=bt/ATmegaBOOT_168_atmega328_bt.hex -bt328.bootloader.unlock_bits=0x3F -bt328.bootloader.lock_bits=0x0F - -bt328.build.mcu=atmega328p -bt328.build.f_cpu=16000000L -bt328.build.core=arduino -bt328.build.variant=eightanaloginputs - -############################################################## - -bt.name=Arduino BT w/ ATmega168 -bt.cpu=ATmega168 -bt.container=Arduino BT +bt.name=Arduino BT bt.upload.tool=avrdude bt.upload.protocol=arduino -bt.upload.maximum_size=14336 bt.upload.speed=19200 bt.upload.disable_flushing=true bt.bootloader.tool=avrdude bt.bootloader.low_fuses=0xff -bt.bootloader.high_fuses=0xdd -bt.bootloader.extended_fuses=0x00 -bt.bootloader.file=bt/ATmegaBOOT_168.hex bt.bootloader.unlock_bits=0x3F bt.bootloader.lock_bits=0x0F -bt.build.mcu=atmega168 bt.build.f_cpu=16000000L bt.build.core=arduino bt.build.variant=eightanaloginputs -############################################################## +## Arduino BT w/ ATmega328 +menu.cpu.bt.atmega328=ATmega328 +menu.cpu.bt.atmega328.upload.maximum_size=28672 -lilypad328.name=LilyPad Arduino w/ ATmega328 -lilypad328.cpu=ATmega328 -lilypad328.container=LilyPad Arduino +menu.cpu.bt.atmega328.bootloader.high_fuses=0xd8 +menu.cpu.bt.atmega328.bootloader.extended_fuses=0x05 +menu.cpu.bt.atmega328.bootloader.file=bt/ATmegaBOOT_168_atmega328_bt.hex -lilypad328.upload.tool=avrdude -lilypad328.upload.protocol=arduino -lilypad328.upload.maximum_size=30720 -lilypad328.upload.speed=57600 +menu.cpu.bt.atmega328.build.mcu=atmega328p -lilypad328.bootloader.tool=avrdude -lilypad328.bootloader.low_fuses=0xFF -lilypad328.bootloader.high_fuses=0xDA -lilypad328.bootloader.extended_fuses=0x05 -lilypad328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex -lilypad328.bootloader.unlock_bits=0x3F -lilypad328.bootloader.lock_bits=0x0F +## Arduino BT w/ ATmega168 +menu.cpu.bt.atmega168=ATmega168 +menu.cpu.bt.atmega168.upload.maximum_size=14336 -lilypad328.build.mcu=atmega328p -lilypad328.build.f_cpu=8000000L -lilypad328.build.core=arduino -lilypad328.build.variant=standard +menu.cpu.bt.atmega168.bootloader.high_fuses=0xdd +menu.cpu.bt.atmega168.bootloader.extended_fuses=0x00 +menu.cpu.bt.atmega168.bootloader.file=bt/ATmegaBOOT_168.hex + +menu.cpu.bt.atmega168.build.mcu=atmega168 ############################################################## -lilypad.name=LilyPad Arduino w/ ATmega168 -lilypad.cpu=ATmega168 -lilypad.container=LilyPad Arduino +lilypad.name=LilyPad Arduino lilypad.upload.tool=avrdude lilypad.upload.protocol=arduino -lilypad.upload.maximum_size=14336 -lilypad.upload.speed=19200 lilypad.bootloader.tool=avrdude -lilypad.bootloader.low_fuses=0xe2 -lilypad.bootloader.high_fuses=0xdd -lilypad.bootloader.extended_fuses=0x00 -lilypad.bootloader.file=lilypad/LilyPadBOOT_168.hex lilypad.bootloader.unlock_bits=0x3F lilypad.bootloader.lock_bits=0x0F -lilypad.build.mcu=atmega168 lilypad.build.f_cpu=8000000L lilypad.build.core=arduino lilypad.build.variant=standard -############################################################## +## LilyPad Arduino w/ ATmega328 +menu.cpu.lilypad.atmega328=ATmega328 -pro5v328.name=Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328 -pro5v328.cpu=ATmega328 (5V, 16 MHz) -pro5v328.container=Arduino Pro or Pro Mini +menu.cpu.lilypad.atmega328.upload.maximum_size=30720 +menu.cpu.lilypad.atmega328.upload.speed=57600 -pro5v328.upload.tool=avrdude -pro5v328.upload.protocol=arduino -pro5v328.upload.maximum_size=30720 -pro5v328.upload.speed=57600 +menu.cpu.lilypad.atmega328.bootloader.low_fuses=0xFF +menu.cpu.lilypad.atmega328.bootloader.high_fuses=0xDA +menu.cpu.lilypad.atmega328.bootloader.extended_fuses=0x05 +menu.cpu.lilypad.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex -pro5v328.bootloader.tool=avrdude -pro5v328.bootloader.low_fuses=0xFF -pro5v328.bootloader.high_fuses=0xDA -pro5v328.bootloader.extended_fuses=0x05 -pro5v328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex -pro5v328.bootloader.unlock_bits=0x3F -pro5v328.bootloader.lock_bits=0x0F +menu.cpu.lilypad.atmega328.build.mcu=atmega328p -pro5v328.build.mcu=atmega328p -pro5v328.build.f_cpu=16000000L -pro5v328.build.core=arduino -pro5v328.build.variant=standard +## LilyPad Arduino w/ ATmega168 +menu.cpu.lilypad.atmega168=ATmega168 -############################################################## - -pro5v.name=Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega168 -pro5v.cpu=ATmega168 (5V, 16 MHz) -pro5v.container=Arduino Pro or Pro Mini - -pro5v.upload.tool=avrdude -pro5v.upload.protocol=arduino -pro5v.upload.maximum_size=14336 -pro5v.upload.speed=19200 - -pro5v.bootloader.tool=avrdude -pro5v.bootloader.low_fuses=0xff -pro5v.bootloader.high_fuses=0xdd -pro5v.bootloader.extended_fuses=0x00 -pro5v.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex -pro5v.bootloader.unlock_bits=0x3F -pro5v.bootloader.lock_bits=0x0F - -pro5v.build.mcu=atmega168 -pro5v.build.f_cpu=16000000L -pro5v.build.core=arduino -pro5v.build.variant=standard - -############################################################## - -pro328.name=Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328 -pro328.cpu=ATmega328 (3.3V, 8 MHz) -pro328.container=Arduino Pro or Pro Mini +menu.cpu.lilypad.atmega168.upload.maximum_size=14336 +menu.cpu.lilypad.atmega168.upload.speed=19200 -pro328.upload.tool=avrdude -pro328.upload.protocol=arduino -pro328.upload.maximum_size=30720 -pro328.upload.speed=57600 +menu.cpu.lilypad.atmega168.bootloader.low_fuses=0xe2 +menu.cpu.lilypad.atmega168.bootloader.high_fuses=0xdd +menu.cpu.lilypad.atmega168.bootloader.extended_fuses=0x00 +menu.cpu.lilypad.atmega168.bootloader.file=lilypad/LilyPadBOOT_168.hex -pro328.bootloader.tool=avrdude -pro328.bootloader.low_fuses=0xFF -pro328.bootloader.high_fuses=0xDA -pro328.bootloader.extended_fuses=0x05 -pro328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex -pro328.bootloader.unlock_bits=0x3F -pro328.bootloader.lock_bits=0x0F - -pro328.build.mcu=atmega328p -pro328.build.f_cpu=8000000L -pro328.build.core=arduino -pro328.build.variant=standard +menu.cpu.lilypad.atmega168.build.mcu=atmega168 ############################################################## -pro.name=Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega168 -pro.cpu=ATmega168 (3.3V, 8 MHz) -pro.container=Arduino Pro or Pro Mini +pro.name=Arduino Pro or Pro Mini pro.upload.tool=avrdude pro.upload.protocol=arduino -pro.upload.maximum_size=14336 -pro.upload.speed=19200 pro.bootloader.tool=avrdude -pro.bootloader.low_fuses=0xc6 -pro.bootloader.high_fuses=0xdd -pro.bootloader.extended_fuses=0x00 -pro.bootloader.file=atmega/ATmegaBOOT_168_pro_8MHz.hex pro.bootloader.unlock_bits=0x3F pro.bootloader.lock_bits=0x0F -pro.build.mcu=atmega168 -pro.build.f_cpu=8000000L pro.build.core=arduino pro.build.variant=standard -############################################################## +## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega328 +menu.cpu.pro.16MHzatmega328=ATmega328 (5V, 16 MHz) + +menu.cpu.pro.16MHzatmega328.upload.maximum_size=30720 +menu.cpu.pro.16MHzatmega328.upload.speed=57600 + +menu.cpu.pro.16MHzatmega328.bootloader.low_fuses=0xFF +menu.cpu.pro.16MHzatmega328.bootloader.high_fuses=0xDA +menu.cpu.pro.16MHzatmega328.bootloader.extended_fuses=0x05 +menu.cpu.pro.16MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex + +menu.cpu.pro.16MHzatmega328.build.mcu=atmega328p +menu.cpu.pro.16MHzatmega328.build.f_cpu=16000000L + +## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega328 +menu.cpu.pro.8MHzatmega328=ATmega328 (3.3V, 8 MHz) + +menu.cpu.pro.8MHzatmega328.upload.maximum_size=30720 +menu.cpu.pro.8MHzatmega328.upload.speed=57600 + +menu.cpu.pro.8MHzatmega328.bootloader.low_fuses=0xFF +menu.cpu.pro.8MHzatmega328.bootloader.high_fuses=0xDA +menu.cpu.pro.8MHzatmega328.bootloader.extended_fuses=0x05 +menu.cpu.pro.8MHzatmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328_pro_8MHz.hex -atmega168.name=Arduino NG or older w/ ATmega168 -atmega168.cpu=ATmega168 -atmega168.container=Arduino NG or older +menu.cpu.pro.8MHzatmega328.build.mcu=atmega328p +menu.cpu.pro.8MHzatmega328.build.f_cpu=8000000L -atmega168.upload.tool=avrdude -atmega168.upload.protocol=arduino -atmega168.upload.maximum_size=14336 -atmega168.upload.speed=19200 +## Arduino Pro or Pro Mini (5V, 16 MHz) w/ ATmega168 +menu.cpu.pro.16MHzatmega168=ATmega168 (5V, 16 MHz) -atmega168.bootloader.tool=avrdude -atmega168.bootloader.low_fuses=0xff -atmega168.bootloader.high_fuses=0xdd -atmega168.bootloader.extended_fuses=0x00 -atmega168.bootloader.file=atmega/ATmegaBOOT_168_ng.hex -atmega168.bootloader.unlock_bits=0x3F -atmega168.bootloader.lock_bits=0x0F +menu.cpu.pro.16MHzatmega168.upload.maximum_size=14336 +menu.cpu.pro.16MHzatmega168.upload.speed=19200 -atmega168.build.mcu=atmega168 -atmega168.build.f_cpu=16000000L -atmega168.build.core=arduino -atmega168.build.variant=standard +menu.cpu.pro.16MHzatmega168.bootloader.low_fuses=0xff +menu.cpu.pro.16MHzatmega168.bootloader.high_fuses=0xdd +menu.cpu.pro.16MHzatmega168.bootloader.extended_fuses=0x00 +menu.cpu.pro.16MHzatmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex + +menu.cpu.pro.16MHzatmega168.build.mcu=atmega168 +menu.cpu.pro.16MHzatmega168.build.f_cpu=16000000L + +## Arduino Pro or Pro Mini (3.3V, 8 MHz) w/ ATmega168 +menu.cpu.pro.8MHzatmega168=ATmega168 (3.3V, 8 MHz) + +menu.cpu.pro.8MHzatmega168.upload.maximum_size=14336 +menu.cpu.pro.8MHzatmega168.upload.speed=19200 + +menu.cpu.pro.8MHzatmega168.bootloader.low_fuses=0xc6 +menu.cpu.pro.8MHzatmega168.bootloader.high_fuses=0xdd +menu.cpu.pro.8MHzatmega168.bootloader.extended_fuses=0x00 +menu.cpu.pro.8MHzatmega168.bootloader.file=atmega/ATmegaBOOT_168_pro_8MHz.hex + +menu.cpu.pro.8MHzatmega168.build.mcu=atmega168 +menu.cpu.pro.8MHzatmega168.build.f_cpu=8000000L ############################################################## -atmega8.name=Arduino NG or older w/ ATmega8 -atmega8.cpu=ATmega8 -atmega8.container=Arduino NG or older - -atmega8.upload.tool=avrdude -atmega8.upload.protocol=arduino -atmega8.upload.maximum_size=7168 -atmega8.upload.speed=19200 - -atmega8.bootloader.tool=avrdude -atmega8.bootloader.low_fuses=0xdf -atmega8.bootloader.high_fuses=0xca -atmega8.bootloader.file=atmega8/ATmegaBOOT.hex -atmega8.bootloader.unlock_bits=0x3F -atmega8.bootloader.lock_bits=0x0F - -atmega8.build.mcu=atmega8 -atmega8.build.f_cpu=16000000L -atmega8.build.core=arduino -atmega8.build.variant=standard +atmegang.name=Arduino NG or older + +atmegang.upload.tool=avrdude +atmegang.upload.protocol=arduino +atmegang.upload.speed=19200 + +atmegang.bootloader.tool=avrdude +atmegang.bootloader.unlock_bits=0x3F +atmegang.bootloader.lock_bits=0x0F + +atmegang.build.mcu=atmegang +atmegang.build.f_cpu=16000000L +atmegang.build.core=arduino +atmegang.build.variant=standard + +## Arduino NG or older w/ ATmega168 +menu.cpu.atmegang.atmega168=ATmega168 + +menu.cpu.atmegang.atmega168.upload.maximum_size=14336 + +menu.cpu.atmegang.atmega168.bootloader.low_fuses=0xff +menu.cpu.atmegang.atmega168.bootloader.high_fuses=0xdd +menu.cpu.atmegang.atmega168.bootloader.extended_fuses=0x00 +menu.cpu.atmegang.atmega168.bootloader.file=atmega/ATmegaBOOT_168_ng.hex + +menu.cpu.atmegang.atmega168.build.mcu=atmega168 + +## Arduino NG or older w/ ATmega8 +menu.cpu.atmegang.atmega8=ATmega8 + +menu.cpu.atmegang.atmega8.upload.maximum_size=7168 + +menu.cpu.atmegang.atmega8.bootloader.low_fuses=0xdf +menu.cpu.atmegang.atmega8.bootloader.high_fuses=0xca +menu.cpu.atmegang.atmega8.bootloader.file=atmegang/ATmegaBOOT.hex + +menu.cpu.atmegang.atmega8.build.mcu=atmega8 \ No newline at end of file