67 Commits

Author SHA1 Message Date
mitxela
8af0b73a77 typo in hinge.svg
Black 6mm rectangle should have a height of 22.56, with the lower hole 6mm from the bottom, and the top hole 5.28 from the top. It was off by 0.28mm so hardly noticable with the kerf of the laser, but we may as well make it exact.
2025-10-08 12:07:19 +01:00
mitxela
0dc65df840 Add redrawn STEP files
These don't exactly match the STL files although both will work. STL files were generated from the OpenSCAD file. STEP files were redrawn with some fillets and other tweaks, moving forwards the step files may be the main reference
2025-10-08 11:55:02 +01:00
mitxela
9e6b0c1afa Move main STL files into folders for rev C, rev D 2025-10-08 11:54:08 +01:00
mitxela
f5113a92e4 Set brightness curve in config file for phototransistor
The default curve in the firmware, with nothing specified in the config file (or this commented out) matches the LDR.
2025-10-08 11:24:02 +01:00
mitxela
67010598d9 add STL for phototransistor (VTT9812FH) 2025-10-08 11:08:22 +01:00
mitxela
70c04301dc bootloader user request on PA2/hinge TX 2025-08-03 12:21:24 +01:00
mitxela
b7e80f0d8d update config.txt template 2025-08-02 14:34:22 +01:00
mitxela
22cb434297 inc fwt version 2025-08-02 14:18:12 +01:00
mitxela
c632fc4c28 wipe vbat measurement on leaving mode_vbat 2025-08-02 01:39:14 +01:00
mitxela
b3e00fb43c Reduce power-on precision if coin cell below 2.7V 2025-08-02 01:26:30 +01:00
mitxela
914471d6f3 oversampling vbat is substantially more stable 2025-08-01 19:37:36 +01:00
mitxela
922586d549 mode_vbat 2025-08-01 19:28:59 +01:00
mitxela
6ee513efb1 initial vbat reading using adc3 2025-08-01 16:04:12 +01:00
mitxela
c3e81356f5 monitor beidou, plot gps and the highest non-gps satview 2025-08-01 11:43:28 +01:00
mitxela
384b85b9f9 further complication of GSV parsing
signal ID is not always present, number of fields is variable, what was meant to be a quick way of showing number of satellites is becoming a mess
2025-08-01 11:05:25 +01:00
mitxela
f4751fce09 correctly interpret multiple GSV messages
M10 gps module sends GPGSV multiple times in separate groups, even though it's only listening to a single band.
2025-08-01 02:16:35 +01:00
mitxela
b30b862fda latch satview
ublox 10 series output GSV only every 5 seconds
2025-08-01 01:22:08 +01:00
mitxela
74f683c7ba update qspi.md 2025-07-31 23:24:44 +01:00
mitxela
43cdfe10cc tzmap 2025b (full) 2025-07-31 22:37:14 +01:00
mitxela
6ba38a7a55 tzrules to 2025b 2025-07-31 13:58:19 +01:00
mitxela
05ab0d7123 update timezone-names to 2025b 2025-07-31 13:45:09 +01:00
mitxela
529555730a Bootloader updates to explicitly protect the stack
Using both noreturn and __builting_unreachable() is superfluous but hopefully makes it twice as unlikely to optimise the jump into a tail call. Not sure if this is better than -O0 but hopefully makes some people less unhappy.
2025-07-31 11:20:20 +01:00
mitxela
fa71140552 add physical dimensions to hinge svg 2025-07-31 10:47:49 +01:00
mitxela
0d76b0f078 generate either version in openscad 2025-07-31 10:26:48 +01:00
mitxela
f2cc1f54ab cad for vtt9812fh 2025-07-25 11:03:43 +01:00
mitxela
eca890e2b2 a dubiously helpful overlay for brightness curve 2025-07-18 12:20:23 +01:00
mitxela
fd62ade91b method to convert a bunch of brightness values 2025-07-18 12:01:34 +01:00
mitxela
4fb73649ea basic support for touchscreen devices 2025-07-12 23:21:57 +01:00
mitxela
3bc2ccb08b allow pasting in brightness curve values 2025-07-12 22:30:21 +01:00
mitxela
90ac0fc267 generate binary files 2025-07-04 17:43:42 +01:00
mitxela
8ce8a867d1 compatibility with toolchain 12.3.rel1 2025-07-04 17:42:04 +01:00
mitxela
715e8b338d Ignore env hashes using clean/smudge filter
Add following to .git/config:

[filter "eclipse_env_hash"]
	clean = sed 's/env-hash=\"[-,0-9]*\"/env-hash=\"0000000000000000000\"/g'
	smudge = cat
2025-07-04 17:25:38 +01:00
mitxela
2571e62078 Revert "Don't track these IDE files that keep changing"
This reverts commit 8e4d62cca4.
2025-07-04 17:08:06 +01:00
mitxela
7a0fc54fa8 add shelfstand cad files 2025-06-29 18:19:36 +01:00
mitxela
a1e8af3cf9 Add handcrafted SVG version of moshidraw hinge 2025-06-29 17:58:50 +01:00
mitxela
122e601da9 add readme 2025-05-25 12:36:35 +01:00
mitxela
4ce85147f0 CAD files for antenna case
Specifically for the patch antenna with SMA connector crimped as close as possible. Top half (caset.stl) needs to be printed upside down with support for the cable shroud. Last modified 2023-04-19
2025-05-21 12:56:06 +01:00
mitxela
16edb66444 Add cad files for wall hangers 2025-05-21 12:49:25 +01:00
mitxela
7c9b9b6f0e lasercut files update for easier tiling 2025-05-21 12:24:08 +01:00
mitxela
c46e7cc803 Add moshidraw file for hinge (convert to DXF or SVG later) 2025-05-21 12:23:17 +01:00
mitxela
2dd441d178 make colon cover a teeny bit taller 2025-05-21 12:07:35 +01:00
mitxela
4c8d2fa190 add side cutouts to colons for better pliability 2025-05-21 12:06:07 +01:00
mitxela
fb0785b312 flat-top LEDs have 3.15 dia 2025-05-21 12:04:07 +01:00
mitxela
ed93d83036 commit STL files 2025-05-21 12:02:56 +01:00
mitxela
65bb96ff6f cad updates from 2023-06-15 2025-05-21 11:52:47 +01:00
mitxela
30425af408 start adding cad files to this repo 2025-05-21 11:37:13 +01:00
mitxela
8e4d62cca4 Don't track these IDE files that keep changing 2024-10-22 11:17:51 +01:00
mitxela
29691bc5bc Add known firmware images to repo (2024-05-29) 2024-10-22 11:09:33 +01:00
mitxela
9007c9be64 Config file defaults, most modes off 2024-06-27 10:59:05 +01:00
mitxela
0d7561f1ab IDE settings (unsure what changed) 2024-06-27 10:31:14 +01:00
mitxela
e380791170 slightly smaller hammer (re: b91a100) 2024-06-27 10:29:33 +01:00
mitxela
b91a1004f9 sledgehammer to prevent -Os trashing launch_app() 2024-06-27 10:21:34 +01:00
mitxela
3a3db5b583 suppress maybe-uninitialised warning 2024-06-27 10:20:54 +01:00
mitxela
c110cc0b47 Pad bootloader to exactly 64K 2024-06-27 10:20:14 +01:00
mitxela
5c84802a9e Bootloader version string 2024-06-26 09:34:19 +01:00
mitxela
7b388bc2b6 env hash stuff - should probably ignore these files 2024-06-26 09:33:34 +01:00
mitxela
ea364d761a partial changes to bootloader - unfinished
f_mount doesn't actually do anything until first read (unless forced) so it's not really possible to error out at the mount stage, but we don't want any possible way to hang without enabling usb
2023-08-25 13:40:06 +01:00
mitxela
12565ff862 Clear colons in bootloader
They are off when tristated too but need to be explicitly high to remain off on the xl
2023-07-27 13:20:23 +01:00
mitxela
a11f54b005 and volatile again in the bootloader
This was working without it, so the fix is hypothetical. Might be because bootloader is -Os and time is -O3
2023-07-26 12:33:27 +01:00
mitxela
344aa32ddd another volatile optimisation victim 2023-07-25 23:12:37 +01:00
mitxela
2510c85b26 set volume label to CLOCK 2023-07-25 11:47:03 +01:00
mitxela
99af17dd31 blank date when updating on eject 2023-07-24 16:02:58 +01:00
mitxela
ce4fd5172f delay setDisplayFrequency if needed 2023-07-24 15:24:12 +01:00
mitxela
a9490dbee4 Don't write RTC during USB read/writes, pendSV could be delayed 2023-07-24 13:34:06 +01:00
mitxela
cc5e7114b8 fix countdown mode entering/exiting 2023-07-24 13:32:20 +01:00
mitxela
2a04bc99a1 Replace delayedButtonPress with resendDate
Not sure if this is better than the alternative, that is to delay CDC commands and reloaded config too.
Todo: countdown mode fixes
2023-07-23 16:50:37 +01:00
mitxela
95c0565fab Measure lookup time macro
Takes 3x longer if launched via swd instead of bootloader. QSPI quad read seems to make it slower. Definitely something odd going on
2023-07-21 16:25:53 +01:00
65 changed files with 7476 additions and 220 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*/.settings/language.settings.xml filter=eclipse_env_hash

View File

@@ -1,16 +1,20 @@
<!doctype html>
<canvas width=800 height=600 style='position:relative;'></canvas>
<pre></pre>
<br>
<textarea style="width:300px;height:100px" oninput='parse()'></textarea>
<span style='position:absolute;pointer-events:none;font-family:monospace;'></span>
<script>
pre = document.querySelector('pre')
pre = document.querySelector('textarea')
span = document.querySelector('span')
canvas = document.querySelector('canvas')
ctx = canvas.getContext('2d')
w = canvas.width; h = canvas.height;
gw = w-50; gh = h-50
gx=25; gy=25
b={x:0,y:0}
curve = [
[0, 0],
@@ -33,7 +37,9 @@ function circle(x,y) {
ctx.stroke();
}
ctx.font = '18px Courier, monospace';
function draw(){
function draw(wb){
b=canvas.getBoundingClientRect()
ctx.clearRect(0,0,w,h)
ctx.fillStyle='rgba(1,1,1,0.05)'
ctx.fillRect(gx,gy,gw,gh)
@@ -56,11 +62,11 @@ function draw(){
if (i) line( curve[i-1][0], curve[i-1][1], curve[i][0], curve[i][1] )
}
if (wb) return;
s=""
for (let i=0;i<curve.length;i++)
// s+='{'+Math.round(curve[i][0]*4095)+', 4095-'+Math.round(curve[i][1]*4095)+'},\n'
s+= "BS"+(i+1)+" = "+ Math.round(curve[i][0]*4095)+ ',' + Math.round(curve[i][1]*4095)+"\n"
pre.textContent = s
pre.value = s
}
function distance(x1,y1,x2,y2){
@@ -87,27 +93,95 @@ function clamp(x,y,i){
return [Math.min(maxx,Math.max(minx,x)),Math.min(1,Math.max(0,y))]
}
function highlight(e){
let x = (e.pageX-gx-b.x)/gw;
let y = 1-(e.pageY-gy-b.y)/gh;
if (x<0.0 || x>1.0 || y<0.0 || y>1.0) {
span.textContent="";
} else {
let out = single(x)
span.textContent=Math.round(x*4095)+","+Math.round(out*4095);
span.style.left=e.pageX+"px"
span.style.top=((1-out)*gh+gy+b.y)+"px"
}
}
document.onmousemove=highlight
canvas.onmousedown=function(e){
e.preventDefault()
let x = (e.layerX-gx)/gw;
let y = 1-(e.layerY-gy)/gh;
let x = (e.pageX-gx-b.x)/gw;
let y = 1-(e.pageY-gy-b.y)/gh;
span.textContent="";
let i = nearestPoint(x,y)
curve[i] = clamp(x,y,i)
document.onmousemove=function(e){
let x = (e.layerX-gx)/gw;
let y = 1-(e.layerY-gy)/gh;
let x = (e.pageX-gx-b.x)/gw;
let y = 1-(e.pageY-gy-b.y)/gh;
curve[i] = clamp(x,y,i)
draw()
}
document.onmouseup=function(e){
document.onmousemove=null
document.onmousemove=highlight
document.onmouseup=null
}
draw()
}
touch={};
canvas.addEventListener("touchstart",function(e){
if (e.touches.length>1) return;
for (let t of e.changedTouches) {
let x = (t.pageX-gx-b.x)/gw
let y = 1-(t.pageY-gy-b.y)/gh
let i = nearestPoint(x,y)
curve[i] = clamp(x,y,i)
touch = {id:t.identifier,i}
}
e.preventDefault();
draw()
},true);
canvas.addEventListener("touchmove",function(e){
for (let t of e.changedTouches) {
if (touch.id == t.identifier) {
let x = (t.pageX-gx-b.x)/gw
let y = 1-(t.pageY-gy-b.y)/gh
curve[touch.i] = clamp(x,y,touch.i)
}
}
draw()
},true);
function parse(){
var lines = pre.value.split("\n");
for (let line of lines) {
let m = line.match(/^BS([1-5]) = (\d+),(\d+)$/)
if (!m || m[2]>4095 || m[3]>4095) continue;
curve[m[1]-1]=[m[2]/4095, m[3]/4095]
}
draw(1)
}
function single(inp){
let i;
for (i=1; i< curve.length-1; i++){
if (curve[i][0] > inp) break;
}
let factor = (inp - curve[i-1][0]) / (curve[i][0] - curve[i-1][0]);
let out = curve[i-1][1]*(1.0-factor) + curve[i][1]*factor;
if (out>1.0 || isNaN(out)) out=1.0;
else if (out<0.0) out=0.0;
return out
}
draw()
</script>
</script>

View File

@@ -0,0 +1,85 @@
module antenna(){
rotate([90,0,0])cylinder(h=22,r=2,$fn=100);
translate([-23.2/2,0,-1])cube([23.2,23.2,3]);
translate([-21/2,1,-2])cube([21,21,6.5]);
translate([-21/2,1,-2])cube([21,22,3]);
translate([-20/2,0,-2])cube([20,3,3]);
translate([0,23.2/2,0])cylinder(h=4.8,r=7);
}
module caseb_outer() {
rotate([90,0,0])cylinder(h=17,r=3.2,$fn=6);
translate([-25/2,-1,-2.771])cube([25,25,2.771]);
translate([-10,23.5,-1])cube([20,1,1]);
translate([-10,-1.4,-1])cube([20,1,1]);
}
module caseb() difference(){
caseb_outer();
antenna();
translate([-25,-25,0])cube([50,60,5]);
translate([11.5,-2,-3])rotate([0,30,0])cube([5,30,5]);
translate([-15.5,-2,-6])rotate([0,-30,0])cube([5,30,5]);
translate([2.8,-17,-2])cube([10,3,4]);
translate([-12.8,-17,-2])cube([10,3,4]);
}
module caset_outer(){
rotate([90,0,0])cylinder(h=17,r=3.2,$fn=6);
translate([-25/2,-1,0])cube([25,25,2.771]);
translate([-24/2,-0.5,0])cube([24,24,5.2]);
translate([-24.4/2,-0.7,0])cube([24.4,24.4,3]);
}
module caset_notabs() difference(){
caset_outer();
antenna();
translate([-25,-25,-5])cube([50,60,5]);
}
module tabprofile() difference(){
translate([-10,24.0,-2.5])cube([20,1.2,4.0]);
translate([-10,23.5,-1.2])cube([20,1,1.2]);
translate([-10,24.3,-2.6])rotate([-30,0,0])cube([20,1,2]);
translate([-10,25.3,0.0])rotate([30,0,0])cube([20,1,2]);
}
module caset(){
caset_notabs();
tabprofile();
difference(){
translate([0,23,0])scale([1,-1,1]) tabprofile();
translate([-3.5,-2.5,-2.6])cube([7,5,5]);
}
difference(){
intersection(){
translate([0,-14,0])rotate([90,0,0])cylinder(h=3,r=4.2,$fn=6);
translate([-5,-20,-1.5])cube([10,10,4.271]);
}
translate([0,-14,0])rotate([90,0,0])cylinder(h=4,r=3.2,$fn=6);
}
}
//difference(){
color("#8f8") caset();
// translate([0,-25,-10])cube([50,60,20]);
//}
//render()
//caseb();
difference(){
//color("#f88")caseb();
//translate([-25,10,-10])cube([50,60,20]);
}
%antenna();

BIN
cad/antenna-case/caseb.stl Normal file

Binary file not shown.

BIN
cad/antenna-case/caset.stl Normal file

Binary file not shown.

212
cad/colons.scad Normal file
View File

@@ -0,0 +1,212 @@
$fn=100;
revD = true; // set false to generate Rev C parts
h=revD ? 34.2 : 34.4;
w=12.0;
d=10.5;
t_side=1;
t_front=1;
t_top=1.5;
tabwidth=5;
tabheight=2.9;
led_height=3;
led_dia=3.15;
ldr_height=1.9;
// colon positions
deltaV=11.3;
deltaH=1.85;
c1x= w/2-deltaH/2;
c2x= w/2+deltaH/2;
c1y= h/2+deltaV/2;
c2y= h/2-deltaV/2;
//latch size, depth and margin
ls=5.5;
ld=0.6;
lmv=0.15;
lmh=0.6;
module latchMale(){
translate([w/2-ls/2,-ld,d/2-ls/2])cube([ls,ld,ls]);
}
module latchFemale(){
//difference(){
// translate([0,-ld,0])cube([w,ld,d]);
translate([w/2-ls/2-lmh,-ld*2,d/2-ls/2-lmv])cube([ls+lmh*2,ld*2,ls+lmv*2]);
//}
}
module sideCutout(){
sc_r = 7;
sc_i = 12;
translate([-1,sc_i,11])rotate([0,90,0])cylinder(h=w+2,r=sc_r);
translate([-1,h-sc_i,11])rotate([0,90,0])cylinder(h=w+2,r=sc_r);
translate([-1,sc_i,11])rotate([0,90,0])cube([sc_r,h-sc_i*2,w+2]);
}
module colon(){
difference(){
union(){
difference() {
cube([w,h,d]);
translate([t_side,t_top,t_front])cube([w-t_side*2,h-t_top*2,d]);
sideCutout();
}
translate([c1x,c1y,0])cylinder(led_height,d=5);
translate([c2x,c2y,0])cylinder(led_height,d=5);
tab();
translate([w,h,0])rotate([0,0,180]) tab();
}
translate([c1x,c1y,-1])cylinder(11,d=led_dia);
translate([c2x,c2y,-1])cylinder(11,d=led_dia);
}
}
module switchcover(){
h=34.6;
difference(){
union(){
difference() {
cube([w,h,d]);
translate([t_side,t_top,t_front])cube([w-t_side*2,h-t_top*2,d]);
}
tab();
translate([w,h,0])rotate([0,0,180]) tab();
latchMale();
}
translate([w/2,h/2-4.5,-1])cylinder(11,d=3.5);
translate([w/2,h/2+4.5,-1])cylinder(11,d=3.5);
translate([0,-ld,0])magnet();
translate([w/2-2,0.3,6])rotate([-20,0,0])cube([4,3,4]);
}
translate([0,-ld,0])magnetHolder();
//latchMale();
//latchFemale();
}
module magnet(){
translate([w/2,4.0,d/2])rotate([90,0,0])cylinder(h=3.5,d=4.1);
}
module magnetHolder(){
cutaway=0;
difference(){
translate([w/2-3,1,d/2-4.5])cube([6,3.5-cutaway,5]);
magnet();
}
translate([w/2-3,4,5.75])rotate([-20,0,0])cube([6,0.5,2]);
translate([w/2+2.1,3.22,5.5])rotate([-45,0,0])cube([0.9,0.5,1.5]);
translate([w/2-3,3.22,5.5])rotate([-45,0,0])cube([0.9,0.5,1.5]);
}
ldr_pad=0.07;
module ldr(){
h=34.6;
difference(){
union(){
difference() {
cube([w,h,d]);
translate([t_side,t_top,t_front])cube([w-t_side*2,h-t_top*2,d]);
}
tab();
translate([w,h,0])rotate([0,0,180]) tab();
translate([w/2-2.5,h/2+1.45,0.5]){
cube([5.0,1.0,2]);
cube([5.0,1.3,1.6]);
}
translate([w/2-2.5,h/2-2.45,0.5])cube([5.0,1.0,2]);
translate([w/2-2.5,h/2-2.75,0.5])cube([5.0,1.3,1.6]);
}
translate([w/2,h/2,-1]) intersection(){
cylinder(ldr_height+1,r=2.5+ldr_pad);
translate([-5,-4.0/2-ldr_pad,0])cube([10,4.0+ldr_pad*2,ldr_height+1]);
}
translate([w-1,1.5+3.58,d-2])cube([1,8,2]);
translate([0,ld,0])magnet();
//translate([w/2-2,0.9+ld,6])rotate([-20,0,0])cube([4,3,4]);
translate([0,ld,0])latchFemale();
}
magnetHolder();
}
module vtt9812fh(){
h=34.6;
difference(){
union(){
difference() {
cube([w,h,d]);
translate([t_side,t_top,t_front])cube([w-t_side*2,h-t_top*2,d]);
}
tab();
translate([w,h,0])rotate([0,0,180]) tab();
translate([w/2,h/2,0]) cylinder(d=7,h=2.8);
}
translate([w/2,h/2,-1]) intersection(){
cylinder(d=5,h=5);
}
translate([w-1,1.5+3.58,d-2])cube([1,8,2]);
translate([0,ld,0])magnet();
translate([0,ld,0])latchFemale();
}
magnetHolder();
}
module tab(){
difference(){
translate([w/2-tabwidth/2,0,d]) {
cube([tabwidth,1.5,tabheight-1]);
translate([0,0,1.6])cube([tabwidth,2,tabheight-1-1.6]);
translate([0,1.0,tabheight-1])rotate([0,90,0])cylinder(h=tabwidth,r=1.0);
}
translate([0,1.5,d]) cube([w,2,1.6]);
}
}
module ldrFitTest() {
cutaway=1;
intersection(){
ldr();
translate([1,12,0]) cube([10-cutaway*5,10,5]);
}
}
/*
intersection(){
//ldr();
switchcover();
translate([0,-2,0])cube([w/2,40,20]);
}
//*/
//ldrFitTest();
//ldr();
//switchcover();
//colon();
//vtt9812fh();
translate([-30,0,0]) colon();
translate([-15,0,0]) colon();
translate([0,0,0]) switchcover();
if (revD) {
translate([15,0,0]) vtt9812fh();
} else {
translate([15,0,0]) ldr();
}

1714
cad/hinge.mdr Normal file

File diff suppressed because it is too large Load Diff

65
cad/hinge.svg Normal file
View File

@@ -0,0 +1,65 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 -10 150 100" width="150mm" height="100mm" fill="none" stroke="#000" stroke-width="0.2">
<!-- White 5mm Delrin -->
<g>
<rect x="45" y="39" width="3" height="5"/>
<circle cx="50" cy="24.72" r="1.5"/>
<circle cx="50" cy="36" r="1.5"/>
<circle cx="50" cy="47.28" r="1.5"/>
<polyline points="50,18.72 56,18.72 56,53.28 44,53.28 44,24.72"/>
<path d="M44,24.72 A6 6 0 0 1 50,18.72"/>
</g>
<g>
<rect x="32" y="39" width="3" height="5"/>
<circle cx="30" cy="24.72" r="1.5"/>
<circle cx="30" cy="36" r="1.5"/>
<circle cx="30" cy="47.28" r="1.5"/>
<polyline points="30,18.72 24,18.72 24,53.28 36,53.28 36,24.72"/>
<path d="M30,18.72 A6 6 0 0 1 36,24.72"/>
</g>
<!-- Black 6mm Delrin -->
<g>
<circle cx="42" cy="5" r="1.5"/>
<circle cx="30" cy="5" r="1.5"/>
<path d="M30,11 L42,11 A6 6 0 0 0 42,-1 L30,-1 A6 6 0 0 0 30,11"/>
</g>
<g>
<circle cx="10" cy="47.28" r="1.5"/>
<circle cx="10" cy="36" r="1.5"/>
<polyline points="16,53.28 4,53.28 4,30.72 16,30.72 16,53.28"/>
</g>
<!-- White 3mm Delrin -->
<g>
<circle cx="72" cy="5" r="1.3"/>
<circle cx="60" cy="5" r="1.3"/>
<path d="M60,11 L72,11 A6 6 0 0 0 72,-1 L 60,-1 A6 6 0 0 0 60,11"/>
</g>
<!-- Acetate film -->
<g>
<circle cx="122" cy="25" r="1.45"/>
<circle cx="110" cy="25" r="1.45"/>
<circle cx="122" cy="38" r="1.45"/>
<circle cx="110" cy="38" r="1.45"/>
<path d="M110,42 L 122,42
A4 4 0 0 0 122,34
L 121.5,34
A2.5 2.5 0 0 1 121.5,29
L 122,29
A4 4 0 0 0 122,21
L110,21
A4 4 0 0 0 110,29
L110.5,29
A2.5 2.5 0 0 1 110.5,34
L110,34
A4 4 0 0 0 110,42
"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -119,6 +119,7 @@
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.628128892" name="Floating-point ABI" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi" useByScannerDiscovery="true" value="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.floatabi.value.hard" valueType="enumerated"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.467584027" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.1800155271" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.5 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.base.gnu-tools-for-stm32 || STM32L476RCTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../FATFS/App | ../USB_DEVICE/Target | ../Drivers/CMSIS/Include | ../Core/Inc | ../USB_DEVICE/App | ../Drivers/CMSIS/Device/ST/STM32L4xx/Include | ../FATFS/Target | ../Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Inc | ../Drivers/STM32L4xx_HAL_Driver/Inc | ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc | ../Middlewares/Third_Party/FatFs/src | ../Drivers/STM32L4xx_HAL_Driver/Inc/Legacy || || || USE_HAL_DRIVER | STM32L476xx || || Drivers | Core/Startup | Middlewares | Core | FATFS | USB_DEVICE || || || ${workspace_loc:/${ProjName}/STM32L476RCTX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary.1568961625" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.699779650" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/mk4-bootloader}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1049602492" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.1341160678" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">

View File

@@ -6,7 +6,7 @@
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="185955069870389989" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="0000000000000000000" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -17,8 +17,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="115984574982993951" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="0000000000000000000" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@@ -1,4 +1,4 @@
2F62501ED4689FB349E356AB974DBE57=50C66168B03739D025B40EAABFA700A5
8DF89ED150041C4CBC7CB9A9CAA90856=50C66168B03739D025B40EAABFA700A5
DC22A860405A8BF2F2C095E5B6529F12=460787E75B2D603D0ACA93B88832D04C
2F62501ED4689FB349E356AB974DBE57=5A72FCC93240365763D02B1C9D2B862E
8DF89ED150041C4CBC7CB9A9CAA90856=5A72FCC93240365763D02B1C9D2B862E
DC22A860405A8BF2F2C095E5B6529F12=264DA9245F9288E3067220E69F3ED6D7
eclipse.preferences.version=1

View File

@@ -66,6 +66,7 @@ extern "C" {
#define bSegDecode7 0b0000011100
#define bSegDecode8 0b0111111100
#define bSegDecode9 0b0110111100
#define bSegDecodeU 0b0011111000
#define bCat0 0b1111000000000000
#define bCat1 0b1110001000000000
@@ -73,6 +74,30 @@ extern "C" {
#define bCat3 0b1011001000000000
#define bCat4 0b0111001000000000
// Unable to mount / fatfs failure
#define ERR_FATFS bSegDecode0
// Firmware image on file system fails CRC check
#define ERR_FS_IMG_CRC_INVALID bSegDecode1
// Loaded firmware image is invalid and no replacement found in file system
#define ERR_INVALID_NO_FW bSegDecode2
// Flash page erase failed
#define ERR_ERASE_FAILED bSegDecode3
// Data written to flash didn't match data read back
#define ERR_WRITE_INVALID bSegDecode4
// Write data to flash returned failure
#define ERR_WRITE_FAILED bSegDecode5
#define ERR_UNKNOWN bSegDecode9
// User request bootloader hang for backup USB stack
#define ERR_USER bSegDecodeU
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
@@ -82,6 +107,7 @@ extern "C" {
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
void hang_error(uint16_t errno);
/* USER CODE BEGIN EFP */

View File

@@ -71,27 +71,6 @@ static void MX_TIM4_Init(void);
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
// Firmware image on file system fails CRC check
#define ERR_FS_IMG_CRC_INVALID 0b0011111100 // 0
// Loaded firmware image is invalid and no replacement found in file system
#define ERR_INVALID_NO_FW 0b0000011000 // 1
// Flash page erase failed
#define ERR_ERASE_FAILED 0b0101101100 // 2
// Data written to flash didn't match data read back
#define ERR_WRITE_INVALID 0b0100111100 // 3
// Write data to flash returned failure
#define ERR_WRITE_FAILED 0b0110011000 // 4
//0b0110110100 // 5
//0b0111110100 // 6
//0b0000011100 // 7
//0b0111111100 // 8
//0b0110111100 // 9
#define byteswap32(x) \
( ((x & 0xff000000) >> 24) | ((x & 0x00ff0000) >> 8) \
| ((x & 0x0000ff00) << 8) | ((x & 0x000000ff) << 24))
@@ -124,7 +103,7 @@ void setDisplayPWM(uint32_t bright){
HAL_DMA_Start(&hdma_tim4_up, (uint32_t)buffer_c, (uint32_t)&GPIOC->ODR, bright);
}
uint8_t ejected_state = 0;
volatile uint8_t ejected_state = 0;
void hang_error(uint16_t errno){
MX_USB_DEVICE_Init();
@@ -207,8 +186,7 @@ uint32_t app_crc()
return result;
}
void launch_app(){
void __attribute__((naked,noreturn)) launch_app(){
HAL_RCC_DeInit();
HAL_DeInit();
@@ -225,6 +203,7 @@ void launch_app(){
__set_MSP(_app_start[0]);
((void (*)(void)) _app_start[1])();
__builtin_unreachable();
}
@@ -404,7 +383,7 @@ int main(void)
__HAL_TIM_ENABLE(&htim4);
_Bool new_fw_present;
uint32_t new_fw_crc;
uint32_t new_fw_crc =0;
// Calculate CRC of loaded image
uint32_t loaded_fw_crc = app_crc();
@@ -423,6 +402,11 @@ int main(void)
// debug force reload
// new_fw_crc=0;
// Hinge TX connection shorted to ground - force bootloader to hang
if ((GPIOA->IDR & (1<<2))==0) {
hang_error(ERR_USER);
}
if (loaded_fw_crc == byteswap32(*(uint32_t*)(FLASH_BASE + BOOT_SIZE + APP_SIZE -4)) ) { // loaded firmware valid
@@ -728,6 +712,25 @@ static void MX_GPIO_Init(void)
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0|GPIO_PIN_1, GPIO_PIN_SET);
/*Configure GPIO pin : PA0 PA1 */
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/**USART2 GPIO Configuration
PA2 ------> USART2_TX
PA3 ------> USART2_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13|GPIO_PIN_0|GPIO_PIN_1|GPIO_PIN_2
|GPIO_PIN_3|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6
@@ -777,7 +780,7 @@ void Error_Handler(void)
{
/* USER CODE BEGIN Error_Handler_Debug */
/* User can add his own implementation to report the HAL error return state */
while(1){}
hang_error(ERR_UNKNOWN);
/* USER CODE END Error_Handler_Debug */
}

View File

@@ -24,6 +24,7 @@
/* Includes */
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
/* Variables */
extern int errno;

View File

@@ -1,4 +1,4 @@
// in pre-build steps: rm -f Core/Src/version.o
#define VERSION_STRING "BootVer 0.0.1 "
#define VERSION_STRING "BootVer 0.0.3 "
#include "../../../version.h"

View File

@@ -34,8 +34,10 @@ void MX_FATFS_Init(void)
/* USER CODE BEGIN Init */
// This should never fail, as f_mount does not do anything until
// the first read (unless forced)
if (f_mount(&USERFatFS, (TCHAR const*)USERPath, 0) != FR_OK)
Error_Handler();
hang_error(ERR_FATFS);
/* USER CODE END Init */
}

View File

@@ -114,7 +114,7 @@ static int8_t SCSI_ProcessWrite(USBD_HandleTypeDef *pdev, uint8_t lun);
*/
int8_t SCSI_ProcessCmd(USBD_HandleTypeDef *pdev, uint8_t lun, uint8_t *cmd)
{
extern uint8_t ejected_state;
extern volatile uint8_t ejected_state;
if (ejected_state==1) ejected_state=2;
switch (cmd[0])
{

View File

@@ -145,7 +145,11 @@ SECTIONS
} >RAM AT> FLASH
.pad : { KEEP(*(.pad)) } > PAD
.pad :
{
KEEP(*(.pad))
. = LENGTH(PAD);
} > PAD
/* Uninitialized data section into "RAM" Ram type memory */
. = ALIGN(4);

View File

@@ -115,6 +115,7 @@
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid.914925487" name="Core" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_coreid" useByScannerDiscovery="false" value="0" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.2071828213" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.974500262" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.5 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.base.gnu-tools-for-stm32 || STM32L010C6Tx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../Drivers/CMSIS/Include | ../Core/Inc | ../Drivers/STM32L0xx_HAL_Driver/Inc | ../Drivers/CMSIS/Device/ST/STM32L0xx/Include || || || HSE_VALUE=8000000 | HSE_STARTUP_TIMEOUT=100 | HSI_VALUE=16000000 | LSE_STARTUP_TIMEOUT=5000 | LSE_VALUE=32768 | DATA_CACHE_ENABLE=1 | LSI_VALUE=37000 | MSI_VALUE=2097000 | VDD_VALUE=3300 | INSTRUCTION_CACHE_ENABLE=1 | USE_FULL_LL_DRIVER | STM32L010x6 | PREFETCH_ENABLE=0 || || Drivers | Core/Startup | Core || || || ${workspace_loc:/${ProjName}/STM32L010C6TX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary.572415805" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.131568553" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/mk4-date}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.744708051" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.2032152780" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">

View File

@@ -6,7 +6,7 @@
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="179684480100589093" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="0000000000000000000" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -17,8 +17,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="179684480100589093" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="0000000000000000000" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@@ -24,6 +24,7 @@
/* Includes */
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
/* Variables */
extern int errno;

View File

@@ -124,6 +124,7 @@
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board.283690338" name="Board" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.target_board" useByScannerDiscovery="false" value="genericBoard" valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults.950842211" name="Defaults" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.defaults" useByScannerDiscovery="false" value="com.st.stm32cube.ide.common.services.build.inputs.revA.1.0.5 || Release || false || Executable || com.st.stm32cube.ide.mcu.gnu.managedbuild.toolchain.base.gnu-tools-for-stm32 || STM32L476RGTx || 0 || 0 || arm-none-eabi- || ${gnu_tools_for_stm32_compiler_path} || ../FATFS/App | ../USB_DEVICE/Target | ../Drivers/CMSIS/Include | ../Core/Inc | ../USB_DEVICE/App | ../Drivers/CMSIS/Device/ST/STM32L4xx/Include | ../FATFS/Target | ../Middlewares/ST/STM32_USB_Device_Library/Class/MSC/Inc | ../Drivers/STM32L4xx_HAL_Driver/Inc | ../Middlewares/ST/STM32_USB_Device_Library/Core/Inc | ../Middlewares/Third_Party/FatFs/src | ../Drivers/STM32L4xx_HAL_Driver/Inc/Legacy || || || USE_HAL_DRIVER | STM32L476xx | USE_FULL_LL_DRIVER || || Drivers | Core/Startup | Middlewares | Core | FATFS | USB_DEVICE || || || ${workspace_loc:/${ProjName}/STM32L476RGTX_FLASH.ld} || true || NonSecure || || secure_nsclib.o || || None || " valueType="string"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat.34089756" name="Use float with printf from newlib-nano (-u _printf_float)" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.nanoprintffloat" useByScannerDiscovery="false" value="true" valueType="boolean"/>
<option id="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary.343825891" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.option.convertbinary" value="true" valueType="boolean"/>
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform.620354801" isAbstract="false" osList="all" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.targetplatform"/>
<builder buildPath="${workspace_loc:/mk4-time}/Release" id="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder.1346654687" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="Gnu Make Builder" parallelBuildOn="true" parallelizationNumber="optimal" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.builder"/>
<tool id="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler.110828471" name="MCU GCC Assembler" superClass="com.st.stm32cube.ide.mcu.gnu.managedbuild.tool.assembler">

View File

@@ -5,8 +5,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="185955069870389989" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="0000000000000000000" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
@@ -17,8 +16,7 @@
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
<provider copy-of="extension" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser"/>
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="115984574982993951" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<provider class="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" console="false" env-hash="0000000000000000000" id="com.st.stm32cube.ide.mcu.toolchain.armnone.setup.CrossBuiltinSpecsDetector" keep-relative-paths="false" name="MCU ARM GCC Built-in Compiler Settings" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>

View File

@@ -1,4 +1,4 @@
2F62501ED4689FB349E356AB974DBE57=567EE81E60C8A1A45682D5C5317E6662
8DF89ED150041C4CBC7CB9A9CAA90856=567EE81E60C8A1A45682D5C5317E6662
DC22A860405A8BF2F2C095E5B6529F12=AA705B8CAFB58EBE5E4C71DC01DEB86F
DC22A860405A8BF2F2C095E5B6529F12=AFF9D44B33335AD8FB5822992DE506A7
eclipse.preferences.version=1

View File

@@ -77,6 +77,9 @@ extern uint16_t buffer_b[];
extern _Bool delayedReadConfigFile;
extern _Bool delayedCheckOnEject;
extern _Bool waitingForLatch;
extern _Bool resendDate;
/* USER CODE END ET */
/* Exported constants --------------------------------------------------------*/
@@ -148,6 +151,7 @@ enum {
MODE_TEXT,
MODE_FIRMWARE_CRC_T,
MODE_FIRMWARE_CRC_D,
MODE_VBAT,
NUM_DISPLAY_MODES
};
@@ -182,6 +186,18 @@ enum {
RULES_CATEGORY_UNKNOWN,
RULES_ZONE_UNKNOWN
};
enum {
SV_GPS_L1=0,
SV_GPS_UNKNOWN,
SV_GLONASS_L1,
SV_GLONASS_UNKNOWN,
SV_GALILEO_E1,
SV_GALILEO_UNKNOWN,
SV_BEIDOU_B1,
SV_BEIDOU_UNKNOWN,
SV_COUNT
};
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
@@ -200,7 +216,7 @@ void Error_Handler(void);
/* USER CODE BEGIN EFP */
void decodeRMC(void);
void decodeGSV(void);
void decodeGSV(uint8_t rec);
void setDisplayPWM(uint32_t bright);
void write_rtc(void);
void displayOff(void);
@@ -226,9 +242,13 @@ void monitor_vbus(void);
#define triggerPendSV() \
SCB->ICSR = SCB_ICSR_PENDSVSET_Msk;
#define sendLatch() \
huart2.Instance->TDR = 0xFE;
#define loadNextTimestamp() \
latchSegments() \
huart2.Instance->TDR = 0xFE; \
sendLatch() \
waitingForLatch=0;\
triggerPendSV()
extern uint32_t __VECTORS_FLASH[];

View File

@@ -61,6 +61,6 @@ QSPI_STATUS QSPI_Write_Sector(uint8_t *pData, uint32_t address);
uint8_t QSPI_Initialized();
uint8_t QSPI_Locked();
extern uint32_t qspi_write_time;
extern uint32_t qspi_usb_read_time;
extern volatile uint32_t qspi_write_time;
extern volatile uint32_t qspi_usb_read_time;
#endif

View File

@@ -367,15 +367,21 @@ void firmwareCheckOnEject(){
if (f_open(&file2, "/FWT.BIN", FA_READ) == FR_OK) {
f_lseek(&file2, TIME_APP_SIZE - 4);
f_read(&file2, &new_fwt_crc, 4, &rc);
if (rc==4 && new_fwt_crc != cur_fwt_crc)
if (rc==4 && new_fwt_crc != cur_fwt_crc) {
displayOff();
HAL_Delay(5);
NVIC_SystemReset();
}
}
if (f_open(&file1, "/FWD.BIN", FA_READ) == FR_OK) {
f_lseek(&file1, DATE_APP_SIZE - 4);
f_read(&file1, &new_fwd_crc, 4, &rc);
if (rc==4 && new_fwd_crc != cur_fwd_crc)
if (rc==4 && new_fwd_crc != cur_fwd_crc) {
displayOff();
HAL_Delay(5);
NVIC_SystemReset();
}
}
delayedCheckOnEject = 0;
}

View File

@@ -50,6 +50,7 @@
/* Private variables ---------------------------------------------------------*/
ADC_HandleTypeDef hadc1;
ADC_HandleTypeDef hadc3;
CRC_HandleTypeDef hcrc;
@@ -96,6 +97,7 @@ static void MX_TIM7_Init(void);
static void MX_CRC_Init(void);
static void MX_LPTIM1_Init(void);
static void MX_TIM5_Init(void);
static void MX_ADC3_Init(void);
/* USER CODE BEGIN PFP */
void tmToBcd(struct tm *in, bcdStamp_t *out );
uint8_t loadRulesSingle(char * str);
@@ -118,12 +120,14 @@ uint8_t uart2_tx_buffer[32];
volatile uint16_t buffer_adc[ADC_BUFFER_SIZE] = {0};
uint16_t buffer_dac[DAC_BUFFER_SIZE] = {[0 ... DAC_BUFFER_SIZE-1] = 4095};
float dac_target=4095;
float vbat = 0.0;
uint16_t buffer_colons_L[200] = {0};
uint16_t buffer_colons_R[200] = {0};
uint8_t nmea[NMEA_BUF_SIZE];
uint8_t GPS_sv = 255, GLONASS_sv = 255;
uint8_t satview[SV_COUNT];
uint8_t satview_stale = 0;
time_t currentTime;
bcdStamp_t nextBcd;
@@ -160,6 +164,10 @@ char textDisplay[32];
_Bool delayedLoadRules = 0;
_Bool delayedReadConfigFile = 0;
_Bool delayedCheckOnEject = 0;
uint32_t delayedDisplayFreq = 0;
_Bool waitingForLatch = 0;
_Bool resendDate = 0;
uint32_t LPTIM1_high;
@@ -206,8 +214,21 @@ void memcpyword(volatile uint32_t *dest, volatile uint32_t *src, size_t n){
}
}
// 12 bytes at 115200 8E1 is 1.14ms, 32 bytes would be 3.06ms
void sendDate( _Bool now ){
if (waitingForLatch) {
if (countMode==COUNT_HIDDEN) {
// if we've entered count_hidden while waiting for latch, it will never happen
sendLatch()
waitingForLatch=0;
} else {
resendDate=1;
return;
}
}
uint8_t i = 10;
HAL_UART_AbortTransmit(&huart2);
uart2_tx_buffer[0] = CMD_LOAD_TEXT;
switch (displayMode) {
@@ -302,12 +323,28 @@ void sendDate( _Bool now ){
i = sprintf((char*)&uart2_tx_buffer[1], "%s", wday_str[tm_wday]);
break;
case MODE_SATVIEW:
if (GPS_sv==255) {
i = sprintf((char*)&uart2_tx_buffer[1], "GPS - L-");
} else if (GLONASS_sv==255) {
i = sprintf((char*)&uart2_tx_buffer[1], "GPS %d. L-", GPS_sv);
if (satview[SV_GPS_L1]==255 && satview[SV_GPS_UNKNOWN]==255) {
i = sprintf((char*)&uart2_tx_buffer[1], "GPS -");
} else {
i = sprintf((char*)&uart2_tx_buffer[1], "GPS %d. L%d", GPS_sv, GLONASS_sv);
uint8_t GPS_sv = 0, GLONASS_sv = 0, GALILEO_sv = 0, BEIDOU_sv = 0;
if (satview[SV_GPS_L1]!=255) GPS_sv += satview[SV_GPS_L1];
if (satview[SV_GPS_UNKNOWN]!=255) GPS_sv += satview[SV_GPS_UNKNOWN];
if (satview[SV_GLONASS_L1]!=255) GLONASS_sv += satview[SV_GLONASS_L1];
if (satview[SV_GLONASS_UNKNOWN]!=255) GLONASS_sv += satview[SV_GLONASS_UNKNOWN];
if (satview[SV_GALILEO_E1]!=255) GALILEO_sv += satview[SV_GALILEO_E1];
if (satview[SV_GALILEO_UNKNOWN]!=255) GALILEO_sv += satview[SV_GALILEO_UNKNOWN];
if (satview[SV_BEIDOU_B1]!=255) BEIDOU_sv += satview[SV_BEIDOU_B1];
if (satview[SV_BEIDOU_UNKNOWN]!=255) BEIDOU_sv += satview[SV_BEIDOU_UNKNOWN];
if (GLONASS_sv>0 && GLONASS_sv>=GALILEO_sv && GLONASS_sv>=BEIDOU_sv) {
i = sprintf((char*)&uart2_tx_buffer[1], "GPS %d L%d", GPS_sv, GLONASS_sv);
} else if (GALILEO_sv>0 && GALILEO_sv>=GLONASS_sv && GALILEO_sv>=BEIDOU_sv){
i = sprintf((char*)&uart2_tx_buffer[1], "GPS %d A%d", GPS_sv, GALILEO_sv);
} else if (BEIDOU_sv>0 && BEIDOU_sv>=GLONASS_sv && BEIDOU_sv>=GALILEO_sv){
i = sprintf((char*)&uart2_tx_buffer[1], "GPS %d b%d", GPS_sv, BEIDOU_sv);
} else {
i = sprintf((char*)&uart2_tx_buffer[1], "GPS %d -", GPS_sv);
}
}
break;
case MODE_STANDBY:
@@ -329,6 +366,13 @@ void sendDate( _Bool now ){
i=1;
}
break;
case MODE_VBAT:
if (vbat == 0.0) {
i = sprintf((char*)&uart2_tx_buffer[1], "bat -");
} else {
i = sprintf((char*)&uart2_tx_buffer[1], "bat %.4f", vbat);
}
break;
case MODE_FIRMWARE_CRC_T:
{
extern uint32_t _app_crc[];
@@ -340,8 +384,12 @@ void sendDate( _Bool now ){
uart2_tx_buffer[0]=CMD_SHOW_CRC;
break;
}
uart2_tx_buffer[++i]= now ? CMD_RELOAD_TEXT : '\n';
HAL_UART_AbortTransmit(&huart2);
if (now) {
uart2_tx_buffer[++i]= CMD_RELOAD_TEXT;
} else {
uart2_tx_buffer[++i]= '\n';
waitingForLatch=1;
}
HAL_UART_Transmit_DMA(&huart2, uart2_tx_buffer, i+1);
}
@@ -580,12 +628,47 @@ void decodeRMC(void){
}
void decodeGSV(void){
uint8_t sv = (nmea[11]-'0')*10 + (nmea[12]-'0');
if (nmea[2] == 'P') {
GPS_sv = sv;
} else if (nmea[2] == 'L') {
GLONASS_sv = sv;
void decodeGSV(uint8_t rec){
unsigned int sv = (nmea[11]-'0')*10 + (nmea[12]-'0');
uint8_t constellation = nmea[2];
uint8_t signal_id;
// signal ID is not always present in GSV (on M8Q)
unsigned int num_fields = 0, r=0;
while (++r<rec) if (nmea[r]==',') num_fields++;
if (num_fields % 4 != 0) {
signal_id = '0';
} else {
signal_id = nmea[rec-6];
}
if (constellation == 'P') {
if (signal_id == '0') {
satview[SV_GPS_UNKNOWN] = sv;
} else {
satview[SV_GPS_L1] = sv;
}
satview_stale = 0;
} else if (constellation == 'L') {
if (signal_id == '0') {
satview[SV_GLONASS_UNKNOWN] = sv;
} else {
satview[SV_GLONASS_L1] = sv;
}
} else if (constellation == 'A') {
if (signal_id == '0') {
satview[SV_GALILEO_UNKNOWN] = sv;
} else {
satview[SV_GALILEO_E1] = sv;
}
} else if (constellation == 'B') {
if (signal_id == '0') {
satview[SV_BEIDOU_UNKNOWN] = sv;
} else {
satview[SV_BEIDOU_B1] = sv;
}
}
}
@@ -619,14 +702,21 @@ void displayOn(void){
}
void setDisplayFreq(uint32_t freq){
if (waitingForLatch) {
delayedDisplayFreq = freq;
return;
}
if (freq<1000 || freq>100000) return;
if (freq<1000 || freq>100000) {delayedDisplayFreq=0; return;}
uart2_tx_buffer[0]= CMD_SET_FREQUENCY;
uart2_tx_buffer[1]= (freq>>14) & 0x7F;
uart2_tx_buffer[2]= (freq>>7) & 0x7F;
uart2_tx_buffer[3]= (freq) & 0x7F;
HAL_UART_Transmit(&huart2, uart2_tx_buffer, 4, 2);
uint8_t tx_buf[4];
tx_buf[0]= CMD_SET_FREQUENCY;
tx_buf[1]= (freq>>14) & 0x7F;
tx_buf[2]= (freq>>7) & 0x7F;
tx_buf[3]= (freq) & 0x7F;
if (HAL_UART_Transmit(&huart2, tx_buf, 4, 2) == HAL_OK) {
delayedDisplayFreq = 0;
}
uint32_t arr = round(16000000.0 / (float)freq) -1.0;
@@ -742,11 +832,10 @@ void parseConfigString(char *key, char *value) {
if (strcasecmp(key, "text") == 0) {
strcpy(textDisplay, value);
strcpy(textDisplay, value);
} else if (strcasecmp(key, "MATRIX_FREQUENCY") == 0) {
//todo: check not waiting for latch
setDisplayFreq(atoi(value));
} else if (strcasecmp(key, "zone_override") == 0) {
@@ -804,6 +893,8 @@ void parseConfigString(char *key, char *value) {
set_mode_enabled(MODE_DEBUG_RTC, value);
} else if (strcasecmp(key, "MODE_TEXT") == 0) {
set_mode_enabled(MODE_TEXT, value);
} else if (strcasecmp(key, "MODE_VBAT") == 0) {
set_mode_enabled(MODE_VBAT, value);
} else if (strcasecmp(key, "MODE_FIRMWARE_CRC") == 0) {
set_mode_enabled(MODE_FIRMWARE_CRC_D, value);
set_mode_enabled(MODE_FIRMWARE_CRC_T, value);
@@ -1340,7 +1431,15 @@ void monitor_vbus(void){
vbus_state = vbus;
}
void measure_vbat(void){
ADC123_COMMON->CCR |= ADC_CCR_VBATEN;
HAL_Delay(5);
HAL_ADC_Start(&hadc3);
HAL_ADC_PollForConversion(&hadc3, 10);
uint16_t adc = HAL_ADC_GetValue(&hadc3);
ADC123_COMMON->CCR &= ~ADC_CCR_VBATEN;
vbat = (float)adc *0.0024102564102564104;//3*3.29/4095.0;
}
uint8_t f_getzcmp(FIL* fp, char * str){
unsigned int rc;
@@ -1475,7 +1574,7 @@ void setPrecision(void){
SetSysTick( &SysTick_CountUp_P0 );
}
} else if (countMode == COUNT_DOWN) {
} else if (displayMode == MODE_COUNTDOWN) {
if (config.countdown_to >= currentTime) {
SetPPS( &PPS_Countdown );
@@ -1501,6 +1600,7 @@ void setPrecision(void){
}
} else {
countMode = COUNT_HIDDEN;
SetSysTick( &SysTick_CountUp_NoUpdate );
SetPPS( &PPS_NoUpdate );
buffer_c[0].low=cSegDecode0;
@@ -1519,10 +1619,10 @@ void setPrecision(void){
}
}
#define justExited(x) ((oldMode==x) && (displayMode != x))
void nextMode(_Bool reverse){
_Bool wasOff = (displayMode==MODE_STANDBY);
_Bool wasCountdown = (displayMode==MODE_COUNTDOWN);
uint8_t oldMode = displayMode;
if (requestMode!=255){
if (!config.modes_enabled[requestMode]) {
@@ -1541,36 +1641,35 @@ void nextMode(_Bool reverse){
} while (!config.modes_enabled[displayMode]);
}
if (wasOff && displayMode != MODE_STANDBY) displayOn();
if ( displayMode == MODE_ISO_WEEK ||
(wasCountdown && displayMode != MODE_COUNTDOWN)) {
// It shouldn't be possible to exit countdown mode at .9 seconds
// but if we did, it would show the wrong time for .1 seconds
if (justExited(MODE_VBAT)) vbat = 0.0;
if (justExited(MODE_STANDBY)) displayOn();
if ( displayMode == MODE_ISO_WEEK || justExited(MODE_COUNTDOWN)) {
// If we exit countdown mode at .9 seconds
// it will show the wrong time for .1 seconds
setNextTimestamp(currentTime);
}
if (displayMode == MODE_SHOW_OFFSET) {
if (countMode != COUNT_HIDDEN) {
countMode = COUNT_HIDDEN;
SetSysTick( &SysTick_CountUp_NoUpdate );
SetPPS( &PPS_NoUpdate );
colonAnimationStop()
TIM2->CCR1 = 0; // specific to show_offset
TIM2->CCR2 = 300;
}
countMode = COUNT_HIDDEN;
SetSysTick( &SysTick_CountUp_NoUpdate );
SetPPS( &PPS_NoUpdate );
colonAnimationStop()
TIM2->CCR1 = 0; // specific to show_offset
TIM2->CCR2 = 300;
} else if (displayMode == MODE_COUNTDOWN) {
if (countMode != COUNT_DOWN) {
if (config.countdown_to >= currentTime) {
countMode = COUNT_DOWN;
if (config.countdown_to >= currentTime) {
setNextCountdown(currentTime);
} else countdown_days = 0;
setPrecision();
TIM2->CCR1 = 0;
TIM2->CCR2 = 0;
latchSegments();
setNextCountdown(currentTime);
} else {
countMode = COUNT_HIDDEN;
countdown_days = 0;
}
setPrecision();
TIM2->CCR1 = 0;
TIM2->CCR2 = 0;
latchSegments();
}
else {
if (countMode != COUNT_NORMAL) {
@@ -1582,27 +1681,13 @@ void nextMode(_Bool reverse){
latchSegments();
}
}
sendDate(1);
}
void button1pressed(void){
// 12 bytes at 115200 8E1 is 1.14ms
nextMode(0);
// Normally this routine is only called when it is safe to do so
// But if we have just left COUNT_HIDDEN, the button press could have been called at any time, so
// avoid transmission if <3ms till rollover.
// If we are still in COUNT_HIDDEN, always send.
if (countMode == COUNT_HIDDEN || decisec!=9 || centisec!=9 || millisec<7)
sendDate(1);
// todo: detect this and resend date in pendsv
}
void button2pressed(void){
nextMode(1);
if (countMode == COUNT_HIDDEN || decisec!=9 || centisec!=9 || millisec<7)
sendDate(1);
}
void generateDACbuffer(uint16_t * buf) {
@@ -1740,7 +1825,7 @@ int main(void)
USART1->CR1 |= USART_CR1_UE;
MX_ADC3_Init();
// Configure ADC and DAC DMA for display brightness
HAL_ADC_Start(&hadc1);
@@ -1785,6 +1870,8 @@ int main(void)
readConfigFile();
checkDelayedLoadRules();
measure_vbat();
if (RTC->ISR & RTC_ISR_INITS) //RTC contains non-zero data
{
RTC_DateTypeDef sdate;
@@ -1795,7 +1882,7 @@ int main(void)
memcpyword( (uint32_t*)zone, (uint32_t*)&(RTC->BKP0R), 8 );
zone[31]=0;
if (loadRulesSingle(zone) != RULES_OK){ // takes 34ms -O0, 26ms -O2
if (loadRulesSingle(zone) != RULES_OK){ // takes ~8ms
memcpyword( (uint32_t*)loadedRulesString, (uint32_t*)&(RTC->BKP0R), 8 );
loadedRulesString[31]=0;//paranoia
memcpyword( (uint32_t*)rules, (uint32_t*)&(RTC->BKP8R), 22 );
@@ -1832,7 +1919,17 @@ int main(void)
setNextTimestamp( currentTime );
sendDate(1);
latchSegments();
rtc_good=1;
// As the coin cell goes flat, the RTC stops ticking long before the backup registers die.
// Powering on with a flat battery means the clock thinks no time has passed, and assumes it has good precision.
// Explicitly stop this by checking the battery voltage.
if (vbat > 2.70) {
rtc_good=1;
} else {
// trash the calibration time to ensure lowest precision display
if (currentTime - rtc_last_calibration < config.tolerance_100ms)
rtc_last_calibration -= config.tolerance_100ms +1;
}
} else { // backup domain reset
@@ -1842,11 +1939,13 @@ int main(void)
MX_RTC_Init();
}
vbat = 0.0; // don't allow measurement to go stale
setPrecision();
PPS_Init();
HAL_UART_Receive_DMA(&huart1, nmea, sizeof(nmea));
//#define MEASURE_LOOKUP_TIME
/* USER CODE END 2 */
@@ -1861,14 +1960,26 @@ int main(void)
new_position=0;
FIL mapfile;
if (f_open(&mapfile, MAP_FILENAME, FA_READ) == FR_OK) {
#ifdef MEASURE_LOOKUP_TIME
uint32_t start=uwTick;
#endif
ZoneDetect *const zdb = ZDOpenDatabase(&mapfile);
if (!zdb) {
// mapfile error
} else {
char* zone = ZDHelperSimpleLookupString(zdb, latitude, longitude);
#ifdef MEASURE_LOOKUP_TIME
uint32_t ztime=uwTick-start;
#endif
if (zone && !delayedLoadRules) {
#ifdef MEASURE_LOOKUP_TIME
start=uwTick;
#endif
loadRulesSingle(zone);
#ifdef MEASURE_LOOKUP_TIME
sprintf(textDisplay,"d%ld L%ld",ztime, uwTick-start);
#endif
}
free(zone);
ZDCloseDatabase(zdb);
@@ -1888,9 +1999,13 @@ int main(void)
checkDelayedLoadRules();
if (delayedDisplayFreq) setDisplayFreq(delayedDisplayFreq);
monitor_vbus();
// qspi_usb_read_time too?
if (displayMode == MODE_VBAT)
measure_vbat();
/* USER CODE END WHILE */
@@ -2035,6 +2150,72 @@ static void MX_ADC1_Init(void)
}
/**
* @brief ADC3 Initialization Function
* @param None
* @retval None
*/
static void MX_ADC3_Init(void)
{
/* USER CODE BEGIN ADC3_Init 0 */
/* USER CODE END ADC3_Init 0 */
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC3_Init 1 */
/* USER CODE END ADC3_Init 1 */
/** Common config
*/
hadc3.Instance = ADC3;
hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV2;
hadc3.Init.Resolution = ADC_RESOLUTION_12B;
hadc3.Init.DataAlign = ADC_DATAALIGN_RIGHT;
hadc3.Init.ScanConvMode = ADC_SCAN_DISABLE;
hadc3.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc3.Init.LowPowerAutoWait = DISABLE;
hadc3.Init.ContinuousConvMode = DISABLE;
hadc3.Init.NbrOfConversion = 1;
hadc3.Init.DiscontinuousConvMode = DISABLE;
hadc3.Init.NbrOfDiscConversion = 1;
hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc3.Init.DMAContinuousRequests = DISABLE;
hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc3.Init.OversamplingMode = ENABLE;
hadc3.Init.Oversampling.Ratio = ADC_OVERSAMPLING_RATIO_16;
hadc3.Init.Oversampling.RightBitShift = ADC_RIGHTBITSHIFT_4;
hadc3.Init.Oversampling.TriggeredMode = ADC_TRIGGEREDMODE_SINGLE_TRIGGER;
hadc3.Init.Oversampling.OversamplingStopReset = ADC_REGOVERSAMPLING_RESUMED_MODE;
if (HAL_ADC_Init(&hadc3) != HAL_OK)
{
Error_Handler();
}
HAL_ADCEx_Calibration_Start(&hadc3, ADC_SINGLE_ENDED);
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_VBAT;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_640CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN ADC3_Init 2 */
ADC123_COMMON->CCR &= ~ADC_CCR_VBATEN;
/* USER CODE END ADC3_Init 2 */
}
/**
* @brief CRC Initialization Function
* @param None

View File

@@ -10,8 +10,8 @@ static QSPI_STATUS QSPI_Write_Page(uint8_t *pData, uint32_t address);
uint8_t initialized = 0;
uint8_t locked = 0;
uint32_t qspi_write_time = 0;
uint32_t qspi_usb_read_time = 0;
volatile uint32_t qspi_write_time = 0;
volatile uint32_t qspi_usb_read_time = 0;
uint8_t QSPI_Initialized()
{

View File

@@ -94,6 +94,8 @@ void HAL_MspInit(void)
/* USER CODE END MspInit 1 */
}
static uint32_t HAL_RCC_ADC_CLK_ENABLED=0;
/**
* @brief ADC MSP Initialization
* This function configures the hardware resources used in this example
@@ -109,7 +111,10 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
/* USER CODE END ADC1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_ADC_CLK_ENABLE();
HAL_RCC_ADC_CLK_ENABLED++;
if(HAL_RCC_ADC_CLK_ENABLED==1){
__HAL_RCC_ADC_CLK_ENABLE();
}
__HAL_RCC_GPIOA_CLK_ENABLE();
/**ADC1 GPIO Configuration
@@ -124,6 +129,20 @@ void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
/* USER CODE END ADC1_MspInit 1 */
}
else if(hadc->Instance==ADC3)
{
/* USER CODE BEGIN ADC3_MspInit 0 */
/* USER CODE END ADC3_MspInit 0 */
/* Peripheral clock enable */
HAL_RCC_ADC_CLK_ENABLED++;
if(HAL_RCC_ADC_CLK_ENABLED==1){
__HAL_RCC_ADC_CLK_ENABLE();
}
/* USER CODE BEGIN ADC3_MspInit 1 */
/* USER CODE END ADC3_MspInit 1 */
}
}
@@ -141,7 +160,10 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
/* USER CODE END ADC1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_ADC_CLK_DISABLE();
HAL_RCC_ADC_CLK_ENABLED--;
if(HAL_RCC_ADC_CLK_ENABLED==0){
__HAL_RCC_ADC_CLK_DISABLE();
}
/**ADC1 GPIO Configuration
PA5 ------> ADC1_IN10
@@ -152,6 +174,20 @@ void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
/* USER CODE END ADC1_MspDeInit 1 */
}
else if(hadc->Instance==ADC3)
{
/* USER CODE BEGIN ADC3_MspDeInit 0 */
/* USER CODE END ADC3_MspDeInit 0 */
/* Peripheral clock disable */
HAL_RCC_ADC_CLK_ENABLED--;
if(HAL_RCC_ADC_CLK_ENABLED==0){
__HAL_RCC_ADC_CLK_DISABLE();
}
/* USER CODE BEGIN ADC3_MspDeInit 1 */
/* USER CODE END ADC3_MspDeInit 1 */
}
}

View File

@@ -44,7 +44,7 @@
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
uint8_t delayButtonPress=0;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
@@ -69,7 +69,8 @@ extern UART_HandleTypeDef huart1;
extern UART_HandleTypeDef huart2;
/* USER CODE BEGIN EV */
extern uint8_t nmea[90];
extern uint8_t GPS_sv, GLONASS_sv;
extern uint8_t satview[SV_COUNT];
extern uint8_t satview_stale;
extern uint16_t buffer_adc[ADC_BUFFER_SIZE];
extern uint16_t buffer_dac[DAC_BUFFER_SIZE];
extern DAC_HandleTypeDef hdac1;
@@ -80,8 +81,8 @@ extern _Bool data_valid, had_pps;
extern uint8_t decisec, centisec, millisec;
extern uint8_t displayMode, countMode, nmea_cdc_level;
extern uint32_t qspi_write_time;
extern uint32_t qspi_usb_read_time;
extern volatile uint32_t qspi_write_time;
extern volatile uint32_t qspi_usb_read_time;
/* USER CODE END EV */
@@ -205,18 +206,30 @@ void PendSV_Handler(void)
// Writing to the RTC is normally very fast, but if something goes wrong
// the HAL functions will fail to time out if it's running with the same
// preemption priority as systick
if (had_pps) write_rtc();
if (had_pps && !qspi_write_time && !qspi_usb_read_time) write_rtc();
//if (buffer_c[3].high & cSegDP) buffer_c[3].high&=~cSegDP; else buffer_c[3].high|=cSegDP;
if (delayButtonPress & 1) { delayButtonPress &= ~1; button1pressed(); }
if (delayButtonPress & 2) { delayButtonPress &= ~2; button2pressed(); }
if (waitingForLatch) {
// in the specific case of countdown reaching zero, it will leave the latch hanging
sendLatch()
waitingForLatch=0;
}
setPrecision();
if (displayMode==MODE_SHOW_OFFSET) {sendDate(1);}
if (resendDate) {sendDate(1); resendDate=0;}
GLONASS_sv = 255; GPS_sv = 255;
if (satview_stale>3){
satview[SV_GPS_L1]=255;
satview[SV_GPS_UNKNOWN]=255;
satview[SV_GLONASS_L1]=255;
satview[SV_GLONASS_UNKNOWN]=255;
satview[SV_GALILEO_E1]=255;
satview[SV_GALILEO_UNKNOWN]=255;
satview[SV_BEIDOU_B1]=255;
satview[SV_BEIDOU_UNKNOWN]=255;
} else satview_stale++;
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
@@ -357,7 +370,7 @@ void USART1_IRQHandler(void)
&& nmea[3]=='G'
&& nmea[4]=='S'
&& nmea[5]=='V')
decodeGSV();
decodeGSV(rec);
HAL_UART_AbortReceive(&huart1);
@@ -385,12 +398,9 @@ void USART2_IRQHandler(void)
uint8_t x = (USART2->RDR &0xFF);
if (x == 0x91) {
// if we're beyond 0.9 seconds the date side will already be waiting for latch
if (decisec==9 && countMode!=COUNT_HIDDEN) delayButtonPress |= 1;
else button1pressed();
button1pressed();
} else if (x == 0x92) {
if (decisec==9 && countMode!=COUNT_HIDDEN) delayButtonPress |= 2;
else button2pressed();
button2pressed();
}
return;
}

View File

@@ -24,6 +24,7 @@
/* Includes */
#include <errno.h>
#include <stdio.h>
#include <sys/types.h>
/* Variables */
extern int errno;

View File

@@ -1,3 +1,4 @@
// in pre-build steps: rm -f Core/Src/version.o
#define VERSION_STRING "Version 0.0.1 "
#include "../../../version.h"

View File

@@ -80,8 +80,8 @@ struct ZoneDetectOpaque {
uint8_t mapCache[MAP_CACHE_SIZE];
uint32_t mapCacheStart = 0xffffffff, mapCacheEnd = 0;
extern uint32_t qspi_write_time;
extern uint32_t qspi_usb_read_time;
extern volatile uint32_t qspi_write_time;
extern volatile uint32_t qspi_usb_read_time;
volatile _Bool zd_abort =0;
void ZDAbort(){

View File

@@ -9,6 +9,15 @@ ADC1.Overrun=ADC_OVR_DATA_OVERWRITTEN
ADC1.Rank-0\#ChannelRegularConversion=1
ADC1.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_92CYCLES_5
ADC1.master=1
ADC3.Channel-0\#ChannelRegularConversion=ADC_CHANNEL_VBAT
ADC3.IPParameters=Rank-0\#ChannelRegularConversion,Channel-0\#ChannelRegularConversion,SamplingTime-0\#ChannelRegularConversion,OffsetNumber-0\#ChannelRegularConversion,NbrOfConversionFlag
ADC3.NbrOfConversionFlag=1
ADC3.OffsetNumber-0\#ChannelRegularConversion=ADC_OFFSET_NONE
ADC3.Rank-0\#ChannelRegularConversion=1
ADC3.SamplingTime-0\#ChannelRegularConversion=ADC_SAMPLETIME_2CYCLES_5
CAD.formats=
CAD.pinconfig=
CAD.provider=
CRC.IPParameters=InputDataInversionMode,OutputDataInversionMode,InputDataFormat
CRC.InputDataFormat=CRC_INPUTDATA_FORMAT_WORDS
CRC.InputDataInversionMode=CRC_INPUTDATA_INVERSION_BYTE
@@ -94,28 +103,30 @@ FATFS._MIN_SS=4096
File.Version=6
GPIO.groupedBy=Group By Peripherals
KeepUserPlacement=false
Mcu.CPN=STM32L476RGT3
Mcu.Family=STM32L4
Mcu.IP0=ADC1
Mcu.IP1=CRC
Mcu.IP10=SYS
Mcu.IP11=TIM1
Mcu.IP12=TIM2
Mcu.IP13=TIM5
Mcu.IP14=TIM6
Mcu.IP15=TIM7
Mcu.IP16=USART1
Mcu.IP17=USART2
Mcu.IP18=USB_DEVICE
Mcu.IP19=USB_OTG_FS
Mcu.IP2=DAC1
Mcu.IP3=DMA
Mcu.IP4=FATFS
Mcu.IP5=LPTIM1
Mcu.IP6=NVIC
Mcu.IP7=QUADSPI
Mcu.IP8=RCC
Mcu.IP9=RTC
Mcu.IPNb=20
Mcu.IP1=ADC3
Mcu.IP10=RTC
Mcu.IP11=SYS
Mcu.IP12=TIM1
Mcu.IP13=TIM2
Mcu.IP14=TIM5
Mcu.IP15=TIM6
Mcu.IP16=TIM7
Mcu.IP17=USART1
Mcu.IP18=USART2
Mcu.IP19=USB_DEVICE
Mcu.IP2=CRC
Mcu.IP20=USB_OTG_FS
Mcu.IP3=DAC1
Mcu.IP4=DMA
Mcu.IP5=FATFS
Mcu.IP6=LPTIM1
Mcu.IP7=NVIC
Mcu.IP8=QUADSPI
Mcu.IP9=RCC
Mcu.IPNb=21
Mcu.Name=STM32L476R(C-E-G)Tx
Mcu.Package=LQFP64
Mcu.Pin0=PC13
@@ -159,51 +170,52 @@ Mcu.Pin42=PB6
Mcu.Pin43=PB7
Mcu.Pin44=PB8
Mcu.Pin45=PB9
Mcu.Pin46=VP_CRC_VS_CRC
Mcu.Pin47=VP_FATFS_VS_Generic
Mcu.Pin48=VP_LPTIM1_VS_LPTIM_counterModeInternalClock
Mcu.Pin49=VP_RTC_VS_RTC_Activate
Mcu.Pin46=VP_ADC3_Vbat_Input
Mcu.Pin47=VP_CRC_VS_CRC
Mcu.Pin48=VP_FATFS_VS_Generic
Mcu.Pin49=VP_LPTIM1_VS_LPTIM_counterModeInternalClock
Mcu.Pin5=PC0
Mcu.Pin50=VP_SYS_VS_Systick
Mcu.Pin51=VP_TIM1_VS_ClockSourceINT
Mcu.Pin52=VP_TIM5_VS_ClockSourceINT
Mcu.Pin53=VP_TIM5_VS_no_output1
Mcu.Pin54=VP_TIM5_VS_no_output2
Mcu.Pin55=VP_TIM6_VS_ClockSourceINT
Mcu.Pin56=VP_TIM7_VS_ClockSourceINT
Mcu.Pin57=VP_USB_DEVICE_VS_USB_DEVICE_MSC_FS
Mcu.Pin50=VP_RTC_VS_RTC_Activate
Mcu.Pin51=VP_SYS_VS_Systick
Mcu.Pin52=VP_TIM1_VS_ClockSourceINT
Mcu.Pin53=VP_TIM5_VS_ClockSourceINT
Mcu.Pin54=VP_TIM5_VS_no_output1
Mcu.Pin55=VP_TIM5_VS_no_output2
Mcu.Pin56=VP_TIM6_VS_ClockSourceINT
Mcu.Pin57=VP_TIM7_VS_ClockSourceINT
Mcu.Pin58=VP_USB_DEVICE_VS_USB_DEVICE_MSC_FS
Mcu.Pin6=PC1
Mcu.Pin7=PC2
Mcu.Pin8=PC3
Mcu.Pin9=PA0
Mcu.PinsNb=58
Mcu.PinsNb=59
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32L476RGTx
MxCube.Version=5.6.0
MxDb.Version=DB.5.0.60
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.DMA1_Channel3_IRQn=true\:1\:0\:true\:false\:true\:false\:true
NVIC.DMA1_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true
NVIC.DMA1_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true
NVIC.DMA1_Channel6_IRQn=true\:0\:0\:false\:false\:true\:false\:true
NVIC.DMA1_Channel7_IRQn=true\:0\:0\:false\:false\:true\:false\:true
NVIC.DMA2_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true
NVIC.DMA2_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.BusFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.DMA1_Channel3_IRQn=true\:1\:0\:true\:false\:true\:false\:true\:true
NVIC.DMA1_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DMA1_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DMA1_Channel6_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DMA1_Channel7_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DMA2_Channel4_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DMA2_Channel5_IRQn=true\:0\:0\:false\:false\:true\:false\:true\:true
NVIC.DebugMonitor_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.ForceEnableDMAVector=true
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.LPTIM1_IRQn=true\:1\:0\:true\:false\:true\:true\:true
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.OTG_FS_IRQn=true\:1\:0\:true\:false\:true\:false\:true
NVIC.PendSV_IRQn=true\:2\:0\:true\:false\:true\:false\:false
NVIC.HardFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.LPTIM1_IRQn=true\:1\:0\:true\:false\:true\:true\:true\:true
NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.OTG_FS_IRQn=true\:1\:0\:true\:false\:true\:false\:true\:true
NVIC.PendSV_IRQn=true\:2\:0\:true\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:false\:false\:false
NVIC.USART1_IRQn=true\:1\:0\:true\:false\:true\:true\:false
NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:0\:0\:true\:false\:false\:false\:false\:false
NVIC.USART1_IRQn=true\:1\:0\:true\:false\:true\:true\:false\:true
NVIC.USART2_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.UsageFault_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
PA0.Signal=S_TIM2_CH1
PA1.Signal=S_TIM2_CH2
PA10.Mode=Asynchronous
@@ -322,10 +334,13 @@ ProjectManager.PreviousToolchain=
ProjectManager.ProjectBuild=false
ProjectManager.ProjectFileName=mk4-time.ioc
ProjectManager.ProjectName=mk4-time
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=STM32CubeIDE
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=true
ProjectManager.functionlistsort=1-MX_GPIO_Init-GPIO-false-HAL-true,2-MX_DMA_Init-DMA-false-HAL-true,3-SystemClock_Config-RCC-false-HAL-false,4-MX_QUADSPI_Init-QUADSPI-false-HAL-true,5-MX_TIM1_Init-TIM1-false-HAL-true,6-MX_USART2_UART_Init-USART2-false-HAL-true,7-MX_FATFS_Init-FATFS-false-HAL-false,8-MX_USB_DEVICE_Init-USB_DEVICE-false-HAL-false,9-MX_USART1_UART_Init-USART1-false-HAL-true,10-MX_TIM2_Init-TIM2-false-HAL-true,11-MX_ADC1_Init-ADC1-false-HAL-true,12-MX_DAC1_Init-DAC1-false-HAL-true,13-MX_TIM6_Init-TIM6-false-HAL-true,14-MX_RTC_Init-RTC-true-HAL-true,15-MX_TIM7_Init-TIM7-false-HAL-true,16-MX_CRC_Init-CRC-false-HAL-true,17-MX_LPTIM1_Init-LPTIM1-false-LL-true,18-MX_TIM5_Init-TIM5-false-HAL-true
QUADSPI.ClockPrescaler-Single\ Bank=0
@@ -445,6 +460,8 @@ USB_DEVICE.VirtualMode=Msc
USB_DEVICE.VirtualModeFS=Msc_FS
USB_OTG_FS.IPParameters=VirtualMode
USB_OTG_FS.VirtualMode=Device_Only
VP_ADC3_Vbat_Input.Mode=IN-Vbat
VP_ADC3_Vbat_Input.Signal=ADC3_Vbat_Input
VP_CRC_VS_CRC.Mode=CRC_Activate
VP_CRC_VS_CRC.Signal=CRC_VS_CRC
VP_FATFS_VS_Generic.Mode=User_defined
@@ -470,3 +487,4 @@ VP_TIM7_VS_ClockSourceINT.Signal=TIM7_VS_ClockSourceINT
VP_USB_DEVICE_VS_USB_DEVICE_MSC_FS.Mode=MSC_FS
VP_USB_DEVICE_VS_USB_DEVICE_MSC_FS.Signal=USB_DEVICE_VS_USB_DEVICE_MSC_FS
board=custom
isbadioc=false

View File

@@ -8,6 +8,7 @@ MATRIX_FREQUENCY = 20000
# Use this timezone, leave blank to calculate automatically
# Must be an IANA timezone string, use e.g. Etc/GMT+5 for fixed offsets
# For UTC use Etc/UTC
#ZONE_OVERRIDE = America/New_York
@@ -19,13 +20,13 @@ MATRIX_FREQUENCY = 20000
MODE_ISO8601_STD=Enabled
# ISO8601 ordinal (day of year)
MODE_ISO_Ordinal=Enabled
MODE_ISO_Ordinal=disabled
# ISO8601 week (year can be different around new year)
MODE_ISO_WEEK = disabled
# Unix timestamp mode. The unix timestamp is always UTC.
MODE_UNIX = Enabled
MODE_UNIX = Disabled
# Julian Date
MODE_JULIAN_DATE = disabled
@@ -40,14 +41,14 @@ MODE_SHOW_OFFSET = enabled
# Attempt to display tz name on the 7-segment display, this is usually fairly illegible
MODE_SHOW_TZ_NAME = enabled
MODE_WEEKDAY = enabled
MODE_WEEKDAY = disabled
# Turn off all LEDs. This mode can be useful if you want to reduce power consumption
# but keep the GPS module fully powered.
MODE_STANDBY=Enabled
MODE_STANDBY=disabled
MODE_COUNTDOWN = on
MODE_COUNTDOWN = off
COUNTDOWN_TO = 2023-05-06T23:00:00Z
@@ -76,11 +77,12 @@ Tolerance_time_100ms = 100000
# nonlinear brightness curve, five stops of input->output, use brightness-curve.htm for a GUI
#BS1 = 0,0
#BS2 = 1425,737
#BS3 = 2566,1601
#BS4 = 3396,2725
#BS5 = 4095,4095
# VTT9812FH with R11 = 470K
BS1 = 0,0
BS2 = 131,365
BS3 = 1076,1422
BS4 = 2774,2665
BS5 = 3849,4095
# shows input and output values of DAC/ADC
MODE_DEBUG_BRIGHTNESS = 0
@@ -91,5 +93,8 @@ MODE_DEBUG_BRIGHTNESS = 0
# show remainder of RTC calibration after 63 second period
MODE_DEBUG_RTC = 0
# list number of GPS/GLONASS satellites (number, not signal strength)
mode_satview = 1
# list number of satellites in view (number, not signal strength)
mode_satview = 0
# show coin cell voltage
mode_vbat = 0

View File

@@ -37,6 +37,7 @@ function cleanup {
trap cleanup EXIT
sudo mkfs.fat -I -S 4096 "$dev"
sudo fatlabel "$dev" CLOCK
sudo mount "$dev" mnt/ # auto detects if loop device

BIN
qspi/output/fwd.bin Normal file

Binary file not shown.

BIN
qspi/output/fwt.bin Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -17,7 +17,7 @@ To run the builder install shapelib (and I had to add `#include <cstdint>`)
Rename `out/timezone21.bin` to `tzmap.bin`
The `out_v1/` format is smaller but takes longer to parse on the clock, so use the 11MB version.
The `out_v1/` format is smaller but takes longer to parse on the clock, so use the `out/` version.
Natural earth data is used only for the "country" database which isn't used here. All data comes from https://github.com/evansiroky/timezone-boundary-builder
@@ -28,7 +28,7 @@ We need to match the zones in the shapefile, so it now uses the `timezone-names.
E.g.
```
curl -L https://github.com/evansiroky/timezone-boundary-builder/releases/download/2023b/timezone-names.json | jq '.' > timezone-names.json
curl -L https://github.com/evansiroky/timezone-boundary-builder/releases/download/2025b/timezone-names.json | jq '.' > timezone-names.json
```
The `generate-tzrules.py` file uses these names and the installed timezone database on the system it's running. Query the tzdata package to see the version (`pacman -Q tzdata` or `apt show tzdata`)
@@ -48,4 +48,4 @@ Both firmware images are unencrypted/unobfuscated, but the last 32bit word of ea
The update is performed if the CRC of the image in external flash is valid and different to the CRC of the loaded image, so downgrades are easy.
## loop device to create disk image
`create-image.sh` will create a correctly formatted 16MB disk image of the QSPI contents using a loop device. The resulting image can be written using `dd` or some other disk image utility, which may be more convenient on other platforms.
`./flash.sh loop` will create a correctly formatted 16MB disk image of the QSPI contents using a loop device. The resulting image can be written using `dd` or some other disk image utility, which may be more convenient on other platforms.

View File

@@ -90,6 +90,7 @@
"America/Chihuahua",
"America/Ciudad_Juarez",
"America/Costa_Rica",
"America/Coyhaique",
"America/Creston",
"America/Cuiaba",
"America/Curacao",
@@ -223,7 +224,6 @@
"Asia/Bishkek",
"Asia/Brunei",
"Asia/Chita",
"Asia/Choibalsan",
"Asia/Colombo",
"Asia/Damascus",
"Asia/Dhaka",

13
readme.md Normal file
View File

@@ -0,0 +1,13 @@
# Precision Clock Mk IV
Source code for the [Precision Clock Mk IV](https://mitxela.com/projects/precision_clock_mk_iv)
There are three software projects, compiled with STM32CubeIDE:
- mk4-time is the main clock source code running on the STM32L476
- mk4-date is the secondary display running on the STM32L010
- mk4-bootloader runs on the STM32L476 to do firmware updates
In the QSPI folder, there are scripts to create firmware images with CRC that the clock will recognise, along with the scripts to create the tzrules and create a valid disk image, see [these notes](qspi/qspi.md) for more info.
Timezone detection is ported from [ZoneDetect](https://github.com/BertoldVdb/ZoneDetect) by Bertold Van den Bergh and uses shapefile data from [Timezone Boundary Builder](https://github.com/evansiroky/timezone-boundary-builder) by Evan Siroky.