diff --git a/Phase Measurement Prototype.ipynb b/Phase Measurement Prototype.ipynb
index df68f94..10c7209 100644
--- a/Phase Measurement Prototype.ipynb
+++ b/Phase Measurement Prototype.ipynb
@@ -26,13 +26,13 @@
},
{
"cell_type": "code",
- "execution_count": 255,
+ "execution_count": 275,
"metadata": {
"scrolled": false
},
"outputs": [],
"source": [
- "fs = 1e3 # Hz\n",
+ "fs = 1000 # Hz\n",
"ff = 50 # Hz\n",
"duration = 60 # seconds\n",
"# test_data = rocof_test_data.sample_waveform(rocof_test_data.test_close_interharmonics_and_flicker(),\n",
@@ -64,13 +64,13 @@
},
{
"cell_type": "code",
- "execution_count": 256,
+ "execution_count": 276,
"metadata": {},
"outputs": [],
"source": [
"analysis_periods = 10\n",
"window_len = fs * analysis_periods/ff\n",
- "nfft_factor = 1\n",
+ "nfft_factor = 4\n",
"sigma = window_len/8 # samples\n",
"\n",
"ffts = []\n",
@@ -86,7 +86,7 @@
},
{
"cell_type": "code",
- "execution_count": 257,
+ "execution_count": 277,
"metadata": {
"scrolled": false
},
@@ -874,7 +874,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
@@ -901,7 +901,7 @@
},
{
"cell_type": "code",
- "execution_count": 259,
+ "execution_count": 278,
"metadata": {
"scrolled": false
},
@@ -1689,7 +1689,7 @@
{
"data": {
"text/html": [
- "
"
+ "
"
],
"text/plain": [
""
diff --git a/gm_platform/fw/Makefile b/gm_platform/fw/Makefile
new file mode 100644
index 0000000..ea874eb
--- /dev/null
+++ b/gm_platform/fw/Makefile
@@ -0,0 +1,111 @@
+# Megumin LED display firmware
+# Copyright (C) 2018 Sebastian Götte
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+CUBE_PATH ?= $(wildcard ~)/resource/STM32CubeF0
+CMSIS_PATH ?= $(CUBE_PATH)/Drivers/CMSIS
+CMSIS_DEV_PATH ?= $(CMSIS_PATH)/Device/ST/STM32F0xx
+HAL_PATH ?= $(CUBE_PATH)/Drivers/STM32F0xx_HAL_Driver
+
+MAC_ADDR ?= 0xdeadbeef
+
+CC := arm-none-eabi-gcc
+LD := arm-none-eabi-ld
+OBJCOPY := arm-none-eabi-objcopy
+OBJDUMP := arm-none-eabi-objdump
+SIZE := arm-none-eabi-size
+
+CFLAGS = -g -Wall -Wextra -std=gnu11 -O0 -fdump-rtl-expand
+CFLAGS += -mlittle-endian -mcpu=cortex-m0 -march=armv6-m -mthumb
+#CFLAGS += -ffunction-sections -fdata-sections
+LDFLAGS = -nostartfiles
+#LDFLAGS += -specs=rdimon.specs -DSEMIHOSTING
+LDFLAGS += -Wl,-Map=main.map -nostdlib
+#LDFLAGS += -Wl,--gc-sections
+LIBS = -lgcc
+#LIBS += -lrdimon
+
+# Technically we're using an STM32F030F4, but apart from the TSSOP20 package that one is largely identical to the
+# STM32F030*6 and there is no separate device header provided for it, so we're faking a *6 device here. This is
+# even documented in stm32f0xx.h. Thanks ST!
+CFLAGS += -DSTM32F030x6 -DHSE_VALUE=8000000
+
+LDFLAGS += -Tstm32_flash.ld
+CFLAGS += -I$(CMSIS_DEV_PATH)/Include -I$(CMSIS_PATH)/Include -I$(HAL_PATH)/Inc -Iconfig -Wno-unused -I../common
+LDFLAGS += -L$(CMSIS_PATH)/Lib/GCC -larm_cortexM0l_math
+
+###################################################
+
+.PHONY: program clean
+
+all: main.elf
+
+.clang:
+ echo flags = $(CFLAGS) > .clang
+
+cmsis_exports.c: $(CMSIS_DEV_PATH)/Include/stm32f030x6.h $(CMSIS_PATH)/Include/core_cm0.h
+ python3 tools/gen_cmsis_exports.py $^ > $@
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) -o $@ $^
+# $(CC) -E $(CFLAGS) -o $(@:.o=.pp) $^
+
+%.o: %.s
+ $(CC) -c $(CFLAGS) -o $@ $^
+# $(CC) -E $(CFLAGS) -o $(@:.o=.pp) $^
+
+%.dot: %.elf
+ r2 -a arm -qc 'aa;agC' $< 2>/dev/null >$@
+
+sources.tar.xz: main.c Makefile
+ tar -caf $@ $^
+
+# don't ask...
+sources.tar.xz.zip: sources.tar.xz
+ zip $@ $^
+
+sources.c: sources.tar.xz.zip
+ xxd -i $< | head -n -1 | sed 's/=/__attribute__((section(".source_tarball"))) =/' > $@
+
+main.elf: main.c adc.c serial.c cobs.c startup_stm32f030x6.s system_stm32f0xx.c $(HAL_PATH)/Src/stm32f0xx_ll_utils.c base.c cmsis_exports.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $^ $(LIBS)
+ $(OBJCOPY) -O ihex $@ $(@:.elf=.hex)
+ $(OBJCOPY) -O binary $@ $(@:.elf=.bin)
+ $(OBJDUMP) -St $@ >$(@:.elf=.lst)
+ $(SIZE) $@
+
+program: main.elf openocd.cfg
+ openocd -f openocd.cfg -c "program $< verify reset exit"
+
+8b10b_test_encode: 8b10b_test_encode.c 8b10b.c
+ gcc -o $@ $^
+
+8b10b_test_decode: 8b10b_test_decode.c 8b10b.c
+ gcc -o $@ $^
+
+protocol_test: protocol.c protocol_test.c
+ gcc -o $@ -O0 -Wall -Wextra -g -I../common $^
+
+clean:
+ rm -f **.o
+ rm -f main.elf main.hex main.bin main.map main.lst
+ rm -f **.expand
+ rm -f cmsis_exports.c
+ rm -f sources.tar.xz
+ rm -f sources.tar.xz.zip
+ rm -f sources.c
+ rm -f *.dot
+ rm -f protocol_test
+
diff --git a/gm_platform/fw/Scope.ipynb b/gm_platform/fw/Scope.ipynb
new file mode 100644
index 0000000..1022e56
--- /dev/null
+++ b/gm_platform/fw/Scope.ipynb
@@ -0,0 +1,906 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 14,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "from matplotlib import pyplot as plt\n",
+ "%matplotlib notebook\n",
+ "import numpy as np\n",
+ "import struct\n",
+ "import math"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 33,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "def plot_data(offx=0, end=-1, signed=False, channels=1):\n",
+ " with open('/tmp/scope_dump.bin', 'rb') as f:\n",
+ " raw_data = f.read()\n",
+ " data = struct.unpack(f'<{len(raw_data)//2}{\"h\" if signed else \"H\"}', raw_data)\n",
+ " \n",
+ " fig, axs = plt.subplots(channels*2, 1, squeeze=False, sharex=True, figsize=(10, 5))\n",
+ " axs = axs.flatten()\n",
+ " for i, (ax_t, ax_f) in enumerate(zip(axs[0::2], axs[1::2])):\n",
+ " le_slice = data[offx:][:end][i::channels]\n",
+ " ax_t.plot(np.linspace(0, len(le_slice)/1000, len(le_slice)),\n",
+ " [math.nan if x==-255 else x for x in le_slice])\n",
+ " ax_t.grid() \n",
+ " \n",
+ " ax_f.specgram(le_slice, Fs=1000)\n",
+ " ax_f.grid()\n",
+ " \n",
+ " return data"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 40,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " fig.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\n",
+ " titlebar.append(titletext)\n",
+ " this.root.append(titlebar);\n",
+ " this.header = titletext[0];\n",
+ "}\n",
+ "\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_canvas = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var canvas_div = $('');\n",
+ "\n",
+ " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
+ "\n",
+ " function canvas_keyboard_event(event) {\n",
+ " return fig.key_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
+ " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
+ " this.canvas_div = canvas_div\n",
+ " this._canvas_extra_style(canvas_div)\n",
+ " this.root.append(canvas_div);\n",
+ "\n",
+ " var canvas = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items) {\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) {\n",
+ " // put a spacer in here.\n",
+ " continue;\n",
+ " }\n",
+ " var button = $('');\n",
+ " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
+ " 'ui-button-icon-only');\n",
+ " button.attr('role', 'button');\n",
+ " button.attr('aria-disabled', 'false');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ "\n",
+ " var icon_img = $('');\n",
+ " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
+ " icon_img.addClass(image);\n",
+ " icon_img.addClass('ui-corner-all');\n",
+ "\n",
+ " var tooltip_span = $('');\n",
+ " tooltip_span.addClass('ui-button-text');\n",
+ " tooltip_span.html(tooltip);\n",
+ "\n",
+ " button.append(icon_img);\n",
+ " button.append(tooltip_span);\n",
+ "\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " var fmt_picker_span = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\n",
+ " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
+ " fmt_picker_span.append(fmt_picker);\n",
+ " nav_element.append(fmt_picker_span);\n",
+ " this.format_dropdown = fmt_picker[0];\n",
+ "\n",
+ " for (var ind in mpl.extensions) {\n",
+ " var fmt = mpl.extensions[ind];\n",
+ " var option = $(\n",
+ " '', {selected: fmt === mpl.default_extension}).html(fmt);\n",
+ " fmt_picker.append(option)\n",
+ " }\n",
+ "\n",
+ " // Add hover states to the ui-buttons\n",
+ " $( \".ui-button\" ).hover(\n",
+ " function() { $(this).addClass(\"ui-state-hover\");},\n",
+ " function() { $(this).removeClass(\"ui-state-hover\");}\n",
+ " );\n",
+ "\n",
+ " var status_bar = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('
');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '
';\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Tell IPython that the notebook contents must change.\n",
+ " IPython.notebook.set_dirty(true);\n",
+ " this.send_message(\"ack\", {});\n",
+ " var fig = this;\n",
+ " // Wait a second, then push the new image to the DOM so\n",
+ " // that it is saved nicely (might be nice to debounce this).\n",
+ " setTimeout(function () { fig.push_to_output() }, 1000);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items){\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) { continue; };\n",
+ "\n",
+ " var button = $('');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " // Add the status bar.\n",
+ " var status_bar = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " event.shiftKey = false;\n",
+ " // Send a \"J\" for go to next cell\n",
+ " event.which = 74;\n",
+ " event.keyCode = 74;\n",
+ " manager.command_mode();\n",
+ " manager.handle_keydown(event);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; i= 3 moved mimebundle to data attribute of output\n",
+ " data = data.data;\n",
+ " }\n",
+ " if (data['text/html'] == html_output) {\n",
+ " return [cell, data, j];\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "// Register the function which deals with the matplotlib target/channel.\n",
+ "// The kernel may be null if the page has been refreshed.\n",
+ "if (IPython.notebook.kernel != null) {\n",
+ " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
+ "}\n"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "data = plot_data(offx=4, signed=True, channels=1)\n",
+ "#print(''.join(str(x) for x in data[4:][3::4]))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 32,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "ename": "FileNotFoundError",
+ "evalue": "[Errno 2] No such file or directory: '/tmp/foo'",
+ "output_type": "error",
+ "traceback": [
+ "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
+ "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0mplotdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0msum\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvals\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m+\u001b[0m\u001b[0mdelta\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m/\u001b[0m\u001b[0mdelta\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mlen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mvals\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdelta\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0mplt\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mplot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mplotdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0mplot_avg\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
+ "\u001b[0;32m\u001b[0m in \u001b[0;36mplot_avg\u001b[0;34m()\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mplot_avg\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mwith\u001b[0m \u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'/tmp/foo'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'rb'\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 5\u001b[0m \u001b[0mvals\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfrombuffer\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdtype\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m'uint16'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n",
+ "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/tmp/foo'"
+ ]
+ }
+ ],
+ "source": [
+ "import random, struct, numpy as np\n",
+ "\n",
+ "def plot_avg():\n",
+ " with open('/tmp/foo', 'rb') as f:\n",
+ " vals = np.frombuffer(f.read(), dtype='uint16')\n",
+ " \n",
+ " vals = vals.copy()\n",
+ " idx = 1\n",
+ " vals &= 1<>= idx\n",
+ " \n",
+ " delta = 10000\n",
+ " plotdata = [sum(vals[i:i+delta])/delta for i in range(0, len(vals), delta)]\n",
+ " plt.plot(plotdata)\n",
+ "plot_avg()"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}
diff --git a/gm_platform/fw/adc.c b/gm_platform/fw/adc.c
new file mode 100644
index 0000000..547089b
--- /dev/null
+++ b/gm_platform/fw/adc.c
@@ -0,0 +1,125 @@
+/* Megumin LED display firmware
+ * Copyright (C) 2018 Sebastian Götte
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "adc.h"
+
+#include
+#include
+
+volatile uint16_t adc_buf[ADC_BUFSIZE];
+
+static void adc_dma_init(int burstlen);
+static void adc_timer_init(int psc, int ivl);
+
+
+/* Mode that can be used for debugging */
+void adc_configure_scope_mode(int sampling_interval_ns) {
+ adc_dma_init(sizeof(adc_buf)/sizeof(adc_buf[0]));
+
+ /* Clock from PCLK/4 instead of the internal exclusive high-speed RC oscillator. */
+ ADC1->CFGR2 = (2< total conversion time 38.5us*/
+ ADC1->SMPR = (7<CFGR1 = ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG | (2<CHSELR = ADC_CHSELR_CHSEL2;
+ /* Perform self-calibration */
+ ADC1->CR |= ADC_CR_ADCAL;
+ while (ADC1->CR & ADC_CR_ADCAL)
+ ;
+ /* Enable conversion */
+ ADC1->CR |= ADC_CR_ADEN;
+ ADC1->CR |= ADC_CR_ADSTART;
+
+ /* An ADC conversion takes 1.1667us, so to be sure we don't get data overruns we limit sampling to every 1.5us.
+ Since we don't have a spare PLL to generate the ADC sample clock and re-configuring the system clock just for this
+ would be overkill we round to 250ns increments. The minimum sampling rate is about 60Hz due to timer resolution. */
+ int cycles = sampling_interval_ns > 1500 ? sampling_interval_ns/250 : 6;
+ if (cycles > 0xffff)
+ cycles = 0xffff;
+ adc_timer_init(12/*250ns/tick*/, cycles);
+}
+
+/* FIXME figure out the proper place to configure this. */
+#define ADC_TIMER_INTERVAL_US 20
+
+static void adc_dma_init(int burstlen) {
+ /* Configure DMA 1 Channel 1 to get rid of all the data */
+ DMA1_Channel1->CPAR = (unsigned int)&ADC1->DR;
+ DMA1_Channel1->CMAR = (unsigned int)&adc_buf;
+ DMA1_Channel1->CNDTR = burstlen;
+ DMA1_Channel1->CCR = (0<CCR |=
+ DMA_CCR_CIRC /* circular mode so we can leave it running indefinitely */
+ | (1<CCR |= DMA_CCR_EN; /* Enable channel */
+}
+
+static void adc_timer_init(int psc, int ivl) {
+ TIM1->BDTR = TIM_BDTR_MOE; /* MOE is needed even though we only "output" a chip-internal signal TODO: Verify this. */
+ TIM1->CCMR2 = (6<CCER = TIM_CCER_CC4E; /* Enable capture/compare unit 4 connected to ADC */
+ TIM1->CCR4 = 1; /* Trigger at start of timer cycle */
+ /* Set prescaler and interval */
+ TIM1->PSC = psc-1;
+ TIM1->ARR = ivl-1;
+ /* Preload all values */
+ TIM1->EGR |= TIM_EGR_UG;
+ TIM1->CR1 = TIM_CR1_ARPE;
+ /* And... go! */
+ TIM1->CR1 |= TIM_CR1_CEN;
+}
+
+/* This acts as a no-op that provides a convenient point to set a breakpoint for the debug scope logic */
+static void gdb_dump(void) {
+}
+
+void DMA1_Channel1_IRQHandler(void) {
+ /* Clear the interrupt flag */
+ DMA1->IFCR |= DMA_IFCR_CGIF1;
+ gdb_dump();
+
+ /*
+ static int debug_buf_pos = 0;
+ if (st->sync) {
+ if (debug_buf_pos < NCH) {
+ debug_buf_pos = NCH;
+ } else {
+ adc_buf[debug_buf_pos++] = symbol;
+
+ if (debug_buf_pos >= sizeof(adc_buf)/sizeof(adc_buf[0])) {
+ debug_buf_pos = 0;
+ st->sync = 0;
+ gdb_dump();
+ for (int i=0; i
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __ADC_H__
+#define __ADC_H__
+
+#include "global.h"
+
+extern volatile uint16_t adc_buf[ADC_BUFSIZE];
+
+void adc_init(void);
+void adc_configure_scope_mode(int sampling_interval_ns);
+
+#endif/*__ADC_H__*/
diff --git a/gm_platform/fw/base.c b/gm_platform/fw/base.c
new file mode 100644
index 0000000..8e7c03b
--- /dev/null
+++ b/gm_platform/fw/base.c
@@ -0,0 +1,25 @@
+
+#include
+#include
+
+int __errno = 0;
+void *_impure_ptr = NULL;
+
+void __sinit(void) {
+}
+
+void *memset(void *s, int c, size_t n) {
+ char *end = (char *)s + n;
+ for (char *p = (char *)s; p < end; p++)
+ *p = (char)c;
+ return s;
+}
+
+size_t strlen(const char *s) {
+ const char *start = s;
+ while (*s++);
+ return s - start - 1;
+}
+
+void __assert_func(bool value) {
+}
diff --git a/gm_platform/fw/cmsis_exports.c b/gm_platform/fw/cmsis_exports.c
new file mode 100644
index 0000000..39874b5
--- /dev/null
+++ b/gm_platform/fw/cmsis_exports.c
@@ -0,0 +1,48 @@
+#ifndef __GENERATED_CMSIS_HEADER_EXPORTS__
+#define __GENERATED_CMSIS_HEADER_EXPORTS__
+
+#include
+
+/* stm32f030x6.h */
+TIM_TypeDef *tim3 = TIM3;
+TIM_TypeDef *tim14 = TIM14;
+RTC_TypeDef *rtc = RTC;
+WWDG_TypeDef *wwdg = WWDG;
+IWDG_TypeDef *iwdg = IWDG;
+I2C_TypeDef *i2c1 = I2C1;
+PWR_TypeDef *pwr = PWR;
+SYSCFG_TypeDef *syscfg = SYSCFG;
+EXTI_TypeDef *exti = EXTI;
+ADC_TypeDef *adc1 = ADC1;
+ADC_Common_TypeDef *adc1_common = ADC1_COMMON;
+ADC_Common_TypeDef *adc = ADC;
+TIM_TypeDef *tim1 = TIM1;
+SPI_TypeDef *spi1 = SPI1;
+USART_TypeDef *usart1 = USART1;
+TIM_TypeDef *tim16 = TIM16;
+TIM_TypeDef *tim17 = TIM17;
+DBGMCU_TypeDef *dbgmcu = DBGMCU;
+DMA_TypeDef *dma1 = DMA1;
+DMA_Channel_TypeDef *dma1_channel1 = DMA1_Channel1;
+DMA_Channel_TypeDef *dma1_channel2 = DMA1_Channel2;
+DMA_Channel_TypeDef *dma1_channel3 = DMA1_Channel3;
+DMA_Channel_TypeDef *dma1_channel4 = DMA1_Channel4;
+DMA_Channel_TypeDef *dma1_channel5 = DMA1_Channel5;
+FLASH_TypeDef *flash = FLASH;
+OB_TypeDef *ob = OB;
+RCC_TypeDef *rcc = RCC;
+CRC_TypeDef *crc = CRC;
+GPIO_TypeDef *gpioa = GPIOA;
+GPIO_TypeDef *gpiob = GPIOB;
+GPIO_TypeDef *gpioc = GPIOC;
+GPIO_TypeDef *gpiod = GPIOD;
+GPIO_TypeDef *gpiof = GPIOF;
+
+#include
+
+/* core_cm0.h */
+SCB_Type *scb = SCB;
+SysTick_Type *systick = SysTick;
+NVIC_Type *nvic = NVIC;
+
+#endif//__GENERATED_CMSIS_HEADER_EXPORTS__
diff --git a/gm_platform/fw/cobs.c b/gm_platform/fw/cobs.c
new file mode 100644
index 0000000..22dcac0
--- /dev/null
+++ b/gm_platform/fw/cobs.c
@@ -0,0 +1,293 @@
+
+#include "serial.h"
+#include "cobs.h"
+
+/*@ requires \valid(dst + (0..dstlen-1));
+ @ requires \valid_read(src + (0..srclen-1));
+ @ requires \separated(dst + (0..dstlen-1), src + (0..srclen-1));
+ @
+ @ behavior valid:
+ @ assumes 0 <= srclen <= 254;
+ @ assumes 0 <= dstlen <= 65535;
+ @ assumes dstlen >= srclen+2;
+ @ assigns dst[0..srclen+1];
+ @ ensures \forall integer i; (0 <= i < srclen && \old(src[i]) != 0) ==> dst[i+1] == src[i];
+ @ ensures \result == srclen+2;
+ @ ensures \forall integer i; 0 <= i <= srclen ==> dst[i] != 0;
+ @ ensures dst[srclen+1] == 0;
+ @
+ @ behavior invalid:
+ @ assumes srclen < 0 || srclen > 254
+ @ || dstlen < 0 || dstlen > 65535
+ @ || dstlen < srclen+2;
+ @ assigns \nothing;
+ @ ensures \result == -1;
+ @
+ @ complete behaviors;
+ @ disjoint behaviors;
+ @*/
+ssize_t cobs_encode(char *dst, size_t dstlen, char *src, size_t srclen) {
+ if (dstlen > 65535 || srclen > 254)
+ return -1;
+ //@ assert 0 <= dstlen <= 65535 && 0 <= srclen <= 254;
+
+ if (dstlen < srclen+2)
+ return -1;
+ //@ assert 0 <= srclen < srclen+2 <= dstlen;
+
+ size_t p = 0;
+ /*@ loop invariant 0 <= p <= srclen+1;
+ @ loop invariant \forall integer i; 0 <= i < p ==> dst[i] != 0;
+ @ loop invariant \forall integer i; 0 < i < p ==> (src[i-1] != 0 ==> dst[i] == src[i-1]);
+ @ loop assigns p, dst[0..srclen+1];
+ @ loop variant srclen-p+1;
+ @*/
+ while (p <= srclen) {
+
+ char val;
+ if (p != 0 && src[p-1] != 0) {
+ val = src[p-1];
+
+ } else {
+ size_t q = p;
+ /*@ loop invariant 0 <= p <= q <= srclen;
+ @ loop invariant \forall integer i; p <= i < q ==> src[i] != 0;
+ @ loop assigns q;
+ @ loop variant srclen-q;
+ @*/
+ while (q < srclen && src[q] != 0)
+ q++;
+ //@ assert q == srclen || src[q] == 0;
+ //@ assert q <= srclen <= 254;
+ val = (char)q-p+1;
+ //@ assert val != 0;
+ }
+
+ dst[p] = val;
+ p++;
+ }
+
+ dst[p] = 0;
+ //@ assert p == srclen+1;
+
+ return srclen+2;
+}
+
+int cobs_encode_usart(char *src, size_t srclen) {
+ if (srclen > 254)
+ return -1;
+ //@ assert 0 <= srclen <= 254;
+
+ size_t p = 0;
+ /*@ loop invariant 0 <= p <= srclen+1;
+ @ loop assigns p;
+ @ loop variant srclen-p+1;
+ @*/
+ while (p <= srclen) {
+
+ char val;
+ if (p != 0 && src[p-1] != 0) {
+ val = src[p-1];
+
+ } else {
+ size_t q = p;
+ /*@ loop invariant 0 <= p <= q <= srclen;
+ @ loop invariant \forall integer i; p <= i < q ==> src[i] != 0;
+ @ loop assigns q;
+ @ loop variant srclen-q;
+ @*/
+ while (q < srclen && src[q] != 0)
+ q++;
+ //@ assert q == srclen || src[q] == 0;
+ //@ assert q <= srclen <= 254;
+ val = (char)q-p+1;
+ //@ assert val != 0;
+ }
+
+ usart_putc(val);
+ p++;
+ }
+
+ usart_putc(0);
+ //@ assert p == srclen+1;
+
+ return 0;
+}
+
+/*@ requires \valid(dst + (0..dstlen-1));
+ @ requires \valid_read(src + (0..srclen-1));
+ @ requires \separated(dst + (0..dstlen-1), src + (0..srclen-1));
+ @
+ @ behavior maybe_valid_frame:
+ @ assumes 1 <= srclen <= dstlen <= 65535;
+ @ assumes \exists integer j; j > 0 && \forall integer i; 0 <= i < j ==> src[i] != 0;
+ @ assumes \exists integer i; 0 <= i < srclen && src[i] == 0;
+ @ assigns dst[0..dstlen-1];
+ @ ensures \result >= 0 || \result == -3;
+ @ ensures \result >= 0 ==> src[\result+1] == 0;
+ @ ensures \result >= 0 ==> (\forall integer i; 0 <= i < \result ==> src[i] != 0);
+ @
+ @ behavior invalid_frame:
+ @ assumes 1 <= srclen <= dstlen <= 65535;
+ @ assumes src[0] == 0 || \forall integer i; 0 <= i < srclen ==> src[i] != 0;
+ @ assigns dst[0..dstlen-1];
+ @ ensures \result == -2;
+ @
+ @ behavior invalid_buffers:
+ @ assumes dstlen < 0 || dstlen > 65535
+ @ || srclen < 1 || srclen > 65535
+ @ || dstlen < srclen;
+ @ assigns \nothing;
+ @ ensures \result == -1;
+ @
+ @ complete behaviors;
+ @ disjoint behaviors;
+ @*/
+ssize_t cobs_decode(char *dst, size_t dstlen, char *src, size_t srclen) {
+ if (dstlen > 65535 || srclen > 65535)
+ return -1;
+
+ if (srclen < 1)
+ return -1;
+
+ if (dstlen < srclen)
+ return -1;
+
+ size_t p = 1;
+ size_t c = (unsigned char)src[0];
+ //@ assert 0 <= c < 256;
+ //@ assert 0 <= c;
+ //@ assert c < 256;
+ if (c == 0)
+ return -2; /* invalid framing. An empty frame would be [...] 00 01 00, not [...] 00 00 */
+ //@ assert c >= 0;
+ //@ assert c != 0;
+ //@ assert c <= 257;
+ //@ assert c > 0;
+ //@ assert c >= 0 && c != 0 ==> c > 0;
+
+ /*@ //loop invariant \forall integer i; 0 <= i <= p ==> (i == srclen || src[i] != 0);
+ @ loop invariant \forall integer i; 1 <= i < p ==> src[i] != 0;
+ @ loop invariant c > 0;
+ @ loop invariant 1 <= p <= srclen <= dstlen <= 65535;
+ @ loop invariant \separated(dst + (0..dstlen-1), src + (0..srclen-1));
+ @ loop invariant \valid_read(src + (0..srclen-1));
+ @ loop invariant \forall integer i; 1 <= i <= srclen ==> \valid(dst + i - 1);
+ @ loop assigns dst[0..dstlen-1], p, c;
+ @ loop variant srclen-p;
+ @*/
+ while (p < srclen && src[p]) {
+ char val;
+ c--;
+
+ //@ assert src[p] != 0;
+ if (c == 0) {
+ c = (unsigned char)src[p];
+ val = 0;
+ } else {
+ val = src[p];
+ }
+
+ //@ assert 0 <= p-1 <= dstlen-1;
+ dst[p-1] = val;
+ p++;
+ }
+
+ if (p == srclen)
+ return -2; /* Invalid framing. The terminating null byte should always be present in the input buffer. */
+
+ if (c != 1)
+ return -3; /* Invalid framing. The skip counter does not hit the end of the frame. */
+
+ //@ assert 0 < p <= srclen <= 65535;
+ //@ assert src[p] == 0;
+ //@ assert \forall integer i; 1 <= i < p ==> src[i] != 0;
+ return p-1;
+}
+
+void cobs_decode_incremental_initialize(struct cobs_decode_state *state) {
+ state->p = 0;
+ state->c = 0;
+}
+
+int cobs_decode_incremental(struct cobs_decode_state *state, char *dst, size_t dstlen, char src) {
+ if (state->p == 0) {
+ if (src == 0)
+ goto empty_errout; /* invalid framing. An empty frame would be [...] 00 01 00, not [...] 00 00 */
+ state->c = (unsigned char)src;
+ state->p++;
+ return 0;
+ }
+
+ if (!src) {
+ if (state->c != 1)
+ goto errout; /* Invalid framing. The skip counter does not hit the end of the frame. */
+ int rv = state->p-1;
+ cobs_decode_incremental_initialize(state);
+ return rv;
+ }
+
+ char val;
+ state->c--;
+
+ if (state->c == 0) {
+ state->c = (unsigned char)src;
+ val = 0;
+ } else {
+ val = src;
+ }
+
+ size_t pos = state->p-1;
+ if (pos >= dstlen)
+ return -2; /* output buffer too small */
+ dst[pos] = val;
+ state->p++;
+ return 0;
+
+errout:
+ cobs_decode_incremental_initialize(state);
+ return -1;
+
+empty_errout:
+ cobs_decode_incremental_initialize(state);
+ return -3;
+}
+
+#ifdef VALIDATION
+/*@
+ @ requires 0 <= d < 256;
+ @ assigns \nothing;
+ @*/
+size_t test(char foo, unsigned int d) {
+ unsigned int c = (unsigned char)foo;
+ if (c != 0) {
+ //@ assert c < 256;
+ //@ assert c >= 0;
+ //@ assert c != 0;
+ //@ assert c > 0;
+ }
+ if (d != 0) {
+ //@ assert d >= 0;
+ //@ assert d != 0;
+ //@ assert d > 0;
+ }
+ return c + d;
+}
+
+#include <__fc_builtin.h>
+
+void main(void) {
+ char inbuf[254];
+ char cobsbuf[256];
+ char outbuf[256];
+
+ size_t range = Frama_C_interval(0, sizeof(inbuf));
+ Frama_C_make_unknown((char *)inbuf, range);
+
+ cobs_encode(cobsbuf, sizeof(cobsbuf), inbuf, sizeof(inbuf));
+ cobs_decode(outbuf, sizeof(outbuf), cobsbuf, sizeof(cobsbuf));
+
+ //@ assert \forall integer i; 0 <= i < sizeof(inbuf) ==> outbuf[i] == inbuf[i];
+}
+#endif//VALIDATION
+
diff --git a/gm_platform/fw/cobs.h b/gm_platform/fw/cobs.h
new file mode 100644
index 0000000..40f7955
--- /dev/null
+++ b/gm_platform/fw/cobs.h
@@ -0,0 +1,23 @@
+#ifndef __COBS_H__
+#define __COBS_H__
+
+#include
+#include
+#include
+
+
+struct cobs_decode_state {
+ size_t p;
+ size_t c;
+};
+
+
+ssize_t cobs_encode(char *dst, size_t dstlen, char *src, size_t srclen);
+ssize_t cobs_decode(char *dst, size_t dstlen, char *src, size_t srclen);
+
+int cobs_encode_usart(char *src, size_t srclen);
+
+void cobs_decode_incremental_initialize(struct cobs_decode_state *state);
+int cobs_decode_incremental(struct cobs_decode_state *state, char *dst, size_t dstlen, char src);
+
+#endif//__COBS_H__
diff --git a/gm_platform/fw/global.h b/gm_platform/fw/global.h
new file mode 100644
index 0000000..5fedde7
--- /dev/null
+++ b/gm_platform/fw/global.h
@@ -0,0 +1,52 @@
+/* Megumin LED display firmware
+ * Copyright (C) 2018 Sebastian Götte
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __GLOBAL_H__
+#define __GLOBAL_H__
+
+/* Workaround for sub-par ST libraries */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#include
+#include
+#include
+#pragma GCC diagnostic pop
+
+#include
+
+#include
+#include
+#include
+#include
+
+/* Microcontroller part number: STM32F030F4P6 */
+
+/* Things used for module status reporting. */
+#define FIRMWARE_VERSION 1
+#define HARDWARE_VERSION 0
+
+#define TS_CAL1 (*(uint16_t *)0x1FFFF7B8)
+#define VREFINT_CAL (*(uint16_t *)0x1FFFF7BA)
+
+#define ADC_BUFSIZE 1024
+
+extern volatile unsigned int sys_time;
+extern volatile unsigned int sys_time_seconds;
+
+#define UNUSED(var) ((void)var)
+
+#endif/*__GLOBAL_H__*/
diff --git a/gm_platform/fw/main.bin b/gm_platform/fw/main.bin
new file mode 100755
index 0000000..e2b0cdc
Binary files /dev/null and b/gm_platform/fw/main.bin differ
diff --git a/gm_platform/fw/main.c b/gm_platform/fw/main.c
new file mode 100644
index 0000000..d2bc33c
--- /dev/null
+++ b/gm_platform/fw/main.c
@@ -0,0 +1,175 @@
+/* Megumin LED display firmware
+ * Copyright (C) 2018 Sebastian Götte
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "global.h"
+#include "adc.h"
+#include "serial.h"
+
+
+volatile unsigned int sys_time_seconds = 0;
+
+void update_leds() {
+
+}
+
+volatile union {
+ struct {
+ unsigned int usb, ocxo, error, _nc1, _nc2, _nc3, pps, sd_card;
+ };
+ unsigned int arr[0];
+} leds;
+
+int main(void) {
+ RCC->CR |= RCC_CR_HSEON;
+ while (!(RCC->CR&RCC_CR_HSERDY));
+ RCC->CFGR &= ~RCC_CFGR_PLLMUL_Msk & ~RCC_CFGR_SW_Msk & ~RCC_CFGR_PPRE_Msk & ~RCC_CFGR_HPRE_Msk;
+ RCC->CFGR |= ((6-2)< 48.0MHz */
+ RCC->CR |= RCC_CR_PLLON;
+ while (!(RCC->CR&RCC_CR_PLLRDY));
+ RCC->CFGR |= (2<AHBENR |= RCC_AHBENR_DMAEN | RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_FLITFEN;
+ RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADCEN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_DBGMCUEN |\
+ RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN | RCC_APB2ENR_USART1EN;
+ RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
+
+ GPIOA->MODER |=
+ (3<OSPEEDR |=
+ (2<AFR[0] = (0<AFR[1] = (1<<8) | (1<<4);
+
+ GPIOB->MODER |=
+ (0<CR1 =
+ SPI_CR1_SSM
+ | SPI_CR1_SSI
+ | (4<CR2 = (7<CR1 |= SPI_CR1_SPE;
+
+ NVIC_EnableIRQ(SPI1_IRQn);
+ NVIC_SetPriority(SPI1_IRQn, 2<<5);
+
+ TIM16->CR2 = 0;
+ TIM16->DIER = TIM_DIER_UIE;
+ TIM16->PSC = 48-1; /* 1us */
+ TIM16->ARR = 1000-1; /* 1ms */
+ TIM16->CR1 = TIM_CR1_CEN;
+
+ NVIC_EnableIRQ(TIM16_IRQn);
+ NVIC_SetPriority(TIM16_IRQn, 2<<5);
+
+ adc_configure_scope_mode(1000000);
+
+ usart_dma_init();
+
+ while (42) {
+ char *data = "FOOBAR\n";
+ usart_send_packet((uint8_t*)data, 8);
+ for (int i=0; i<100000; i++);
+ //int pol = GPIOB->IDR & (1<<1); /* Sample current polarity */
+ //leds.error = pol ? 100 : 0;
+ //for (int i=0; i<10000; i++) ;
+ //leds.error = 100;
+ }
+}
+
+void SPI1_IRQHandler(void) {
+ if (SPI1->SR & SPI_SR_TXE) {
+ /* LED_STB */
+ GPIOA->BSRR = 1<<3;
+ SPI1->CR2 &= ~SPI_CR2_TXEIE;
+ }
+}
+
+void TIM16_IRQHandler(void) {
+ static int leds_update_counter = 0;
+ if (TIM16->SR & TIM_SR_UIF) {
+ TIM16->SR &= ~TIM_SR_UIF;
+
+ uint8_t bits = 0, mask = 1;
+ for (size_t i=0; iDR)) = bits;
+ SPI1->CR2 |= SPI_CR2_TXEIE;
+ GPIOA->BRR = 1<<3;
+ }
+ }
+}
+
+void NMI_Handler(void) {
+ asm volatile ("bkpt");
+}
+
+void HardFault_Handler(void) __attribute__((naked));
+void HardFault_Handler() {
+ asm volatile ("bkpt");
+}
+
+void SVC_Handler(void) {
+ asm volatile ("bkpt");
+}
+
+
+void PendSV_Handler(void) {
+ asm volatile ("bkpt");
+}
+
+void SysTick_Handler(void) {
+ static int n = 0;
+ if (n++ == 10) {
+ n = 0;
+ sys_time_seconds++;
+ leds.pps = 100; /* ms */
+ }
+}
+
diff --git a/gm_platform/fw/main.c.bak b/gm_platform/fw/main.c.bak
new file mode 100644
index 0000000..07d065d
--- /dev/null
+++ b/gm_platform/fw/main.c.bak
@@ -0,0 +1,162 @@
+/* Megumin LED display firmware
+ * Copyright (C) 2018 Sebastian Götte
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "global.h"
+
+#include "adc.h"
+
+volatile unsigned int sys_time = 0;
+volatile unsigned int sys_time_seconds = 0;
+
+void TIM1_BRK_UP_TRG_COM_Handler() {
+ TIM1->SR &= ~TIM_SR_UIF_Msk;
+}
+
+int main(void) {
+ RCC->CR |= RCC_CR_HSEON;
+ while (!(RCC->CR&RCC_CR_HSERDY));
+ RCC->CFGR &= ~RCC_CFGR_PLLMUL_Msk & ~RCC_CFGR_SW_Msk & ~RCC_CFGR_PPRE_Msk & ~RCC_CFGR_HPRE_Msk;
+ RCC->CFGR |= ((6-2)< 48.0MHz */
+ RCC->CR |= RCC_CR_PLLON;
+ while (!(RCC->CR&RCC_CR_PLLRDY));
+ RCC->CFGR |= (2<AHBENR |= RCC_AHBENR_DMAEN | RCC_AHBENR_GPIOAEN | RCC_AHBENR_FLITFEN;
+ RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADCEN| RCC_APB2ENR_DBGMCUEN | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM1EN;;
+ RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
+
+ GPIOA->MODER |=
+ (3<OSPEEDR |=
+ (2<BDTR = TIM_BDTR_MOE;
+ TIM1->CCMR2 = (6<CCER = TIM_CCER_CC4E;
+ TIM1->CCR4 = 1;
+ TIM1->DIER = TIM_DIER_UIE;
+
+ TIM1->PSC = SystemCoreClock/500000 - 1; /* 0.5us/tick */
+ TIM1->ARR = 25-1;
+ /* Preload all values */
+ TIM1->EGR |= TIM_EGR_UG;
+ TIM1->CR1 = TIM_CR1_ARPE;
+ /* And... go! */
+ TIM1->CR1 |= TIM_CR1_CEN;
+
+ void set_outputs(uint8_t val) {
+ int a=!!(val&1), b=!!(val&2), c=!!(val&4), d=!!(val&8);
+ GPIOA->ODR &= ~(!a<<3 | !b<<7 | c<<6 | d<<4);
+ GPIOA->ODR |= a<<3 | b<<7 | !c<<6 | !d<<4;
+ }
+ set_outputs(0);
+
+ adc_init();
+
+ uint8_t out_state = 0x01;
+#define DEBOUNCE 100
+ int debounce_ctr = 0;
+ int val_last = 0;
+ int ctr = 0;
+#define RESET 1000
+ int reset_ctr = 0;
+ while (42) {
+#define FOO 500000
+ if (reset_ctr)
+ reset_ctr--;
+ else
+ set_outputs(0);
+
+ if (debounce_ctr) {
+ debounce_ctr--;
+ } else {
+ int val = !!(GPIOA->IDR & 1);
+ debounce_ctr = DEBOUNCE;
+
+ if (val != val_last) {
+ if (val)
+ set_outputs(out_state & 0xf);
+ else
+ set_outputs(out_state >> 4);
+ reset_ctr = RESET;
+ val_last = val;
+ ctr++;
+
+ if (ctr == 100) {
+ ctr = 0;
+ out_state = out_state<<1 | out_state>>7;
+ }
+ }
+ }
+ /*
+ for (int i=0; iODR ^= 4;
+ }
+}
+
+void NMI_Handler(void) {
+}
+
+void HardFault_Handler(void) __attribute__((naked));
+void HardFault_Handler() {
+ asm volatile ("bkpt");
+}
+
+void SVC_Handler(void) {
+}
+
+
+void PendSV_Handler(void) {
+}
+
+void SysTick_Handler(void) {
+ static int n = 0;
+ sys_time++;
+ if (n++ == 1000) {
+ n = 0;
+ sys_time_seconds++;
+ }
+}
+
diff --git a/gm_platform/fw/main.elf b/gm_platform/fw/main.elf
new file mode 100755
index 0000000..f23985f
Binary files /dev/null and b/gm_platform/fw/main.elf differ
diff --git a/gm_platform/fw/main.hex b/gm_platform/fw/main.hex
new file mode 100644
index 0000000..c23d980
--- /dev/null
+++ b/gm_platform/fw/main.hex
@@ -0,0 +1,414 @@
+:020000040800F2
+:100000000010002095180008B1040008BD04000885
+:1000100000000000000000000000000000000000E0
+:10002000000000000000000000000000C104000803
+:100030000000000000000000CD040008D904000802
+:10004000E118000800000000E1180008E1180008AD
+:10005000E1180008E1180008E1180008E11800089C
+:1000600000000000930700085D0A0008E11800087E
+:10007000E1180008E1180008E1180008000000007D
+:10008000E11800080000000000000000E11800086E
+:1000900000000000F5030008E1180008E11800085E
+:1000A00000000000C903000800000000E11800087B
+:1000B0000000000000000000000000000000000040
+:1000C00080B582B000AF0200FB1D1A70FB1D1B78CB
+:1000D0001A001F231A40044B012191400A001A60A4
+:1000E000C046BD4602B080BD00E100E090B583B0DF
+:1000F00000AF02003960FB1D1A70FB1D1B787F2BBF
+:1001000032D92F4AFB1D1B7819000F230B40083BE7
+:100110009B0806339B00D31804331B68FA1D127822
+:10012000110003220A40D200FF2191400A00D2436D
+:100130001A4011003B689B01FF221A40FB1D1B78EF
+:10014000180003230340DB009A401D48FB1D1B7869
+:100150001C000F232340083B9B080A4306339B00E7
+:10016000C31804331A6027E0164AFB1D1B785BB2E4
+:100170009B08C0339B009B58FA1D12781100032284
+:100180000A40D200FF2191400A00D2431A401100D8
+:100190003B689B01FF221A40FB1D1B7818000323BC
+:1001A0000340DB009A400748FB1D1B785BB29B08AD
+:1001B0000A43C0339B001A50C046BD4603B090BDF1
+:1001C00000ED00E000E100E080B582B000AF7860B3
+:1001D0007B685A1E80235B049A4201D3012310E0FE
+:1001E0000A4B7A68013A5A6001235B4203211800E6
+:1001F000FFF77CFF054B00229A60044B07221A6030
+:1002000000231800BD4602B080BDC04610E000E0EB
+:1002100080B500AFC046BD4680BD80B582B000AF9E
+:100220005B4B1A685A4B802149020A431A60C04648
+:10023000574B1A6880239B021340F9D0544B5A68DD
+:10024000534B54490A405A60514B5A68504B8821CD
+:1002500049030A435A604E4B1A684D4B80214904AA
+:100260000A431A60C0464A4B1A6880239B04134015
+:10027000F9D0474B5A68464B02210A435A6000F0B6
+:1002800011FE454B1B680A21180001F08DF903008F
+:100290001800FFF799FF01235B421800FFF710FFDA
+:1002A00001235B4260211800FFF720FF384B5A6999
+:1002B000374B3A490A435A61354B9A69344B3849AE
+:1002C0000A439A61324BDA69314B02210A43DA61FF
+:1002D0009023DB051A689023DB0532490A431A6034
+:1002E0009023DB059A689023DB052F490A439A6027
+:1002F0009023DB0500221A629023DB05882252003E
+:100300005A622A4A294B12681A60294BC922920064
+:100310001A60274BE022D2005A60254B1A68244B02
+:1003200040210A431A601920FFF7CAFE4021192014
+:10033000FFF7DCFE1F4B00225A601E4B0122DA60E1
+:100340001C4B2F229A621B4B1B4ADA62194B01226B
+:100350001A601520FFF7B4FE40211520FFF7C6FEF6
+:10036000164B180000F05AF900F0BEFA144B3B602F
+:100370003B680821180000F091FB00237B6002E03D
+:100380007B6801337B607B680E4A9342F8DDEDE7C2
+:10039000001002400CF8C3FF00000020110006000E
+:1003A000015A420070A92800808A08000004004811
+:1003B0000030014000440140E703000040420F00CC
+:1003C000E41800089F86010080B500AF084B9B68C9
+:1003D0000222134009D09023DB0508229A61044BC6
+:1003E0005A68034B80218A435A60C046BD4680BD8F
+:1003F0000030014080B582B000AF284B1B6901225C
+:10040000134047D0254B1A69244B01218A431A61B6
+:10041000FB1D00221A70BB1D01221A7000233B60D5
+:100420001DE01F4B3A689200D358002B0FD01C4B95
+:100430003A689200D358591E194B3A689200D1502D
+:10044000FB1DF91DBA1D097812780A431A70BA1DEE
+:10045000BB1D1B78DB1813703B6801333B603B68A6
+:10046000072BDED90F4B1B68591C0E4A11600A2B53
+:1004700010D10C4B00221A600B4AFB1D1B78137025
+:100480000A4B5A68094B80210A435A609023DB05C6
+:1004900008229A62C046BD4602B080BD00440140B9
+:1004A000A8000020980000200C30014000300140DE
+:1004B00080B500AF00BEC046BD4680BD00BEC04690
+:1004C00080B500AF00BEC046BD4680BD80B500AF60
+:1004D00000BEC046BD4680BD80B500AF0A4B1B685C
+:1004E000591C094A11600A2B0AD1074B00221A60D5
+:1004F000064B1B685A1C054B1A60054B64229A6117
+:10050000C046BD4680BDC0469C000020940000202F
+:10051000A800002080B582B000AF0200FB1D1A7059
+:10052000FB1D1B781A001F231A40044B0121914028
+:100530000A001A60C046BD4602B080BD00E100E07E
+:1005400090B583B000AF02003960FB1D1A70FB1D2F
+:100550001B787F2B32D92F4AFB1D1B7819000F23E4
+:100560000B40083B9B0806339B00D31804331B68E1
+:10057000FA1D1278110003220A40D200FF21914097
+:100580000A00D2431A4011003B689B01FF221A4027
+:10059000FB1D1B78180003230340DB009A401D4815
+:1005A000FB1D1B781C000F232340083B9B080A43BC
+:1005B00006339B00C31804331A6027E0164AFB1D5C
+:1005C0001B785BB29B08C0339B009B58FA1D1278C6
+:1005D000110003220A40D200FF2191400A00D243B9
+:1005E0001A4011003B689B01FF221A40FB1D1B783B
+:1005F000180003230340DB009A400748FB1D1B78CB
+:100600005BB29B080A43C0339B001A50C046BD46EC
+:1006100003B090BD00ED00E000E100E080B584B0E3
+:1006200000AF78608023DB00180000F04BF8214B0E
+:10063000802212061A611F4B07225A611D4B1E4A67
+:10064000DA601C4B04229A621A4B9A68194B80217B
+:1006500009060A439A60C046164B9B68002BFBDBD9
+:10066000144B9A68134B01210A439A60114B9A6804
+:10067000104B04210A439A607B68104A934206DDBE
+:100680007B68FA21180001F019F8030000E0062346
+:10069000FB60FA6880235B029A4201DB084BFB6037
+:1006A000FB6819000C2000F03DF8C046BD4604B0C0
+:1006B00080BDC0460024014043080000DC05000066
+:1006C000FFFF000080B582B000AF7860114B124A86
+:1006D0009A60104B114ADA600E4B7A685A600D4BE3
+:1006E00000221A600B4B1A680A4B0D490A431A6024
+:1006F0000920FFF70FFF40210920FFF721FF054BDD
+:100700001A68044B01210A431A60C046BD4602B074
+:1007100080BDC0460800024040240140C8000020BF
+:10072000A205000080B582B000AF78603960154B3B
+:10073000802212025A64134BC022D201DA61114B9B
+:10074000802252011A620F4B01221A647B685A1EE2
+:100750000C4B9A623B685A1E0A4BDA62094B5A6983
+:10076000084B01210A435A61064B80221A60054B4F
+:100770001A68044B01210A431A60C046BD4602B004
+:1007800080BDC046002C014080B500AFC046BD46CC
+:1007900080BD80B500AF054B5A68044B01210A4368
+:1007A0005A60FFF7F1FFC046BD4680BD0000024021
+:1007B00080B582B000AF0200FB1D1A70FB1D1B78D4
+:1007C0001A001F231A40044B012191400A001A60AD
+:1007D000C046BD4602B080BD00E100E080B582B0F9
+:1007E00000AF0200FB1D1A70FB1D1B781A001F23AF
+:1007F0001340054901229A40130080228B50C046C5
+:10080000BD4602B080BDC04600E100E090B583B0B7
+:1008100000AF02003960FB1D1A70FB1D1B787F2B97
+:1008200032D92F4AFB1D1B7819000F230B40083BC0
+:100830009B0806339B00D31804331B68FA1D1278FB
+:10084000110003220A40D200FF2191400A00D24346
+:100850001A4011003B689B01FF221A40FB1D1B78C8
+:10086000180003230340DB009A401D48FB1D1B7842
+:100870001C000F232340083B9B080A4306339B00C0
+:10088000C31804331A6027E0164AFB1D1B785BB2BD
+:100890009B08C0339B009B58FA1D1278110003225D
+:1008A0000A40D200FF2191400A00D2431A401100B1
+:1008B0003B689B01FF221A40FB1D1B781800032395
+:1008C0000340DB009A400748FB1D1B785BB29B0886
+:1008D0000A43C0339B001A50C046BD4603B090BDCA
+:1008E00000ED00E000E100E080B500AF174B012211
+:1008F00052421A60154B00225A60144B00229A6033
+:10090000134B144A9A60124B92221A600A20FFF786
+:100910004FFF20210A20FFF779FF0F4B0F4A1A6083
+:100920000D4B3022DA600C4BC02292025A600A4B07
+:100930009A68094B80210A439A60074B1A68064B54
+:1009400001210A431A60C046BD4680BDC808002088
+:100950001C00024028380140003801402C200000D3
+:1009600080B584B000AF194BBB60BB685B687B602F
+:10097000BB689B687A689A4205D2BB689A687B68B4
+:10098000D31AFB6004E07B6880225200D31AFB601C
+:10099000BB687A681A607A68FB68D318FF221A402D
+:1009A000BB685A60BB680C331A007B68D218084BCE
+:1009B000DA60074BFA685A60054B1A68044B01214C
+:1009C0000A431A60C046BD4604B080BDC808002076
+:1009D0001C00024080B582B000AF78600A00FB1CAA
+:1009E0001A700A20FFF7FAFE7B689A687B681B681A
+:1009F0009A4205D10A20FFF7DBFE10235B4211E08B
+:100A00007B689B687A68D318FA1C12781A737B6823
+:100A10009B680133FF221A407B689A600A20FFF727
+:100A2000C7FE00231800BD4602B080BD80B582B06D
+:100A300000AF0200FB1D1A70C046FB1D1A78064B62
+:100A400011001800FFF7C6FF03001033F5D0C046B1
+:100A5000C046BD4602B080BDC808002080B500AFCA
+:100A60000B4B5A680A4B20210A435A60094B1A68FB
+:100A7000084B01218A431A60074B9A68064B5B6852
+:100A80009A4201D0FFF76CFFC046BD4680BDC0460C
+:100A9000000002401C000240C808002080B582B05F
+:100AA00000AF786039603A687B681100180000F088
+:100AB00070F8054B1B680122134001D1FFF750FF6E
+:100AC000C046BD4602B080BD1C00024080B588B063
+:100AD00000AFF860B9607A603B60BA6880235B025F
+:100AE0009A4202D23B68FE2B02D901235B424CE0C2
+:100AF0003B680233BA689A4202D201235B4244E067
+:100B00000023FB6136E0FB69002B0FD0FB69013B42
+:100B10007A68D3181B78002B08D0FB69013B7A68F0
+:100B2000D2181B23FB1812781A7019E0FB697B613D
+:100B300002E07B6901337B617A693B689A4205D2A6
+:100B40007A687B69D3181B78002BF2D17B69DAB203
+:100B5000FB69DBB2D31ADAB21B23FB1801321A701D
+:100B6000FA68FB69D3181B22BA1812781A70FB694D
+:100B70000133FB61FA693B689A42C4D9FA68FB69A0
+:100B8000D31800221A703B6802331800BD4608B023
+:100B900080BD80B586B000AF786039603B68FE2BC1
+:100BA00002D901235B4240E000237B6135E07B6991
+:100BB000002B0FD07B69013B7A68D3181B78002B80
+:100BC00008D07B69013B7A68D2181323FB1812788E
+:100BD0001A7019E07B69FB6002E0FB680133FB607F
+:100BE000FA683B689A4205D27A68FB68D3181B788A
+:100BF000002BF2D1FB68DAB27B69DBB2D31ADAB22E
+:100C00001323FB1801321A701323FB181B781800EA
+:100C1000FFF70CFF7B6901337B617A693B689A427D
+:100C2000C5D90020FFF702FF00231800BD4606B01B
+:100C300080BD80B588B000AFF860B9607A603B6075
+:100C4000BA6880235B029A4204D23A6880235B022E
+:100C50009A4202D301235B4252E03B68002B02D14F
+:100C600001235B424CE0BA683B689A4202D20123FE
+:100C70005B4245E00123FB617B681B78BB61BB697C
+:100C8000002B24D102235B423AE0BB69013BBB61EC
+:100C9000BB69002B09D17A68FB69D3181B78BB614B
+:100CA0001723FB1800221A7006E07A68FB69D21835
+:100CB0001723FB1812781A70FB69013BFA68D318E6
+:100CC0001722BA1812781A70FB690133FB61FA69AE
+:100CD0003B689A4205D27A68FB69D3181B78002BCF
+:100CE000D3D1FA693B689A4202D102235B4207E002
+:100CF000BB69012B02D003235B4201E0FB69013B8E
+:100D00001800BD4608B080BD80B582B000AF7860E5
+:100D10007B6800221A607B6800225A60C046BD468C
+:100D200002B080BD80B588B000AFF860B9607A606D
+:100D30001A00FB1C1A70FB681B68002B0ED1FB1CF1
+:100D40001B78002B54D0FB1C1A78FB685A60FB6898
+:100D50001B685A1CFB681A60002350E0FB1C1B78C0
+:100D6000002B0DD1FB685B68012B39D1FB681B6838
+:100D7000013B7B61FB681800FFF7C6FF7B693EE023
+:100D8000FB685B685A1EFB685A60FB685B68002B57
+:100D900008D1FB1C1A78FB685A601F23FB1800223D
+:100DA0001A7004E01F23FB18FA1C12781A70FB68F3
+:100DB0001B68013BBB61BA697B689A4202D302237C
+:100DC0005B421CE0BA68BB69D3181F22BA181278BC
+:100DD0001A70FB681B685A1CFB681A6000230EE03F
+:100DE000C046FB681800FFF78FFF01235B4206E057
+:100DF000C046FB681800FFF787FF03235B4218001B
+:100E0000BD4608B080BD0419000800000020940011
+:100E1000002094000020D4090020000080B500AF1D
+:100E20001A4B1A68194B01210A431A60174B5A686A
+:100E3000164B17490A405A60144B1A68134B154950
+:100E40000A401A60114B1A68104B13490A401A6085
+:100E50000E4B5A680D4B11490A405A600B4BDA6A27
+:100E60000A4B0F218A43DA62084B1A6B074B0C4975
+:100E70000A401A63054B5A6B044B01218A435A639B
+:100E8000024B00229A60C046BD4680BD0010024061
+:100E90000CB8FF08FFFFF6FEFFFFFBFFFFFFC0FFE0
+:100EA000ECFEFFFF80B584B000AF0023FB600023A1
+:100EB000BB6000237B6000233B60314B5B680C22EE
+:100EC0001340FB60FB68082B11D0FB68082B41D84E
+:100ED000FB68002B03D0FB68042B04D03AE0294BBD
+:100EE000294A1A603AE0274B274A1A6036E0244B19
+:100EF0005A68F0239B031340BB60214B5A68802340
+:100F00005B0213407B60BB689B0C0233BB601C4BD5
+:100F1000DB6A0F22134001333B607A6880235B0257
+:100F20009A420AD13968184800F03EFB03001A00C3
+:100F3000BB685A43134B1A6010E0B9680A005201AB
+:100F4000521A93019B1ADB005B181B021A000D4B0F
+:100F50001A6003E00B4B0C4A1A60C046084B5B68F2
+:100F60001B090F221340094AD35CFB60054B1A682A
+:100F7000FB68DA40034B1A60C046BD4604B080BD32
+:100F8000001002400000002000127A00EC18000857
+:100F900080B500AF044B1A68034B8021C9020A4395
+:100FA0001A60C046BD4680BD0010024080B500AF4B
+:100FB000044B1A68034B04490A401A60C046BD46F8
+:100FC00080BDC04600100240FFFFFBFF80B500AFB0
+:100FD000044B1A68034B802149020A431A60C04639
+:100FE000BD4680BD0010024080B500AF064B1A68B8
+:100FF00080239B021340054A944663445A4253415E
+:10100000DBB21800BD4680BD001002400000FEFFAC
+:1010100080B500AF044B1A68034B01210A431A60E4
+:10102000C046BD4680BDC0460010024080B500AF3E
+:10103000054B1B6802221340023B5A425341DBB26C
+:101040001800BD4680BDC0460010024080B582B089
+:1010500000AF7860064B5B68032293431900044B92
+:101060007A680A435A60C046BD4602B080BDC04699
+:101070000010024080B500AF034B5B680C221340A8
+:101080001800BD4680BDC0460010024080B582B049
+:1010900000AF7860064B5B68F02293431900044B65
+:1010A0007A680A435A60C046BD4602B080BDC04659
+:1010B0000010024080B582B000AF7860064B5B68DC
+:1010C000064A13401900044B7A680A435A60C04626
+:1010D000BD4602B080BDC04600100240FFF8FFFFD1
+:1010E00080B500AF044B1A68034B802149040A43C2
+:1010F0001A60C046BD4680BD0010024080B500AFFA
+:10110000074B1A6880239B041340FE221206944664
+:1011100063445A425341DBB21800BD4680BDC0460D
+:101120000010024080B582B000AF786039600E4B8D
+:101130005B680E4A134019007A6880235B021A40EC
+:101140003B681A43084B0A435A60074BDB6A0F227D
+:10115000934319007B680F221A40034B0A43DA625B
+:10116000C046BD4602B080BD00100240FFFFC2FF76
+:1011700080B582B000AF786039603968786800F077
+:1011800013FA03001A00064B013A5A60044B00227E
+:101190009A60034B05221A60C046BD4602B080BD6E
+:1011A00010E000E080B582B000AF7860064B1B68AD
+:1011B000012293431900044B7A680A431A60C0461F
+:1011C000BD4602B080BDC0460020024080B500AFE1
+:1011D000034B1B68012213401800BD4680BDC0466A
+:1011E0000020024080B582B000AF7860FA239A00F8
+:1011F0007B6811001800FFF7BBFFC046BD4602B078
+:1012000080BD80B584B000AF78600E4B1B68FB607A
+:10121000FB687B6801330CD07B6801337B6008E09E
+:10122000084B1A6880235B02134002D07B68013BA5
+:101230007B607B68002BF3D1C046C046BD4604B03E
+:1012400080BDC04610E000E080B582B000AF78609D
+:10125000034B7A681A60C046BD4602B080BDC046E6
+:101260000000002090B585B000AF786039600F2392
+:10127000FB1801221A700023BB6000F0D4F80300B1
+:10128000012B28D17B6801225A607B68174A19001C
+:10129000100000F0ABF80300BB60FFF7C7FE0300CF
+:1012A000012B07D0FFF7B4FEC046FFF7BFFE0300D7
+:1012B000012BFAD17B681B6819000020FFF732FF71
+:1012C0000F23FC183A68BB681100180000F0BEF844
+:1012D0000300237003E00F23FB1800221A700F2372
+:1012E000FB181B781800BD4605B090BD00127A00AF
+:1012F00090B587B000AFF860B9607A603B601723A3
+:10130000FB1801221A7000233B6100F08CF80300E7
+:10131000012B32D17A68FB681100180000F066F8E2
+:1013200003003B61FFF760FE0300012B0FD0BB6899
+:10133000012B02D1FFF72CFE01E0FFF737FEFFF78C
+:1013400045FEC046FFF750FE0300012BFAD17B6833
+:101350005B68802252021A437B681B6819001000E8
+:10136000FFF7E0FE1723FC183A683B6911001800EC
+:1013700000F06CF80300237003E01723FB18002231
+:101380001A701723FB181B781800BD4607B090BDD4
+:1013900080B584B000AF78600F217B1801221A70ED
+:1013A0000023BB607B68002B03D17B1800221A70DE
+:1013B00013E07B680C4A934201D90123BB60BB68F0
+:1013C0001800FFF7EFFEFFF701FF0200BB68934232
+:1013D00003D00F23FB1800221A700F23FB181B7871
+:1013E0001800BD4604B080BD00366E0180B584B0E3
+:1013F00000AF786039600023FB603B685B680133B5
+:101400001900786800F0D0F8030019003B681B68E9
+:101410009B0C0F22134002334B43FB60FB68180008
+:10142000BD4604B080BD80B582B000AFFB1D012277
+:101430001A70FFF763FE031E02D0FB1D00221A7014
+:10144000FB1D1B781800BD4602B080BD90B585B06D
+:1014500000AF786039600F203B1801221A7000231A
+:10146000BB602E4B1A683B681B681B090F210B40A1
+:101470002B49CB5C9A401300BB60BA687B689A42E8
+:1014800006D23C187B681800FFF782FF0300237028
+:101490000F23FB181B78012B1AD1FFF721FEC04642
+:1014A000FFF72CFE0300012BFAD13B681B681800E4
+:1014B000FFF7ECFD0220FFF7C9FDC046FFF7DAFD9C
+:1014C0000300082BFAD13B685B681800FFF7F2FDB8
+:1014D000BA687B689A4207D90F23FC187B6818000A
+:1014E000FFF756FF030023700F23FB181B78012B17
+:1014F0000CD13B681B681B090F221340084AD35CC0
+:101500001A007B68D3401800FFF79EFE0F23FB18DC
+:101510001B781800BD4605B090BDC04600000020F5
+:10152000EC18000880B500AFC046BD4680BD80B550
+:1015300086B000AFF860B9607A60FA687B68D3184B
+:101540003B61FB687B6106E0BB68DAB27B691A70BD
+:101550007B6901337B617A693B699A42F4D3FB680A
+:101560001800BD4606B080BD80B584B000AF78607D
+:101570007B68FB60C0467B685A1C7A601B78002B36
+:10158000F9D17A68FB68D31A013B1800BD4604B054
+:1015900080BD80B582B000AF0200FB1D1A70C0464E
+:1015A000BD4602B080BD0000002243088B4274D3C8
+:1015B00003098B425FD3030A8B4244D3030B8B4254
+:1015C00028D3030C8B420DD3FF22090212BA030C5D
+:1015D0008B4202D31212090265D0030B8B4219D33E
+:1015E00000E0090AC30B8B4201D3CB03C01A52415E
+:1015F000830B8B4201D38B03C01A5241430B8B42A6
+:1016000001D34B03C01A5241030B8B4201D30B038E
+:10161000C01A5241C30A8B4201D3CB02C01A5241B5
+:10162000830A8B4201D38B02C01A5241430A8B4278
+:1016300001D34B02C01A5241030A8B4201D30B0261
+:10164000C01A5241CDD2C3098B4201D3CB01C01A7B
+:10165000524183098B4201D38B01C01A5241430985
+:101660008B4201D34B01C01A524103098B4201D373
+:101670000B01C01A5241C3088B4201D3CB00C01AE0
+:10168000524183088B4201D38B00C01A5241430858
+:101690008B4201D34B00C01A5241411A00D201467D
+:1016A000524110467047FFE701B5002000F0F0F806
+:1016B00002BDC0460029F7D076E7704703460B43CA
+:1016C0007FD4002243088B4274D303098B425FD33B
+:1016D000030A8B4244D3030B8B4228D3030C8B4267
+:1016E0000DD3FF22090212BA030C8B4202D312124D
+:1016F000090265D0030B8B4219D300E0090AC30B22
+:101700008B4201D3CB03C01A5241830B8B4201D3CE
+:101710008B03C01A5241430B8B4201D34B03C01AB7
+:101720005241030B8B4201D30B03C01A5241C30A2F
+:101730008B4201D3CB02C01A5241830A8B4201D3A0
+:101740008B02C01A5241430A8B4201D34B02C01A8A
+:101750005241030A8B4201D30B02C01A5241CDD22F
+:10176000C3098B4201D3CB01C01A524183098B427A
+:1017700001D38B01C01A524143098B4201D34B0163
+:10178000C01A524103098B4201D30B01C01A5241C6
+:10179000C3088B4201D3CB00C01A524183088B424D
+:1017A00001D38B00C01A524143088B4201D34B0036
+:1017B000C01A5241411A00D20146524110467047A8
+:1017C0005DE0CA0F00D04942031000D340425340AD
+:1017D00000229C4603098B422DD3030A8B4212D36D
+:1017E000FC22890112BA030A8B420CD3890192119F
+:1017F0008B4208D3890192118B4204D389013AD0DC
+:10180000921100E08909C3098B4201D3CB01C01AB0
+:10181000524183098B4201D38B01C01A52414309C3
+:101820008B4201D34B01C01A524103098B4201D3B1
+:101830000B01C01A5241C3088B4201D3CB00C01A1E
+:10184000524183088B4201D38B00C01A5241D9D236
+:1018500043088B4201D34B00C01A5241411A00D2B7
+:101860000146634652415B10104601D34042002BB3
+:1018700000D54942704763465B1000D3404201B532
+:10188000002000F005F802BD0029F8D016E77047E7
+:101890007047C0460C488546002103E00B4B5B585F
+:1018A000435004310A480B4B42189A42F6D30A4A75
+:1018B00002E0002313600432084B9A42F9D3FFF789
+:1018C000ADFAFEF7AAFCFEE700100020041900089C
+:1018D000000000209400002094000020D409002083
+:1018E000FEE70000464F4F4241520A000000000050
+:1018F00000000000010203040607080900000000C0
+:0419000001020304D9
+:1019040000127A000004004000200040002800403B
+:10191400002C0040003000400054004000700040A3
+:101924000000014000040140002401400827014058
+:1019340008270140002C01400030014000380140DC
+:1019440000440140004801400058014000000240AA
+:10195400080002401C0002403000024044000240E3
+:10196400580002400020024000F8FF1F001002400F
+:10197400003002400000004800040048000800480D
+:10198400000C00480014004800ED00E010E000E006
+:0419940000E100E08E
+:040000050800189542
+:00000001FF
diff --git a/gm_platform/fw/main.lst b/gm_platform/fw/main.lst
new file mode 100644
index 0000000..5be6e7e
--- /dev/null
+++ b/gm_platform/fw/main.lst
@@ -0,0 +1,4459 @@
+
+main.elf: file format elf32-littlearm
+
+SYMBOL TABLE:
+08000000 l d .isr_vector 00000000 .isr_vector
+080000c0 l d .text 00000000 .text
+20000000 l d .data 00000000 .data
+20000094 l d .bss 00000000 .bss
+00000000 l d .comment 00000000 .comment
+00000000 l d .ARM.attributes 00000000 .ARM.attributes
+00000000 l d .debug_aranges 00000000 .debug_aranges
+00000000 l d .debug_info 00000000 .debug_info
+00000000 l d .debug_abbrev 00000000 .debug_abbrev
+00000000 l d .debug_line 00000000 .debug_line
+00000000 l d .debug_frame 00000000 .debug_frame
+00000000 l d .debug_str 00000000 .debug_str
+00000000 l d .debug_ranges 00000000 .debug_ranges
+00000000 l df *ABS* 00000000 /tmp/ccTaPb5k.o
+080018a4 l .text 00000000 LoopCopyDataInit
+0800189c l .text 00000000 CopyDataInit
+080018b8 l .text 00000000 LoopFillZerobss
+080018b2 l .text 00000000 FillZerobss
+080018c6 l .text 00000000 LoopForever
+080018e0 l .text 00000000 Infinite_Loop
+00000000 l df *ABS* 00000000 main.c
+080000c0 l F .text 0000002c NVIC_EnableIRQ
+080000ec l F .text 000000dc NVIC_SetPriority
+080001c8 l F .text 00000048 SysTick_Config
+20000098 l .bss 00000004 leds_update_counter.5785
+2000009c l .bss 00000004 n.5808
+00000000 l df *ABS* 00000000 adc.c
+08000514 l F .text 0000002c NVIC_EnableIRQ
+08000540 l F .text 000000dc NVIC_SetPriority
+080006c4 l F .text 00000060 adc_dma_init
+08000724 l F .text 00000064 adc_timer_init
+08000788 l F .text 0000000a gdb_dump
+00000000 l df *ABS* 00000000 serial.c
+080007b0 l F .text 0000002c NVIC_EnableIRQ
+080007dc l F .text 00000030 NVIC_DisableIRQ
+0800080c l F .text 000000dc NVIC_SetPriority
+08000960 l F .text 00000074 usart_schedule_dma
+00000000 l df *ABS* 00000000 cobs.c
+00000000 l df *ABS* 00000000 system_stm32f0xx.c
+00000000 l df *ABS* 00000000 stm32f0xx_ll_utils.c
+08000f90 l F .text 0000001c LL_RCC_HSE_EnableBypass
+08000fac l F .text 00000020 LL_RCC_HSE_DisableBypass
+08000fcc l F .text 0000001c LL_RCC_HSE_Enable
+08000fe8 l F .text 00000028 LL_RCC_HSE_IsReady
+08001010 l F .text 0000001c LL_RCC_HSI_Enable
+0800102c l F .text 00000020 LL_RCC_HSI_IsReady
+0800104c l F .text 00000028 LL_RCC_SetSysClkSource
+08001074 l F .text 00000018 LL_RCC_GetSysClkSource
+0800108c l F .text 00000028 LL_RCC_SetAHBPrescaler
+080010b4 l F .text 0000002c LL_RCC_SetAPB1Prescaler
+080010e0 l F .text 0000001c LL_RCC_PLL_Enable
+080010fc l F .text 00000028 LL_RCC_PLL_IsReady
+08001124 l F .text 0000004c LL_RCC_PLL_ConfigDomain_SYS
+08001170 l F .text 00000034 LL_InitTick
+080011a4 l F .text 00000028 LL_FLASH_SetLatency
+080011cc l F .text 00000018 LL_FLASH_GetLatency
+08001426 l F .text 00000026 UTILS_PLL_IsBusy
+080013ec l F .text 0000003a UTILS_GetPLLOutputFrequency
+0800144c l F .text 000000d8 UTILS_EnablePLLAndSwitchSystem
+08001390 l F .text 0000005c UTILS_SetFlashLatency
+00000000 l df *ABS* 00000000 base.c
+00000000 l df *ABS* 00000000 cmsis_exports.c
+00000000 l df *ABS* 00000000 _udivsi3.o
+080015a8 l .text 00000000 .udivsi3_skip_div0_test
+00000000 l df *ABS* 00000000 _divsi3.o
+080016bc l .text 00000000 .divsi3_skip_div0_test
+00000000 l df *ABS* 00000000 _dvmd_tls.o
+080018fc g O .text 00000008 APBPrescTable
+20000044 g O .data 00000004 tim17
+2000007c g O .data 00000004 gpioc
+20000088 g O .data 00000004 scb
+08001202 g F .text 00000046 LL_mDelay
+08000a9c g F .text 00000030 usart_send_packet
+080018e0 w F .text 00000002 TIM1_CC_IRQHandler
+08001524 g F .text 0000000a __sinit
+080004bc g F .text 00000004 HardFault_Handler
+2000006c g O .data 00000004 rcc
+080004d8 g F .text 0000003c SysTick_Handler
+08001904 g .text 00000000 _sidata
+080004cc g F .text 0000000c PendSV_Handler
+20000020 g O .data 00000004 syscfg
+080004b0 g F .text 0000000c NMI_Handler
+200009d4 g .bss 00000000 __exidx_end
+08001264 g F .text 0000008c LL_PLL_ConfigSystemClock_HSI
+080018e0 w F .text 00000002 I2C1_IRQHandler
+08001248 g F .text 0000001c LL_SetSystemCoreClock
+200000a0 g O .bss 00000004 __errno
+20000008 g O .data 00000004 tim14
+20000048 g O .data 00000004 dbgmcu
+2000003c g O .data 00000004 usart1
+08001904 g .text 00000000 _etext
+20000094 g .bss 00000000 _sbss
+08000c32 g F .text 000000d6 cobs_decode
+200008c8 g O .bss 0000010c usart_tx_buf
+20000094 g O .bss 00000004 sys_time_seconds
+20000000 g O .data 00000004 SystemCoreClock
+2000001c g O .data 00000004 pwr
+080015a8 g F .text 0000010a .hidden __udivsi3
+08001592 g F .text 00000014 __assert_func
+20000000 g .data 00000000 _sdata
+080003c8 g F .text 0000002c SPI1_IRQHandler
+20000060 g O .data 00000004 dma1_channel5
+20000058 g O .data 00000004 dma1_channel3
+200009d4 g .bss 00000000 __exidx_start
+080011e4 g F .text 0000001e LL_Init1msTick
+20000054 g O .data 00000004 dma1_channel2
+080018e0 w F .text 00000002 EXTI2_3_IRQHandler
+080018e0 w F .text 00000002 ADC1_IRQHandler
+08000d24 g F .text 000000e2 cobs_decode_incremental
+2000004c g O .data 00000004 dma1
+080018e0 w F .text 00000002 TIM17_IRQHandler
+080018e0 w F .text 00000002 RTC_IRQHandler
+200009d4 g .bss 00000000 _ebss
+2000002c g O .data 00000004 adc1_common
+08001894 w F .text 00000034 Reset_Handler
+20000070 g O .data 00000004 crc
+20000024 g O .data 00000004 exti
+08000210 g F .text 0000000a update_leds
+20000028 g O .data 00000004 adc1
+080016bc g F .text 00000000 .hidden __aeabi_idiv
+08000acc g F .text 000000c6 cobs_encode
+200000a8 g O .bss 00000020 leds
+20000074 g O .data 00000004 gpioa
+080003f4 g F .text 000000bc TIM16_IRQHandler
+080018e0 w F .text 00000002 TIM3_IRQHandler
+080018e0 w F .text 00000002 EXTI4_15_IRQHandler
+080018e0 w F .text 00000002 RCC_IRQHandler
+20000094 g .bss 00000000 _bss
+08000792 g F .text 0000001e DMA1_Channel1_IRQHandler
+080018e0 g .text 00000002 Default_Handler
+080018ec g O .text 00000010 AHBPrescTable
+08000b92 g F .text 000000a0 cobs_encode_usart
+20000010 g O .data 00000004 wwdg
+080018e0 w F .text 00000002 TIM14_IRQHandler
+080018e0 w F .text 00000002 DMA1_Channel4_5_IRQHandler
+20000030 g O .data 00000004 adc
+08000a2c g F .text 00000030 usart_putc
+080018e0 w F .text 00000002 EXTI0_1_IRQHandler
+08001890 w F .text 00000002 .hidden __aeabi_ldiv0
+20000004 g O .data 00000004 tim3
+2000000c g O .data 00000004 rtc
+080008e8 g F .text 00000078 usart_dma_init
+0800152e g F .text 0000003a memset
+0800021a g F .text 000001ae main
+20000064 g O .data 00000004 flash
+080015a8 g F .text 00000000 .hidden __aeabi_uidiv
+080004c0 g F .text 0000000c SVC_Handler
+20000018 g O .data 00000004 i2c1
+20000050 g O .data 00000004 dma1_channel1
+080016bc g F .text 000001cc .hidden __divsi3
+20000090 g O .data 00000004 nvic
+08000e1c g F .text 00000088 SystemInit
+200000a4 g O .bss 00000004 _impure_ptr
+080018e0 w F .text 00000002 WWDG_IRQHandler
+20000000 g .data 00000000 _data
+20000084 g O .data 00000004 gpiof
+08000a5c g F .text 00000040 DMA1_Channel2_3_IRQHandler
+200000c8 g O .bss 00000800 adc_buf
+20000080 g O .data 00000004 gpiod
+20001000 g *ABS* 00000000 _estack
+080016b4 g F .text 00000008 .hidden __aeabi_uidivmod
+20000068 g O .data 00000004 ob
+20000094 g .data 00000000 _edata
+20000038 g O .data 00000004 spi1
+080009d4 g F .text 00000058 usart_dma_fifo_push
+2000005c g O .data 00000004 dma1_channel4
+08000000 g O .isr_vector 00000000 g_pfnVectors
+08000ea4 g F .text 000000ec SystemCoreClockUpdate
+080012f0 g F .text 000000a0 LL_PLL_ConfigSystemClock_HSE
+08001890 w F .text 00000002 .hidden __aeabi_idiv0
+20000014 g O .data 00000004 iwdg
+080018e0 w F .text 00000002 FLASH_IRQHandler
+08000d08 g F .text 0000001c cobs_decode_incremental_initialize
+080018e0 w F .text 00000002 USART1_IRQHandler
+0800061c g F .text 000000a8 adc_configure_scope_mode
+08001568 g F .text 0000002a strlen
+080018e0 w F .text 00000002 TIM1_BRK_UP_TRG_COM_IRQHandler
+20000078 g O .data 00000004 gpiob
+20000034 g O .data 00000004 tim1
+2000008c g O .data 00000004 systick
+08001888 g F .text 00000008 .hidden __aeabi_idivmod
+20000040 g O .data 00000004 tim16
+
+
+
+Disassembly of section .text:
+
+080000c0 :
+ \brief Enable External Interrupt
+ \details Enables a device-specific interrupt in the NVIC interrupt controller.
+ \param [in] IRQn External interrupt number. Value cannot be negative.
+ */
+__STATIC_INLINE void NVIC_EnableIRQ(IRQn_Type IRQn)
+{
+ 80000c0: b580 push {r7, lr}
+ 80000c2: b082 sub sp, #8
+ 80000c4: af00 add r7, sp, #0
+ 80000c6: 0002 movs r2, r0
+ 80000c8: 1dfb adds r3, r7, #7
+ 80000ca: 701a strb r2, [r3, #0]
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ 80000cc: 1dfb adds r3, r7, #7
+ 80000ce: 781b ldrb r3, [r3, #0]
+ 80000d0: 001a movs r2, r3
+ 80000d2: 231f movs r3, #31
+ 80000d4: 401a ands r2, r3
+ 80000d6: 4b04 ldr r3, [pc, #16] ; (80000e8 )
+ 80000d8: 2101 movs r1, #1
+ 80000da: 4091 lsls r1, r2
+ 80000dc: 000a movs r2, r1
+ 80000de: 601a str r2, [r3, #0]
+}
+ 80000e0: 46c0 nop ; (mov r8, r8)
+ 80000e2: 46bd mov sp, r7
+ 80000e4: b002 add sp, #8
+ 80000e6: bd80 pop {r7, pc}
+ 80000e8: e000e100 .word 0xe000e100
+
+080000ec :
+ \note The priority cannot be set for every core interrupt.
+ \param [in] IRQn Interrupt number.
+ \param [in] priority Priority to set.
+ */
+__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
+{
+ 80000ec: b590 push {r4, r7, lr}
+ 80000ee: b083 sub sp, #12
+ 80000f0: af00 add r7, sp, #0
+ 80000f2: 0002 movs r2, r0
+ 80000f4: 6039 str r1, [r7, #0]
+ 80000f6: 1dfb adds r3, r7, #7
+ 80000f8: 701a strb r2, [r3, #0]
+ if ((int32_t)(IRQn) < 0)
+ 80000fa: 1dfb adds r3, r7, #7
+ 80000fc: 781b ldrb r3, [r3, #0]
+ 80000fe: 2b7f cmp r3, #127 ; 0x7f
+ 8000100: d932 bls.n 8000168
+ {
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 8000102: 4a2f ldr r2, [pc, #188] ; (80001c0 )
+ 8000104: 1dfb adds r3, r7, #7
+ 8000106: 781b ldrb r3, [r3, #0]
+ 8000108: 0019 movs r1, r3
+ 800010a: 230f movs r3, #15
+ 800010c: 400b ands r3, r1
+ 800010e: 3b08 subs r3, #8
+ 8000110: 089b lsrs r3, r3, #2
+ 8000112: 3306 adds r3, #6
+ 8000114: 009b lsls r3, r3, #2
+ 8000116: 18d3 adds r3, r2, r3
+ 8000118: 3304 adds r3, #4
+ 800011a: 681b ldr r3, [r3, #0]
+ 800011c: 1dfa adds r2, r7, #7
+ 800011e: 7812 ldrb r2, [r2, #0]
+ 8000120: 0011 movs r1, r2
+ 8000122: 2203 movs r2, #3
+ 8000124: 400a ands r2, r1
+ 8000126: 00d2 lsls r2, r2, #3
+ 8000128: 21ff movs r1, #255 ; 0xff
+ 800012a: 4091 lsls r1, r2
+ 800012c: 000a movs r2, r1
+ 800012e: 43d2 mvns r2, r2
+ 8000130: 401a ands r2, r3
+ 8000132: 0011 movs r1, r2
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ 8000134: 683b ldr r3, [r7, #0]
+ 8000136: 019b lsls r3, r3, #6
+ 8000138: 22ff movs r2, #255 ; 0xff
+ 800013a: 401a ands r2, r3
+ 800013c: 1dfb adds r3, r7, #7
+ 800013e: 781b ldrb r3, [r3, #0]
+ 8000140: 0018 movs r0, r3
+ 8000142: 2303 movs r3, #3
+ 8000144: 4003 ands r3, r0
+ 8000146: 00db lsls r3, r3, #3
+ 8000148: 409a lsls r2, r3
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 800014a: 481d ldr r0, [pc, #116] ; (80001c0 )
+ 800014c: 1dfb adds r3, r7, #7
+ 800014e: 781b ldrb r3, [r3, #0]
+ 8000150: 001c movs r4, r3
+ 8000152: 230f movs r3, #15
+ 8000154: 4023 ands r3, r4
+ 8000156: 3b08 subs r3, #8
+ 8000158: 089b lsrs r3, r3, #2
+ 800015a: 430a orrs r2, r1
+ 800015c: 3306 adds r3, #6
+ 800015e: 009b lsls r3, r3, #2
+ 8000160: 18c3 adds r3, r0, r3
+ 8000162: 3304 adds r3, #4
+ 8000164: 601a str r2, [r3, #0]
+ else
+ {
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ }
+}
+ 8000166: e027 b.n 80001b8
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 8000168: 4a16 ldr r2, [pc, #88] ; (80001c4 )
+ 800016a: 1dfb adds r3, r7, #7
+ 800016c: 781b ldrb r3, [r3, #0]
+ 800016e: b25b sxtb r3, r3
+ 8000170: 089b lsrs r3, r3, #2
+ 8000172: 33c0 adds r3, #192 ; 0xc0
+ 8000174: 009b lsls r3, r3, #2
+ 8000176: 589b ldr r3, [r3, r2]
+ 8000178: 1dfa adds r2, r7, #7
+ 800017a: 7812 ldrb r2, [r2, #0]
+ 800017c: 0011 movs r1, r2
+ 800017e: 2203 movs r2, #3
+ 8000180: 400a ands r2, r1
+ 8000182: 00d2 lsls r2, r2, #3
+ 8000184: 21ff movs r1, #255 ; 0xff
+ 8000186: 4091 lsls r1, r2
+ 8000188: 000a movs r2, r1
+ 800018a: 43d2 mvns r2, r2
+ 800018c: 401a ands r2, r3
+ 800018e: 0011 movs r1, r2
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ 8000190: 683b ldr r3, [r7, #0]
+ 8000192: 019b lsls r3, r3, #6
+ 8000194: 22ff movs r2, #255 ; 0xff
+ 8000196: 401a ands r2, r3
+ 8000198: 1dfb adds r3, r7, #7
+ 800019a: 781b ldrb r3, [r3, #0]
+ 800019c: 0018 movs r0, r3
+ 800019e: 2303 movs r3, #3
+ 80001a0: 4003 ands r3, r0
+ 80001a2: 00db lsls r3, r3, #3
+ 80001a4: 409a lsls r2, r3
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 80001a6: 4807 ldr r0, [pc, #28] ; (80001c4 )
+ 80001a8: 1dfb adds r3, r7, #7
+ 80001aa: 781b ldrb r3, [r3, #0]
+ 80001ac: b25b sxtb r3, r3
+ 80001ae: 089b lsrs r3, r3, #2
+ 80001b0: 430a orrs r2, r1
+ 80001b2: 33c0 adds r3, #192 ; 0xc0
+ 80001b4: 009b lsls r3, r3, #2
+ 80001b6: 501a str r2, [r3, r0]
+}
+ 80001b8: 46c0 nop ; (mov r8, r8)
+ 80001ba: 46bd mov sp, r7
+ 80001bc: b003 add sp, #12
+ 80001be: bd90 pop {r4, r7, pc}
+ 80001c0: e000ed00 .word 0xe000ed00
+ 80001c4: e000e100 .word 0xe000e100
+
+080001c8 :
+ \note When the variable __Vendor_SysTickConfig is set to 1, then the
+ function SysTick_Config is not included. In this case, the file device.h
+ must contain a vendor-specific implementation of this function.
+ */
+__STATIC_INLINE uint32_t SysTick_Config(uint32_t ticks)
+{
+ 80001c8: b580 push {r7, lr}
+ 80001ca: b082 sub sp, #8
+ 80001cc: af00 add r7, sp, #0
+ 80001ce: 6078 str r0, [r7, #4]
+ if ((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk)
+ 80001d0: 687b ldr r3, [r7, #4]
+ 80001d2: 1e5a subs r2, r3, #1
+ 80001d4: 2380 movs r3, #128 ; 0x80
+ 80001d6: 045b lsls r3, r3, #17
+ 80001d8: 429a cmp r2, r3
+ 80001da: d301 bcc.n 80001e0
+ {
+ return (1UL); /* Reload value impossible */
+ 80001dc: 2301 movs r3, #1
+ 80001de: e010 b.n 8000202
+ }
+
+ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* set reload register */
+ 80001e0: 4b0a ldr r3, [pc, #40] ; (800020c )
+ 80001e2: 687a ldr r2, [r7, #4]
+ 80001e4: 3a01 subs r2, #1
+ 80001e6: 605a str r2, [r3, #4]
+ NVIC_SetPriority (SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* set Priority for Systick Interrupt */
+ 80001e8: 2301 movs r3, #1
+ 80001ea: 425b negs r3, r3
+ 80001ec: 2103 movs r1, #3
+ 80001ee: 0018 movs r0, r3
+ 80001f0: f7ff ff7c bl 80000ec
+ SysTick->VAL = 0UL; /* Load the SysTick Counter Value */
+ 80001f4: 4b05 ldr r3, [pc, #20] ; (800020c )
+ 80001f6: 2200 movs r2, #0
+ 80001f8: 609a str r2, [r3, #8]
+ SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk |
+ 80001fa: 4b04 ldr r3, [pc, #16] ; (800020c )
+ 80001fc: 2207 movs r2, #7
+ 80001fe: 601a str r2, [r3, #0]
+ SysTick_CTRL_TICKINT_Msk |
+ SysTick_CTRL_ENABLE_Msk; /* Enable SysTick IRQ and SysTick Timer */
+ return (0UL); /* Function successful */
+ 8000200: 2300 movs r3, #0
+}
+ 8000202: 0018 movs r0, r3
+ 8000204: 46bd mov sp, r7
+ 8000206: b002 add sp, #8
+ 8000208: bd80 pop {r7, pc}
+ 800020a: 46c0 nop ; (mov r8, r8)
+ 800020c: e000e010 .word 0xe000e010
+
+08000210 :
+#include "serial.h"
+
+
+volatile unsigned int sys_time_seconds = 0;
+
+void update_leds() {
+ 8000210: b580 push {r7, lr}
+ 8000212: af00 add r7, sp, #0
+
+}
+ 8000214: 46c0 nop ; (mov r8, r8)
+ 8000216: 46bd mov sp, r7
+ 8000218: bd80 pop {r7, pc}
+
+0800021a :
+ unsigned int usb, ocxo, error, _nc1, _nc2, _nc3, pps, sd_card;
+ };
+ unsigned int arr[0];
+} leds;
+
+int main(void) {
+ 800021a: b580 push {r7, lr}
+ 800021c: b082 sub sp, #8
+ 800021e: af00 add r7, sp, #0
+ RCC->CR |= RCC_CR_HSEON;
+ 8000220: 4b5b ldr r3, [pc, #364] ; (8000390 )
+ 8000222: 681a ldr r2, [r3, #0]
+ 8000224: 4b5a ldr r3, [pc, #360] ; (8000390 )
+ 8000226: 2180 movs r1, #128 ; 0x80
+ 8000228: 0249 lsls r1, r1, #9
+ 800022a: 430a orrs r2, r1
+ 800022c: 601a str r2, [r3, #0]
+ while (!(RCC->CR&RCC_CR_HSERDY));
+ 800022e: 46c0 nop ; (mov r8, r8)
+ 8000230: 4b57 ldr r3, [pc, #348] ; (8000390 )
+ 8000232: 681a ldr r2, [r3, #0]
+ 8000234: 2380 movs r3, #128 ; 0x80
+ 8000236: 029b lsls r3, r3, #10
+ 8000238: 4013 ands r3, r2
+ 800023a: d0f9 beq.n 8000230
+ RCC->CFGR &= ~RCC_CFGR_PLLMUL_Msk & ~RCC_CFGR_SW_Msk & ~RCC_CFGR_PPRE_Msk & ~RCC_CFGR_HPRE_Msk;
+ 800023c: 4b54 ldr r3, [pc, #336] ; (8000390 )
+ 800023e: 685a ldr r2, [r3, #4]
+ 8000240: 4b53 ldr r3, [pc, #332] ; (8000390 )
+ 8000242: 4954 ldr r1, [pc, #336] ; (8000394 )
+ 8000244: 400a ands r2, r1
+ 8000246: 605a str r2, [r3, #4]
+ RCC->CFGR |= ((6-2)< 48.0MHz */
+ 8000248: 4b51 ldr r3, [pc, #324] ; (8000390 )
+ 800024a: 685a ldr r2, [r3, #4]
+ 800024c: 4b50 ldr r3, [pc, #320] ; (8000390 )
+ 800024e: 2188 movs r1, #136 ; 0x88
+ 8000250: 0349 lsls r1, r1, #13
+ 8000252: 430a orrs r2, r1
+ 8000254: 605a str r2, [r3, #4]
+ RCC->CR |= RCC_CR_PLLON;
+ 8000256: 4b4e ldr r3, [pc, #312] ; (8000390 )
+ 8000258: 681a ldr r2, [r3, #0]
+ 800025a: 4b4d ldr r3, [pc, #308] ; (8000390 )
+ 800025c: 2180 movs r1, #128 ; 0x80
+ 800025e: 0449 lsls r1, r1, #17
+ 8000260: 430a orrs r2, r1
+ 8000262: 601a str r2, [r3, #0]
+ while (!(RCC->CR&RCC_CR_PLLRDY));
+ 8000264: 46c0 nop ; (mov r8, r8)
+ 8000266: 4b4a ldr r3, [pc, #296] ; (8000390 )
+ 8000268: 681a ldr r2, [r3, #0]
+ 800026a: 2380 movs r3, #128 ; 0x80
+ 800026c: 049b lsls r3, r3, #18
+ 800026e: 4013 ands r3, r2
+ 8000270: d0f9 beq.n 8000266
+ RCC->CFGR |= (2<)
+ 8000274: 685a ldr r2, [r3, #4]
+ 8000276: 4b46 ldr r3, [pc, #280] ; (8000390 )
+ 8000278: 2102 movs r1, #2
+ 800027a: 430a orrs r2, r1
+ 800027c: 605a str r2, [r3, #4]
+ SystemCoreClockUpdate();
+ 800027e: f000 fe11 bl 8000ea4
+ SysTick_Config(SystemCoreClock/10); /* 100ms interval */
+ 8000282: 4b45 ldr r3, [pc, #276] ; (8000398 )
+ 8000284: 681b ldr r3, [r3, #0]
+ 8000286: 210a movs r1, #10
+ 8000288: 0018 movs r0, r3
+ 800028a: f001 f98d bl 80015a8 <__udivsi3>
+ 800028e: 0003 movs r3, r0
+ 8000290: 0018 movs r0, r3
+ 8000292: f7ff ff99 bl 80001c8
+ NVIC_EnableIRQ(SysTick_IRQn);
+ 8000296: 2301 movs r3, #1
+ 8000298: 425b negs r3, r3
+ 800029a: 0018 movs r0, r3
+ 800029c: f7ff ff10 bl 80000c0
+ NVIC_SetPriority(SysTick_IRQn, 3<<5);
+ 80002a0: 2301 movs r3, #1
+ 80002a2: 425b negs r3, r3
+ 80002a4: 2160 movs r1, #96 ; 0x60
+ 80002a6: 0018 movs r0, r3
+ 80002a8: f7ff ff20 bl 80000ec
+
+ /* Turn on lots of neat things */
+ RCC->AHBENR |= RCC_AHBENR_DMAEN | RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_FLITFEN;
+ 80002ac: 4b38 ldr r3, [pc, #224] ; (8000390 )
+ 80002ae: 695a ldr r2, [r3, #20]
+ 80002b0: 4b37 ldr r3, [pc, #220] ; (8000390 )
+ 80002b2: 493a ldr r1, [pc, #232] ; (800039c )
+ 80002b4: 430a orrs r2, r1
+ 80002b6: 615a str r2, [r3, #20]
+ RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_ADCEN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_DBGMCUEN |\
+ 80002b8: 4b35 ldr r3, [pc, #212] ; (8000390 )
+ 80002ba: 699a ldr r2, [r3, #24]
+ 80002bc: 4b34 ldr r3, [pc, #208] ; (8000390 )
+ 80002be: 4938 ldr r1, [pc, #224] ; (80003a0 )
+ 80002c0: 430a orrs r2, r1
+ 80002c2: 619a str r2, [r3, #24]
+ RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN | RCC_APB2ENR_USART1EN;
+ RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
+ 80002c4: 4b32 ldr r3, [pc, #200] ; (8000390 )
+ 80002c6: 69da ldr r2, [r3, #28]
+ 80002c8: 4b31 ldr r3, [pc, #196] ; (8000390 )
+ 80002ca: 2102 movs r1, #2
+ 80002cc: 430a orrs r2, r1
+ 80002ce: 61da str r2, [r3, #28]
+
+ GPIOA->MODER |=
+ 80002d0: 2390 movs r3, #144 ; 0x90
+ 80002d2: 05db lsls r3, r3, #23
+ 80002d4: 681a ldr r2, [r3, #0]
+ 80002d6: 2390 movs r3, #144 ; 0x90
+ 80002d8: 05db lsls r3, r3, #23
+ 80002da: 4932 ldr r1, [pc, #200] ; (80003a4 )
+ 80002dc: 430a orrs r2, r1
+ 80002de: 601a str r2, [r3, #0]
+ | (2<OSPEEDR |=
+ 80002e0: 2390 movs r3, #144 ; 0x90
+ 80002e2: 05db lsls r3, r3, #23
+ 80002e4: 689a ldr r2, [r3, #8]
+ 80002e6: 2390 movs r3, #144 ; 0x90
+ 80002e8: 05db lsls r3, r3, #23
+ 80002ea: 492f ldr r1, [pc, #188] ; (80003a8 )
+ 80002ec: 430a orrs r2, r1
+ 80002ee: 609a str r2, [r3, #8]
+ | (2<AFR[0] = (0<AFR[1] = (1<<8) | (1<<4);
+ 80002f8: 2390 movs r3, #144 ; 0x90
+ 80002fa: 05db lsls r3, r3, #23
+ 80002fc: 2288 movs r2, #136 ; 0x88
+ 80002fe: 0052 lsls r2, r2, #1
+ 8000300: 625a str r2, [r3, #36] ; 0x24
+
+ GPIOB->MODER |=
+ 8000302: 4a2a ldr r2, [pc, #168] ; (80003ac )
+ 8000304: 4b29 ldr r3, [pc, #164] ; (80003ac )
+ 8000306: 6812 ldr r2, [r2, #0]
+ 8000308: 601a str r2, [r3, #0]
+ (0<CR1 =
+ 800030a: 4b29 ldr r3, [pc, #164] ; (80003b0 )
+ 800030c: 22c9 movs r2, #201 ; 0xc9
+ 800030e: 0092 lsls r2, r2, #2
+ 8000310: 601a str r2, [r3, #0]
+ SPI_CR1_SSM
+ | SPI_CR1_SSI
+ | (4<CR2 = (7<)
+ 8000314: 22e0 movs r2, #224 ; 0xe0
+ 8000316: 00d2 lsls r2, r2, #3
+ 8000318: 605a str r2, [r3, #4]
+ SPI1->CR1 |= SPI_CR1_SPE;
+ 800031a: 4b25 ldr r3, [pc, #148] ; (80003b0 )
+ 800031c: 681a ldr r2, [r3, #0]
+ 800031e: 4b24 ldr r3, [pc, #144] ; (80003b0 )
+ 8000320: 2140 movs r1, #64 ; 0x40
+ 8000322: 430a orrs r2, r1
+ 8000324: 601a str r2, [r3, #0]
+
+ NVIC_EnableIRQ(SPI1_IRQn);
+ 8000326: 2019 movs r0, #25
+ 8000328: f7ff feca bl 80000c0
+ NVIC_SetPriority(SPI1_IRQn, 2<<5);
+ 800032c: 2140 movs r1, #64 ; 0x40
+ 800032e: 2019 movs r0, #25
+ 8000330: f7ff fedc bl 80000ec
+
+ TIM16->CR2 = 0;
+ 8000334: 4b1f ldr r3, [pc, #124] ; (80003b4 )
+ 8000336: 2200 movs r2, #0
+ 8000338: 605a str r2, [r3, #4]
+ TIM16->DIER = TIM_DIER_UIE;
+ 800033a: 4b1e ldr r3, [pc, #120] ; (80003b4 )
+ 800033c: 2201 movs r2, #1
+ 800033e: 60da str r2, [r3, #12]
+ TIM16->PSC = 48-1; /* 1us */
+ 8000340: 4b1c ldr r3, [pc, #112] ; (80003b4 )
+ 8000342: 222f movs r2, #47 ; 0x2f
+ 8000344: 629a str r2, [r3, #40] ; 0x28
+ TIM16->ARR = 1000-1; /* 1ms */
+ 8000346: 4b1b ldr r3, [pc, #108] ; (80003b4 )
+ 8000348: 4a1b ldr r2, [pc, #108] ; (80003b8 )
+ 800034a: 62da str r2, [r3, #44] ; 0x2c
+ TIM16->CR1 = TIM_CR1_CEN;
+ 800034c: 4b19 ldr r3, [pc, #100] ; (80003b4 )
+ 800034e: 2201 movs r2, #1
+ 8000350: 601a str r2, [r3, #0]
+
+ NVIC_EnableIRQ(TIM16_IRQn);
+ 8000352: 2015 movs r0, #21
+ 8000354: f7ff feb4 bl 80000c0
+ NVIC_SetPriority(TIM16_IRQn, 2<<5);
+ 8000358: 2140 movs r1, #64 ; 0x40
+ 800035a: 2015 movs r0, #21
+ 800035c: f7ff fec6 bl 80000ec
+
+ adc_configure_scope_mode(1000000);
+ 8000360: 4b16 ldr r3, [pc, #88] ; (80003bc )
+ 8000362: 0018 movs r0, r3
+ 8000364: f000 f95a bl 800061c
+
+ usart_dma_init();
+ 8000368: f000 fabe bl 80008e8
+
+ while (42) {
+ char *data = "FOOBAR\n";
+ 800036c: 4b14 ldr r3, [pc, #80] ; (80003c0 )
+ 800036e: 603b str r3, [r7, #0]
+ usart_send_packet((uint8_t*)data, 8);
+ 8000370: 683b ldr r3, [r7, #0]
+ 8000372: 2108 movs r1, #8
+ 8000374: 0018 movs r0, r3
+ 8000376: f000 fb91 bl 8000a9c
+ for (int i=0; i<100000; i++);
+ 800037a: 2300 movs r3, #0
+ 800037c: 607b str r3, [r7, #4]
+ 800037e: e002 b.n 8000386
+ 8000380: 687b ldr r3, [r7, #4]
+ 8000382: 3301 adds r3, #1
+ 8000384: 607b str r3, [r7, #4]
+ 8000386: 687b ldr r3, [r7, #4]
+ 8000388: 4a0e ldr r2, [pc, #56] ; (80003c4 )
+ 800038a: 4293 cmp r3, r2
+ 800038c: ddf8 ble.n 8000380
+ while (42) {
+ 800038e: e7ed b.n 800036c
+ 8000390: 40021000 .word 0x40021000
+ 8000394: ffc3f80c .word 0xffc3f80c
+ 8000398: 20000000 .word 0x20000000
+ 800039c: 00060011 .word 0x00060011
+ 80003a0: 00425a01 .word 0x00425a01
+ 80003a4: 0028a970 .word 0x0028a970
+ 80003a8: 00088a80 .word 0x00088a80
+ 80003ac: 48000400 .word 0x48000400
+ 80003b0: 40013000 .word 0x40013000
+ 80003b4: 40014400 .word 0x40014400
+ 80003b8: 000003e7 .word 0x000003e7
+ 80003bc: 000f4240 .word 0x000f4240
+ 80003c0: 080018e4 .word 0x080018e4
+ 80003c4: 0001869f .word 0x0001869f
+
+080003c8 :
+ //for (int i=0; i<10000; i++) ;
+ //leds.error = 100;
+ }
+}
+
+void SPI1_IRQHandler(void) {
+ 80003c8: b580 push {r7, lr}
+ 80003ca: af00 add r7, sp, #0
+ if (SPI1->SR & SPI_SR_TXE) {
+ 80003cc: 4b08 ldr r3, [pc, #32] ; (80003f0 )
+ 80003ce: 689b ldr r3, [r3, #8]
+ 80003d0: 2202 movs r2, #2
+ 80003d2: 4013 ands r3, r2
+ 80003d4: d009 beq.n 80003ea
+ /* LED_STB */
+ GPIOA->BSRR = 1<<3;
+ 80003d6: 2390 movs r3, #144 ; 0x90
+ 80003d8: 05db lsls r3, r3, #23
+ 80003da: 2208 movs r2, #8
+ 80003dc: 619a str r2, [r3, #24]
+ SPI1->CR2 &= ~SPI_CR2_TXEIE;
+ 80003de: 4b04 ldr r3, [pc, #16] ; (80003f0 )
+ 80003e0: 685a ldr r2, [r3, #4]
+ 80003e2: 4b03 ldr r3, [pc, #12] ; (80003f0 )
+ 80003e4: 2180 movs r1, #128 ; 0x80
+ 80003e6: 438a bics r2, r1
+ 80003e8: 605a str r2, [r3, #4]
+ }
+}
+ 80003ea: 46c0 nop ; (mov r8, r8)
+ 80003ec: 46bd mov sp, r7
+ 80003ee: bd80 pop {r7, pc}
+ 80003f0: 40013000 .word 0x40013000
+
+080003f4 :
+
+void TIM16_IRQHandler(void) {
+ 80003f4: b580 push {r7, lr}
+ 80003f6: b082 sub sp, #8
+ 80003f8: af00 add r7, sp, #0
+ static int leds_update_counter = 0;
+ if (TIM16->SR & TIM_SR_UIF) {
+ 80003fa: 4b28 ldr r3, [pc, #160] ; (800049c )
+ 80003fc: 691b ldr r3, [r3, #16]
+ 80003fe: 2201 movs r2, #1
+ 8000400: 4013 ands r3, r2
+ 8000402: d047 beq.n 8000494
+ TIM16->SR &= ~TIM_SR_UIF;
+ 8000404: 4b25 ldr r3, [pc, #148] ; (800049c )
+ 8000406: 691a ldr r2, [r3, #16]
+ 8000408: 4b24 ldr r3, [pc, #144] ; (800049c )
+ 800040a: 2101 movs r1, #1
+ 800040c: 438a bics r2, r1
+ 800040e: 611a str r2, [r3, #16]
+
+ uint8_t bits = 0, mask = 1;
+ 8000410: 1dfb adds r3, r7, #7
+ 8000412: 2200 movs r2, #0
+ 8000414: 701a strb r2, [r3, #0]
+ 8000416: 1dbb adds r3, r7, #6
+ 8000418: 2201 movs r2, #1
+ 800041a: 701a strb r2, [r3, #0]
+ for (size_t i=0; i
+ if (leds.arr[i]) {
+ 8000422: 4b1f ldr r3, [pc, #124] ; (80004a0 )
+ 8000424: 683a ldr r2, [r7, #0]
+ 8000426: 0092 lsls r2, r2, #2
+ 8000428: 58d3 ldr r3, [r2, r3]
+ 800042a: 2b00 cmp r3, #0
+ 800042c: d00f beq.n 800044e
+ leds.arr[i]--;
+ 800042e: 4b1c ldr r3, [pc, #112] ; (80004a0 )
+ 8000430: 683a ldr r2, [r7, #0]
+ 8000432: 0092 lsls r2, r2, #2
+ 8000434: 58d3 ldr r3, [r2, r3]
+ 8000436: 1e59 subs r1, r3, #1
+ 8000438: 4b19 ldr r3, [pc, #100] ; (80004a0 )
+ 800043a: 683a ldr r2, [r7, #0]
+ 800043c: 0092 lsls r2, r2, #2
+ 800043e: 50d1 str r1, [r2, r3]
+ bits |= mask;
+ 8000440: 1dfb adds r3, r7, #7
+ 8000442: 1df9 adds r1, r7, #7
+ 8000444: 1dba adds r2, r7, #6
+ 8000446: 7809 ldrb r1, [r1, #0]
+ 8000448: 7812 ldrb r2, [r2, #0]
+ 800044a: 430a orrs r2, r1
+ 800044c: 701a strb r2, [r3, #0]
+ }
+ mask <<= 1;
+ 800044e: 1dba adds r2, r7, #6
+ 8000450: 1dbb adds r3, r7, #6
+ 8000452: 781b ldrb r3, [r3, #0]
+ 8000454: 18db adds r3, r3, r3
+ 8000456: 7013 strb r3, [r2, #0]
+ for (size_t i=0; i
+ }
+
+ if (leds_update_counter++ == 10) {
+ 8000464: 4b0f ldr r3, [pc, #60] ; (80004a4 )
+ 8000466: 681b ldr r3, [r3, #0]
+ 8000468: 1c59 adds r1, r3, #1
+ 800046a: 4a0e ldr r2, [pc, #56] ; (80004a4 )
+ 800046c: 6011 str r1, [r2, #0]
+ 800046e: 2b0a cmp r3, #10
+ 8000470: d110 bne.n 8000494
+ leds_update_counter = 0;
+ 8000472: 4b0c ldr r3, [pc, #48] ; (80004a4 )
+ 8000474: 2200 movs r2, #0
+ 8000476: 601a str r2, [r3, #0]
+
+ /* Workaround for SPI hardware bug: Even if configured to 8-bit mode, the SPI will do a 16-bit transfer if the
+ * data register is accessed through a 16-bit write. Unfortunately, the STMCube register defs define DR as an
+ * uint16_t, so we have to do some magic here to force an 8-bit write. */
+ *((volatile uint8_t*)&(SPI1->DR)) = bits;
+ 8000478: 4a0b ldr r2, [pc, #44] ; (80004a8 )
+ 800047a: 1dfb adds r3, r7, #7
+ 800047c: 781b ldrb r3, [r3, #0]
+ 800047e: 7013 strb r3, [r2, #0]
+ SPI1->CR2 |= SPI_CR2_TXEIE;
+ 8000480: 4b0a ldr r3, [pc, #40] ; (80004ac )
+ 8000482: 685a ldr r2, [r3, #4]
+ 8000484: 4b09 ldr r3, [pc, #36] ; (80004ac )
+ 8000486: 2180 movs r1, #128 ; 0x80
+ 8000488: 430a orrs r2, r1
+ 800048a: 605a str r2, [r3, #4]
+ GPIOA->BRR = 1<<3;
+ 800048c: 2390 movs r3, #144 ; 0x90
+ 800048e: 05db lsls r3, r3, #23
+ 8000490: 2208 movs r2, #8
+ 8000492: 629a str r2, [r3, #40] ; 0x28
+ }
+ }
+}
+ 8000494: 46c0 nop ; (mov r8, r8)
+ 8000496: 46bd mov sp, r7
+ 8000498: b002 add sp, #8
+ 800049a: bd80 pop {r7, pc}
+ 800049c: 40014400 .word 0x40014400
+ 80004a0: 200000a8 .word 0x200000a8
+ 80004a4: 20000098 .word 0x20000098
+ 80004a8: 4001300c .word 0x4001300c
+ 80004ac: 40013000 .word 0x40013000
+
+080004b0 :
+
+void NMI_Handler(void) {
+ 80004b0: b580 push {r7, lr}
+ 80004b2: af00 add r7, sp, #0
+ asm volatile ("bkpt");
+ 80004b4: be00 bkpt 0x0000
+}
+ 80004b6: 46c0 nop ; (mov r8, r8)
+ 80004b8: 46bd mov sp, r7
+ 80004ba: bd80 pop {r7, pc}
+
+080004bc :
+
+void HardFault_Handler(void) __attribute__((naked));
+void HardFault_Handler() {
+ asm volatile ("bkpt");
+ 80004bc: be00 bkpt 0x0000
+}
+ 80004be: 46c0 nop ; (mov r8, r8)
+
+080004c0 :
+
+void SVC_Handler(void) {
+ 80004c0: b580 push {r7, lr}
+ 80004c2: af00 add r7, sp, #0
+ asm volatile ("bkpt");
+ 80004c4: be00 bkpt 0x0000
+}
+ 80004c6: 46c0 nop ; (mov r8, r8)
+ 80004c8: 46bd mov sp, r7
+ 80004ca: bd80 pop {r7, pc}
+
+080004cc :
+
+
+void PendSV_Handler(void) {
+ 80004cc: b580 push {r7, lr}
+ 80004ce: af00 add r7, sp, #0
+ asm volatile ("bkpt");
+ 80004d0: be00 bkpt 0x0000
+}
+ 80004d2: 46c0 nop ; (mov r8, r8)
+ 80004d4: 46bd mov sp, r7
+ 80004d6: bd80 pop {r7, pc}
+
+080004d8 :
+
+void SysTick_Handler(void) {
+ 80004d8: b580 push {r7, lr}
+ 80004da: af00 add r7, sp, #0
+ static int n = 0;
+ if (n++ == 10) {
+ 80004dc: 4b0a ldr r3, [pc, #40] ; (8000508 )
+ 80004de: 681b ldr r3, [r3, #0]
+ 80004e0: 1c59 adds r1, r3, #1
+ 80004e2: 4a09 ldr r2, [pc, #36] ; (8000508 )
+ 80004e4: 6011 str r1, [r2, #0]
+ 80004e6: 2b0a cmp r3, #10
+ 80004e8: d10a bne.n 8000500
+ n = 0;
+ 80004ea: 4b07 ldr r3, [pc, #28] ; (8000508 )
+ 80004ec: 2200 movs r2, #0
+ 80004ee: 601a str r2, [r3, #0]
+ sys_time_seconds++;
+ 80004f0: 4b06 ldr r3, [pc, #24] ; (800050c )
+ 80004f2: 681b ldr r3, [r3, #0]
+ 80004f4: 1c5a adds r2, r3, #1
+ 80004f6: 4b05 ldr r3, [pc, #20] ; (800050c )
+ 80004f8: 601a str r2, [r3, #0]
+ leds.pps = 100; /* ms */
+ 80004fa: 4b05 ldr r3, [pc, #20] ; (8000510 )
+ 80004fc: 2264 movs r2, #100 ; 0x64
+ 80004fe: 619a str r2, [r3, #24]
+ }
+}
+ 8000500: 46c0 nop ; (mov r8, r8)
+ 8000502: 46bd mov sp, r7
+ 8000504: bd80 pop {r7, pc}
+ 8000506: 46c0 nop ; (mov r8, r8)
+ 8000508: 2000009c .word 0x2000009c
+ 800050c: 20000094 .word 0x20000094
+ 8000510: 200000a8 .word 0x200000a8
+
+08000514 :
+{
+ 8000514: b580 push {r7, lr}
+ 8000516: b082 sub sp, #8
+ 8000518: af00 add r7, sp, #0
+ 800051a: 0002 movs r2, r0
+ 800051c: 1dfb adds r3, r7, #7
+ 800051e: 701a strb r2, [r3, #0]
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ 8000520: 1dfb adds r3, r7, #7
+ 8000522: 781b ldrb r3, [r3, #0]
+ 8000524: 001a movs r2, r3
+ 8000526: 231f movs r3, #31
+ 8000528: 401a ands r2, r3
+ 800052a: 4b04 ldr r3, [pc, #16] ; (800053c )
+ 800052c: 2101 movs r1, #1
+ 800052e: 4091 lsls r1, r2
+ 8000530: 000a movs r2, r1
+ 8000532: 601a str r2, [r3, #0]
+}
+ 8000534: 46c0 nop ; (mov r8, r8)
+ 8000536: 46bd mov sp, r7
+ 8000538: b002 add sp, #8
+ 800053a: bd80 pop {r7, pc}
+ 800053c: e000e100 .word 0xe000e100
+
+08000540 :
+{
+ 8000540: b590 push {r4, r7, lr}
+ 8000542: b083 sub sp, #12
+ 8000544: af00 add r7, sp, #0
+ 8000546: 0002 movs r2, r0
+ 8000548: 6039 str r1, [r7, #0]
+ 800054a: 1dfb adds r3, r7, #7
+ 800054c: 701a strb r2, [r3, #0]
+ if ((int32_t)(IRQn) < 0)
+ 800054e: 1dfb adds r3, r7, #7
+ 8000550: 781b ldrb r3, [r3, #0]
+ 8000552: 2b7f cmp r3, #127 ; 0x7f
+ 8000554: d932 bls.n 80005bc
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 8000556: 4a2f ldr r2, [pc, #188] ; (8000614 )
+ 8000558: 1dfb adds r3, r7, #7
+ 800055a: 781b ldrb r3, [r3, #0]
+ 800055c: 0019 movs r1, r3
+ 800055e: 230f movs r3, #15
+ 8000560: 400b ands r3, r1
+ 8000562: 3b08 subs r3, #8
+ 8000564: 089b lsrs r3, r3, #2
+ 8000566: 3306 adds r3, #6
+ 8000568: 009b lsls r3, r3, #2
+ 800056a: 18d3 adds r3, r2, r3
+ 800056c: 3304 adds r3, #4
+ 800056e: 681b ldr r3, [r3, #0]
+ 8000570: 1dfa adds r2, r7, #7
+ 8000572: 7812 ldrb r2, [r2, #0]
+ 8000574: 0011 movs r1, r2
+ 8000576: 2203 movs r2, #3
+ 8000578: 400a ands r2, r1
+ 800057a: 00d2 lsls r2, r2, #3
+ 800057c: 21ff movs r1, #255 ; 0xff
+ 800057e: 4091 lsls r1, r2
+ 8000580: 000a movs r2, r1
+ 8000582: 43d2 mvns r2, r2
+ 8000584: 401a ands r2, r3
+ 8000586: 0011 movs r1, r2
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ 8000588: 683b ldr r3, [r7, #0]
+ 800058a: 019b lsls r3, r3, #6
+ 800058c: 22ff movs r2, #255 ; 0xff
+ 800058e: 401a ands r2, r3
+ 8000590: 1dfb adds r3, r7, #7
+ 8000592: 781b ldrb r3, [r3, #0]
+ 8000594: 0018 movs r0, r3
+ 8000596: 2303 movs r3, #3
+ 8000598: 4003 ands r3, r0
+ 800059a: 00db lsls r3, r3, #3
+ 800059c: 409a lsls r2, r3
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 800059e: 481d ldr r0, [pc, #116] ; (8000614 )
+ 80005a0: 1dfb adds r3, r7, #7
+ 80005a2: 781b ldrb r3, [r3, #0]
+ 80005a4: 001c movs r4, r3
+ 80005a6: 230f movs r3, #15
+ 80005a8: 4023 ands r3, r4
+ 80005aa: 3b08 subs r3, #8
+ 80005ac: 089b lsrs r3, r3, #2
+ 80005ae: 430a orrs r2, r1
+ 80005b0: 3306 adds r3, #6
+ 80005b2: 009b lsls r3, r3, #2
+ 80005b4: 18c3 adds r3, r0, r3
+ 80005b6: 3304 adds r3, #4
+ 80005b8: 601a str r2, [r3, #0]
+}
+ 80005ba: e027 b.n 800060c
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 80005bc: 4a16 ldr r2, [pc, #88] ; (8000618 )
+ 80005be: 1dfb adds r3, r7, #7
+ 80005c0: 781b ldrb r3, [r3, #0]
+ 80005c2: b25b sxtb r3, r3
+ 80005c4: 089b lsrs r3, r3, #2
+ 80005c6: 33c0 adds r3, #192 ; 0xc0
+ 80005c8: 009b lsls r3, r3, #2
+ 80005ca: 589b ldr r3, [r3, r2]
+ 80005cc: 1dfa adds r2, r7, #7
+ 80005ce: 7812 ldrb r2, [r2, #0]
+ 80005d0: 0011 movs r1, r2
+ 80005d2: 2203 movs r2, #3
+ 80005d4: 400a ands r2, r1
+ 80005d6: 00d2 lsls r2, r2, #3
+ 80005d8: 21ff movs r1, #255 ; 0xff
+ 80005da: 4091 lsls r1, r2
+ 80005dc: 000a movs r2, r1
+ 80005de: 43d2 mvns r2, r2
+ 80005e0: 401a ands r2, r3
+ 80005e2: 0011 movs r1, r2
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ 80005e4: 683b ldr r3, [r7, #0]
+ 80005e6: 019b lsls r3, r3, #6
+ 80005e8: 22ff movs r2, #255 ; 0xff
+ 80005ea: 401a ands r2, r3
+ 80005ec: 1dfb adds r3, r7, #7
+ 80005ee: 781b ldrb r3, [r3, #0]
+ 80005f0: 0018 movs r0, r3
+ 80005f2: 2303 movs r3, #3
+ 80005f4: 4003 ands r3, r0
+ 80005f6: 00db lsls r3, r3, #3
+ 80005f8: 409a lsls r2, r3
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 80005fa: 4807 ldr r0, [pc, #28] ; (8000618 )
+ 80005fc: 1dfb adds r3, r7, #7
+ 80005fe: 781b ldrb r3, [r3, #0]
+ 8000600: b25b sxtb r3, r3
+ 8000602: 089b lsrs r3, r3, #2
+ 8000604: 430a orrs r2, r1
+ 8000606: 33c0 adds r3, #192 ; 0xc0
+ 8000608: 009b lsls r3, r3, #2
+ 800060a: 501a str r2, [r3, r0]
+}
+ 800060c: 46c0 nop ; (mov r8, r8)
+ 800060e: 46bd mov sp, r7
+ 8000610: b003 add sp, #12
+ 8000612: bd90 pop {r4, r7, pc}
+ 8000614: e000ed00 .word 0xe000ed00
+ 8000618: e000e100 .word 0xe000e100
+
+0800061c :
+static void adc_dma_init(int burstlen);
+static void adc_timer_init(int psc, int ivl);
+
+
+/* Mode that can be used for debugging */
+void adc_configure_scope_mode(int sampling_interval_ns) {
+ 800061c: b580 push {r7, lr}
+ 800061e: b084 sub sp, #16
+ 8000620: af00 add r7, sp, #0
+ 8000622: 6078 str r0, [r7, #4]
+ adc_dma_init(sizeof(adc_buf)/sizeof(adc_buf[0]));
+ 8000624: 2380 movs r3, #128 ; 0x80
+ 8000626: 00db lsls r3, r3, #3
+ 8000628: 0018 movs r0, r3
+ 800062a: f000 f84b bl 80006c4
+
+ /* Clock from PCLK/4 instead of the internal exclusive high-speed RC oscillator. */
+ ADC1->CFGR2 = (2<)
+ 8000630: 2280 movs r2, #128 ; 0x80
+ 8000632: 0612 lsls r2, r2, #24
+ 8000634: 611a str r2, [r3, #16]
+ /* Sampling time 239.5 ADC clock cycles -> total conversion time 38.5us*/
+ ADC1->SMPR = (7<)
+ 8000638: 2207 movs r2, #7
+ 800063a: 615a str r2, [r3, #20]
+
+ /* Setup DMA and triggering */
+ /* Trigger from TIM1 TRGO */
+ ADC1->CFGR1 = ADC_CFGR1_DMAEN | ADC_CFGR1_DMACFG | (2<)
+ 800063e: 4a1e ldr r2, [pc, #120] ; (80006b8 )
+ 8000640: 60da str r2, [r3, #12]
+ ADC1->CHSELR = ADC_CHSELR_CHSEL2;
+ 8000642: 4b1c ldr r3, [pc, #112] ; (80006b4 )
+ 8000644: 2204 movs r2, #4
+ 8000646: 629a str r2, [r3, #40] ; 0x28
+ /* Perform self-calibration */
+ ADC1->CR |= ADC_CR_ADCAL;
+ 8000648: 4b1a ldr r3, [pc, #104] ; (80006b4 )
+ 800064a: 689a ldr r2, [r3, #8]
+ 800064c: 4b19 ldr r3, [pc, #100] ; (80006b4 )
+ 800064e: 2180 movs r1, #128 ; 0x80
+ 8000650: 0609 lsls r1, r1, #24
+ 8000652: 430a orrs r2, r1
+ 8000654: 609a str r2, [r3, #8]
+ while (ADC1->CR & ADC_CR_ADCAL)
+ 8000656: 46c0 nop ; (mov r8, r8)
+ 8000658: 4b16 ldr r3, [pc, #88] ; (80006b4 )
+ 800065a: 689b ldr r3, [r3, #8]
+ 800065c: 2b00 cmp r3, #0
+ 800065e: dbfb blt.n 8000658
+ ;
+ /* Enable conversion */
+ ADC1->CR |= ADC_CR_ADEN;
+ 8000660: 4b14 ldr r3, [pc, #80] ; (80006b4 )
+ 8000662: 689a ldr r2, [r3, #8]
+ 8000664: 4b13 ldr r3, [pc, #76] ; (80006b4 )
+ 8000666: 2101 movs r1, #1
+ 8000668: 430a orrs r2, r1
+ 800066a: 609a str r2, [r3, #8]
+ ADC1->CR |= ADC_CR_ADSTART;
+ 800066c: 4b11 ldr r3, [pc, #68] ; (80006b4 )
+ 800066e: 689a ldr r2, [r3, #8]
+ 8000670: 4b10 ldr r3, [pc, #64] ; (80006b4 )
+ 8000672: 2104 movs r1, #4
+ 8000674: 430a orrs r2, r1
+ 8000676: 609a str r2, [r3, #8]
+
+ /* An ADC conversion takes 1.1667us, so to be sure we don't get data overruns we limit sampling to every 1.5us.
+ Since we don't have a spare PLL to generate the ADC sample clock and re-configuring the system clock just for this
+ would be overkill we round to 250ns increments. The minimum sampling rate is about 60Hz due to timer resolution. */
+ int cycles = sampling_interval_ns > 1500 ? sampling_interval_ns/250 : 6;
+ 8000678: 687b ldr r3, [r7, #4]
+ 800067a: 4a10 ldr r2, [pc, #64] ; (80006bc )
+ 800067c: 4293 cmp r3, r2
+ 800067e: dd06 ble.n 800068e
+ 8000680: 687b ldr r3, [r7, #4]
+ 8000682: 21fa movs r1, #250 ; 0xfa
+ 8000684: 0018 movs r0, r3
+ 8000686: f001 f819 bl 80016bc <__divsi3>
+ 800068a: 0003 movs r3, r0
+ 800068c: e000 b.n 8000690
+ 800068e: 2306 movs r3, #6
+ 8000690: 60fb str r3, [r7, #12]
+ if (cycles > 0xffff)
+ 8000692: 68fa ldr r2, [r7, #12]
+ 8000694: 2380 movs r3, #128 ; 0x80
+ 8000696: 025b lsls r3, r3, #9
+ 8000698: 429a cmp r2, r3
+ 800069a: db01 blt.n 80006a0
+ cycles = 0xffff;
+ 800069c: 4b08 ldr r3, [pc, #32] ; (80006c0 )
+ 800069e: 60fb str r3, [r7, #12]
+ adc_timer_init(12/*250ns/tick*/, cycles);
+ 80006a0: 68fb ldr r3, [r7, #12]
+ 80006a2: 0019 movs r1, r3
+ 80006a4: 200c movs r0, #12
+ 80006a6: f000 f83d bl 8000724
+}
+ 80006aa: 46c0 nop ; (mov r8, r8)
+ 80006ac: 46bd mov sp, r7
+ 80006ae: b004 add sp, #16
+ 80006b0: bd80 pop {r7, pc}
+ 80006b2: 46c0 nop ; (mov r8, r8)
+ 80006b4: 40012400 .word 0x40012400
+ 80006b8: 00000843 .word 0x00000843
+ 80006bc: 000005dc .word 0x000005dc
+ 80006c0: 0000ffff .word 0x0000ffff
+
+080006c4 :
+
+/* FIXME figure out the proper place to configure this. */
+#define ADC_TIMER_INTERVAL_US 20
+
+static void adc_dma_init(int burstlen) {
+ 80006c4: b580 push {r7, lr}
+ 80006c6: b082 sub sp, #8
+ 80006c8: af00 add r7, sp, #0
+ 80006ca: 6078 str r0, [r7, #4]
+ /* Configure DMA 1 Channel 1 to get rid of all the data */
+ DMA1_Channel1->CPAR = (unsigned int)&ADC1->DR;
+ 80006cc: 4b11 ldr r3, [pc, #68] ; (8000714 )
+ 80006ce: 4a12 ldr r2, [pc, #72] ; (8000718 )
+ 80006d0: 609a str r2, [r3, #8]
+ DMA1_Channel1->CMAR = (unsigned int)&adc_buf;
+ 80006d2: 4b10 ldr r3, [pc, #64] ; (8000714 )
+ 80006d4: 4a11 ldr r2, [pc, #68] ; (800071c )
+ 80006d6: 60da str r2, [r3, #12]
+ DMA1_Channel1->CNDTR = burstlen;
+ 80006d8: 4b0e ldr r3, [pc, #56] ; (8000714 )
+ 80006da: 687a ldr r2, [r7, #4]
+ 80006dc: 605a str r2, [r3, #4]
+ DMA1_Channel1->CCR = (0<)
+ 80006e0: 2200 movs r2, #0
+ 80006e2: 601a str r2, [r3, #0]
+ DMA1_Channel1->CCR |=
+ 80006e4: 4b0b ldr r3, [pc, #44] ; (8000714 )
+ 80006e6: 681a ldr r2, [r3, #0]
+ 80006e8: 4b0a ldr r3, [pc, #40] ; (8000714 )
+ 80006ea: 490d ldr r1, [pc, #52] ; (8000720 )
+ 80006ec: 430a orrs r2, r1
+ 80006ee: 601a str r2, [r3, #0]
+ | (1<
+ NVIC_SetPriority(DMA1_Channel1_IRQn, 2<<5);
+ 80006f6: 2140 movs r1, #64 ; 0x40
+ 80006f8: 2009 movs r0, #9
+ 80006fa: f7ff ff21 bl 8000540
+
+ DMA1_Channel1->CCR |= DMA_CCR_EN; /* Enable channel */
+ 80006fe: 4b05 ldr r3, [pc, #20] ; (8000714 )
+ 8000700: 681a ldr r2, [r3, #0]
+ 8000702: 4b04 ldr r3, [pc, #16] ; (8000714 )
+ 8000704: 2101 movs r1, #1
+ 8000706: 430a orrs r2, r1
+ 8000708: 601a str r2, [r3, #0]
+}
+ 800070a: 46c0 nop ; (mov r8, r8)
+ 800070c: 46bd mov sp, r7
+ 800070e: b002 add sp, #8
+ 8000710: bd80 pop {r7, pc}
+ 8000712: 46c0 nop ; (mov r8, r8)
+ 8000714: 40020008 .word 0x40020008
+ 8000718: 40012440 .word 0x40012440
+ 800071c: 200000c8 .word 0x200000c8
+ 8000720: 000005a2 .word 0x000005a2
+
+08000724 :
+
+static void adc_timer_init(int psc, int ivl) {
+ 8000724: b580 push {r7, lr}
+ 8000726: b082 sub sp, #8
+ 8000728: af00 add r7, sp, #0
+ 800072a: 6078 str r0, [r7, #4]
+ 800072c: 6039 str r1, [r7, #0]
+ TIM1->BDTR = TIM_BDTR_MOE; /* MOE is needed even though we only "output" a chip-internal signal TODO: Verify this. */
+ 800072e: 4b15 ldr r3, [pc, #84] ; (8000784 )
+ 8000730: 2280 movs r2, #128 ; 0x80
+ 8000732: 0212 lsls r2, r2, #8
+ 8000734: 645a str r2, [r3, #68] ; 0x44
+ TIM1->CCMR2 = (6<)
+ 8000738: 22c0 movs r2, #192 ; 0xc0
+ 800073a: 01d2 lsls r2, r2, #7
+ 800073c: 61da str r2, [r3, #28]
+ TIM1->CCER = TIM_CCER_CC4E; /* Enable capture/compare unit 4 connected to ADC */
+ 800073e: 4b11 ldr r3, [pc, #68] ; (8000784 )
+ 8000740: 2280 movs r2, #128 ; 0x80
+ 8000742: 0152 lsls r2, r2, #5
+ 8000744: 621a str r2, [r3, #32]
+ TIM1->CCR4 = 1; /* Trigger at start of timer cycle */
+ 8000746: 4b0f ldr r3, [pc, #60] ; (8000784 )
+ 8000748: 2201 movs r2, #1
+ 800074a: 641a str r2, [r3, #64] ; 0x40
+ /* Set prescaler and interval */
+ TIM1->PSC = psc-1;
+ 800074c: 687b ldr r3, [r7, #4]
+ 800074e: 1e5a subs r2, r3, #1
+ 8000750: 4b0c ldr r3, [pc, #48] ; (8000784 )
+ 8000752: 629a str r2, [r3, #40] ; 0x28
+ TIM1->ARR = ivl-1;
+ 8000754: 683b ldr r3, [r7, #0]
+ 8000756: 1e5a subs r2, r3, #1
+ 8000758: 4b0a ldr r3, [pc, #40] ; (8000784 )
+ 800075a: 62da str r2, [r3, #44] ; 0x2c
+ /* Preload all values */
+ TIM1->EGR |= TIM_EGR_UG;
+ 800075c: 4b09 ldr r3, [pc, #36] ; (8000784 )
+ 800075e: 695a ldr r2, [r3, #20]
+ 8000760: 4b08 ldr r3, [pc, #32] ; (8000784 )
+ 8000762: 2101 movs r1, #1
+ 8000764: 430a orrs r2, r1
+ 8000766: 615a str r2, [r3, #20]
+ TIM1->CR1 = TIM_CR1_ARPE;
+ 8000768: 4b06 ldr r3, [pc, #24] ; (8000784 )
+ 800076a: 2280 movs r2, #128 ; 0x80
+ 800076c: 601a str r2, [r3, #0]
+ /* And... go! */
+ TIM1->CR1 |= TIM_CR1_CEN;
+ 800076e: 4b05 ldr r3, [pc, #20] ; (8000784 )
+ 8000770: 681a ldr r2, [r3, #0]
+ 8000772: 4b04 ldr r3, [pc, #16] ; (8000784 )
+ 8000774: 2101 movs r1, #1
+ 8000776: 430a orrs r2, r1
+ 8000778: 601a str r2, [r3, #0]
+}
+ 800077a: 46c0 nop ; (mov r8, r8)
+ 800077c: 46bd mov sp, r7
+ 800077e: b002 add sp, #8
+ 8000780: bd80 pop {r7, pc}
+ 8000782: 46c0 nop ; (mov r8, r8)
+ 8000784: 40012c00 .word 0x40012c00
+
+08000788 :
+
+/* This acts as a no-op that provides a convenient point to set a breakpoint for the debug scope logic */
+static void gdb_dump(void) {
+ 8000788: b580 push {r7, lr}
+ 800078a: af00 add r7, sp, #0
+}
+ 800078c: 46c0 nop ; (mov r8, r8)
+ 800078e: 46bd mov sp, r7
+ 8000790: bd80 pop {r7, pc}
+
+08000792 :
+
+void DMA1_Channel1_IRQHandler(void) {
+ 8000792: b580 push {r7, lr}
+ 8000794: af00 add r7, sp, #0
+ /* Clear the interrupt flag */
+ DMA1->IFCR |= DMA_IFCR_CGIF1;
+ 8000796: 4b05 ldr r3, [pc, #20] ; (80007ac )
+ 8000798: 685a ldr r2, [r3, #4]
+ 800079a: 4b04 ldr r3, [pc, #16] ; (80007ac )
+ 800079c: 2101 movs r1, #1
+ 800079e: 430a orrs r2, r1
+ 80007a0: 605a str r2, [r3, #4]
+ gdb_dump();
+ 80007a2: f7ff fff1 bl 8000788
+ adc_buf[i] = -255;
+ }
+ }
+ }
+ */
+}
+ 80007a6: 46c0 nop ; (mov r8, r8)
+ 80007a8: 46bd mov sp, r7
+ 80007aa: bd80 pop {r7, pc}
+ 80007ac: 40020000 .word 0x40020000
+
+080007b0 :
+{
+ 80007b0: b580 push {r7, lr}
+ 80007b2: b082 sub sp, #8
+ 80007b4: af00 add r7, sp, #0
+ 80007b6: 0002 movs r2, r0
+ 80007b8: 1dfb adds r3, r7, #7
+ 80007ba: 701a strb r2, [r3, #0]
+ NVIC->ISER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ 80007bc: 1dfb adds r3, r7, #7
+ 80007be: 781b ldrb r3, [r3, #0]
+ 80007c0: 001a movs r2, r3
+ 80007c2: 231f movs r3, #31
+ 80007c4: 401a ands r2, r3
+ 80007c6: 4b04 ldr r3, [pc, #16] ; (80007d8 )
+ 80007c8: 2101 movs r1, #1
+ 80007ca: 4091 lsls r1, r2
+ 80007cc: 000a movs r2, r1
+ 80007ce: 601a str r2, [r3, #0]
+}
+ 80007d0: 46c0 nop ; (mov r8, r8)
+ 80007d2: 46bd mov sp, r7
+ 80007d4: b002 add sp, #8
+ 80007d6: bd80 pop {r7, pc}
+ 80007d8: e000e100 .word 0xe000e100
+
+080007dc :
+{
+ 80007dc: b580 push {r7, lr}
+ 80007de: b082 sub sp, #8
+ 80007e0: af00 add r7, sp, #0
+ 80007e2: 0002 movs r2, r0
+ 80007e4: 1dfb adds r3, r7, #7
+ 80007e6: 701a strb r2, [r3, #0]
+ NVIC->ICER[0U] = (uint32_t)(1UL << (((uint32_t)(int32_t)IRQn) & 0x1FUL));
+ 80007e8: 1dfb adds r3, r7, #7
+ 80007ea: 781b ldrb r3, [r3, #0]
+ 80007ec: 001a movs r2, r3
+ 80007ee: 231f movs r3, #31
+ 80007f0: 4013 ands r3, r2
+ 80007f2: 4905 ldr r1, [pc, #20] ; (8000808 )
+ 80007f4: 2201 movs r2, #1
+ 80007f6: 409a lsls r2, r3
+ 80007f8: 0013 movs r3, r2
+ 80007fa: 2280 movs r2, #128 ; 0x80
+ 80007fc: 508b str r3, [r1, r2]
+}
+ 80007fe: 46c0 nop ; (mov r8, r8)
+ 8000800: 46bd mov sp, r7
+ 8000802: b002 add sp, #8
+ 8000804: bd80 pop {r7, pc}
+ 8000806: 46c0 nop ; (mov r8, r8)
+ 8000808: e000e100 .word 0xe000e100
+
+0800080c :
+{
+ 800080c: b590 push {r4, r7, lr}
+ 800080e: b083 sub sp, #12
+ 8000810: af00 add r7, sp, #0
+ 8000812: 0002 movs r2, r0
+ 8000814: 6039 str r1, [r7, #0]
+ 8000816: 1dfb adds r3, r7, #7
+ 8000818: 701a strb r2, [r3, #0]
+ if ((int32_t)(IRQn) < 0)
+ 800081a: 1dfb adds r3, r7, #7
+ 800081c: 781b ldrb r3, [r3, #0]
+ 800081e: 2b7f cmp r3, #127 ; 0x7f
+ 8000820: d932 bls.n 8000888
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 8000822: 4a2f ldr r2, [pc, #188] ; (80008e0 )
+ 8000824: 1dfb adds r3, r7, #7
+ 8000826: 781b ldrb r3, [r3, #0]
+ 8000828: 0019 movs r1, r3
+ 800082a: 230f movs r3, #15
+ 800082c: 400b ands r3, r1
+ 800082e: 3b08 subs r3, #8
+ 8000830: 089b lsrs r3, r3, #2
+ 8000832: 3306 adds r3, #6
+ 8000834: 009b lsls r3, r3, #2
+ 8000836: 18d3 adds r3, r2, r3
+ 8000838: 3304 adds r3, #4
+ 800083a: 681b ldr r3, [r3, #0]
+ 800083c: 1dfa adds r2, r7, #7
+ 800083e: 7812 ldrb r2, [r2, #0]
+ 8000840: 0011 movs r1, r2
+ 8000842: 2203 movs r2, #3
+ 8000844: 400a ands r2, r1
+ 8000846: 00d2 lsls r2, r2, #3
+ 8000848: 21ff movs r1, #255 ; 0xff
+ 800084a: 4091 lsls r1, r2
+ 800084c: 000a movs r2, r1
+ 800084e: 43d2 mvns r2, r2
+ 8000850: 401a ands r2, r3
+ 8000852: 0011 movs r1, r2
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ 8000854: 683b ldr r3, [r7, #0]
+ 8000856: 019b lsls r3, r3, #6
+ 8000858: 22ff movs r2, #255 ; 0xff
+ 800085a: 401a ands r2, r3
+ 800085c: 1dfb adds r3, r7, #7
+ 800085e: 781b ldrb r3, [r3, #0]
+ 8000860: 0018 movs r0, r3
+ 8000862: 2303 movs r3, #3
+ 8000864: 4003 ands r3, r0
+ 8000866: 00db lsls r3, r3, #3
+ 8000868: 409a lsls r2, r3
+ SCB->SHP[_SHP_IDX(IRQn)] = ((uint32_t)(SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 800086a: 481d ldr r0, [pc, #116] ; (80008e0 )
+ 800086c: 1dfb adds r3, r7, #7
+ 800086e: 781b ldrb r3, [r3, #0]
+ 8000870: 001c movs r4, r3
+ 8000872: 230f movs r3, #15
+ 8000874: 4023 ands r3, r4
+ 8000876: 3b08 subs r3, #8
+ 8000878: 089b lsrs r3, r3, #2
+ 800087a: 430a orrs r2, r1
+ 800087c: 3306 adds r3, #6
+ 800087e: 009b lsls r3, r3, #2
+ 8000880: 18c3 adds r3, r0, r3
+ 8000882: 3304 adds r3, #4
+ 8000884: 601a str r2, [r3, #0]
+}
+ 8000886: e027 b.n 80008d8
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 8000888: 4a16 ldr r2, [pc, #88] ; (80008e4 )
+ 800088a: 1dfb adds r3, r7, #7
+ 800088c: 781b ldrb r3, [r3, #0]
+ 800088e: b25b sxtb r3, r3
+ 8000890: 089b lsrs r3, r3, #2
+ 8000892: 33c0 adds r3, #192 ; 0xc0
+ 8000894: 009b lsls r3, r3, #2
+ 8000896: 589b ldr r3, [r3, r2]
+ 8000898: 1dfa adds r2, r7, #7
+ 800089a: 7812 ldrb r2, [r2, #0]
+ 800089c: 0011 movs r1, r2
+ 800089e: 2203 movs r2, #3
+ 80008a0: 400a ands r2, r1
+ 80008a2: 00d2 lsls r2, r2, #3
+ 80008a4: 21ff movs r1, #255 ; 0xff
+ 80008a6: 4091 lsls r1, r2
+ 80008a8: 000a movs r2, r1
+ 80008aa: 43d2 mvns r2, r2
+ 80008ac: 401a ands r2, r3
+ 80008ae: 0011 movs r1, r2
+ (((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL) << _BIT_SHIFT(IRQn)));
+ 80008b0: 683b ldr r3, [r7, #0]
+ 80008b2: 019b lsls r3, r3, #6
+ 80008b4: 22ff movs r2, #255 ; 0xff
+ 80008b6: 401a ands r2, r3
+ 80008b8: 1dfb adds r3, r7, #7
+ 80008ba: 781b ldrb r3, [r3, #0]
+ 80008bc: 0018 movs r0, r3
+ 80008be: 2303 movs r3, #3
+ 80008c0: 4003 ands r3, r0
+ 80008c2: 00db lsls r3, r3, #3
+ 80008c4: 409a lsls r2, r3
+ NVIC->IP[_IP_IDX(IRQn)] = ((uint32_t)(NVIC->IP[_IP_IDX(IRQn)] & ~(0xFFUL << _BIT_SHIFT(IRQn))) |
+ 80008c6: 4807 ldr r0, [pc, #28] ; (80008e4 )
+ 80008c8: 1dfb adds r3, r7, #7
+ 80008ca: 781b ldrb r3, [r3, #0]
+ 80008cc: b25b sxtb r3, r3
+ 80008ce: 089b lsrs r3, r3, #2
+ 80008d0: 430a orrs r2, r1
+ 80008d2: 33c0 adds r3, #192 ; 0xc0
+ 80008d4: 009b lsls r3, r3, #2
+ 80008d6: 501a str r2, [r3, r0]
+}
+ 80008d8: 46c0 nop ; (mov r8, r8)
+ 80008da: 46bd mov sp, r7
+ 80008dc: b003 add sp, #12
+ 80008de: bd90 pop {r4, r7, pc}
+ 80008e0: e000ed00 .word 0xe000ed00
+ 80008e4: e000e100 .word 0xe000e100
+
+080008e8 :
+
+volatile struct dma_tx_buf usart_tx_buf;
+
+static void usart_schedule_dma();
+
+void usart_dma_init() {
+ 80008e8: b580 push {r7, lr}
+ 80008ea: af00 add r7, sp, #0
+ usart_tx_buf.xfr_start = -1,
+ 80008ec: 4b17 ldr r3, [pc, #92] ; (800094c )
+ 80008ee: 2201 movs r2, #1
+ 80008f0: 4252 negs r2, r2
+ 80008f2: 601a str r2, [r3, #0]
+ usart_tx_buf.xfr_end = 0,
+ 80008f4: 4b15 ldr r3, [pc, #84] ; (800094c )
+ 80008f6: 2200 movs r2, #0
+ 80008f8: 605a str r2, [r3, #4]
+ usart_tx_buf.wr_pos = 0,
+ 80008fa: 4b14 ldr r3, [pc, #80] ; (800094c )
+ 80008fc: 2200 movs r2, #0
+ 80008fe: 609a str r2, [r3, #8]
+
+ /* Configure DMA 1 Channel 2 to handle uart transmission */
+ DMA1_Channel2->CPAR = (unsigned int)&(USART1->TDR);
+ 8000900: 4b13 ldr r3, [pc, #76] ; (8000950 )
+ 8000902: 4a14 ldr r2, [pc, #80] ; (8000954 )
+ 8000904: 609a str r2, [r3, #8]
+ DMA1_Channel2->CCR = (0<)
+ 8000908: 2292 movs r2, #146 ; 0x92
+ 800090a: 601a str r2, [r3, #0]
+ | (0<
+ NVIC_SetPriority(DMA1_Channel2_3_IRQn, 1<<5);
+ 8000912: 2120 movs r1, #32
+ 8000914: 200a movs r0, #10
+ 8000916: f7ff ff79 bl 800080c
+
+ USART1->CR1 = /* 8-bit -> M1, M0 clear */
+ 800091a: 4b0f ldr r3, [pc, #60] ; (8000958 )
+ 800091c: 4a0f ldr r2, [pc, #60] ; (800095c )
+ 800091e: 601a str r2, [r3, #0]
+ | USART_CR1_RXNEIE /* Enable receive interrupt */
+ /* other interrupts clear */
+ | USART_CR1_TE
+ | USART_CR1_RE;
+ /* Set divider for 1MBd @48MHz system clock. */
+ USART1->BRR = 48;
+ 8000920: 4b0d ldr r3, [pc, #52] ; (8000958 )
+ 8000922: 2230 movs r2, #48 ; 0x30
+ 8000924: 60da str r2, [r3, #12]
+
+ USART1->CR2 = USART_CR2_TXINV | USART_CR2_RXINV;
+ 8000926: 4b0c ldr r3, [pc, #48] ; (8000958 )
+ 8000928: 22c0 movs r2, #192 ; 0xc0
+ 800092a: 0292 lsls r2, r2, #10
+ 800092c: 605a str r2, [r3, #4]
+
+ USART1->CR3 |= USART_CR3_DMAT; /* TX DMA enable */
+ 800092e: 4b0a ldr r3, [pc, #40] ; (8000958 )
+ 8000930: 689a ldr r2, [r3, #8]
+ 8000932: 4b09 ldr r3, [pc, #36] ; (8000958