Compare commits
18 Commits
movement-2
...
moonrise
Author | SHA1 | Date | |
---|---|---|---|
|
49181dadde | ||
|
8abf6f4f5b | ||
|
8c39d42824 | ||
|
56f2c93783 | ||
|
14e64caac9 | ||
|
cc6a0c363e | ||
|
845caa30fb | ||
|
0ef5e5700e | ||
|
e8f31beb70 | ||
|
c2103d9eaa | ||
|
88338dc0ba | ||
|
e8ba597131 | ||
|
52c3d5b796 | ||
|
7af5626147 | ||
|
b2d313e0e7 | ||
|
0f5defe789 | ||
|
3634460a02 | ||
|
fc2f9c5130 |
34
PCB/Main Boards/OSO-SWAT-C1/ELT-3KN004B.wrl
Normal file
34
PCB/Main Boards/OSO-SWAT-C1/ELT-3KN004B.wrl
Normal file
File diff suppressed because one or more lines are too long
12383
PCB/Main Boards/OSO-SWAT-C1/EVP-BB4A9B000--3DModel-STEP-56544.STEP
Normal file
12383
PCB/Main Boards/OSO-SWAT-C1/EVP-BB4A9B000--3DModel-STEP-56544.STEP
Normal file
File diff suppressed because it is too large
Load Diff
8784
PCB/Main Boards/OSO-SWAT-C1/FH19C-9S-0.5SH.stp
Normal file
8784
PCB/Main Boards/OSO-SWAT-C1/FH19C-9S-0.5SH.stp
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
2373
PCB/Main Boards/OSO-SWAT-C1/NX3215SA.step
Normal file
2373
PCB/Main Boards/OSO-SWAT-C1/NX3215SA.step
Normal file
File diff suppressed because it is too large
Load Diff
6938
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-A1-05-eagle-import.kicad_sym
Normal file
6938
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-A1-05-eagle-import.kicad_sym
Normal file
File diff suppressed because it is too large
Load Diff
BIN
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-06.zip
Normal file
BIN
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-06.zip
Normal file
Binary file not shown.
93996
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-rounded.kicad_pcb
Normal file
93996
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-rounded.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
83
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-rounded.kicad_prl
Normal file
83
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-rounded.kicad_prl
Normal file
@ -0,0 +1,83 @@
|
||||
{
|
||||
"board": {
|
||||
"active_layer": 31,
|
||||
"active_layer_preset": "",
|
||||
"auto_track_width": true,
|
||||
"hidden_netclasses": [],
|
||||
"hidden_nets": [],
|
||||
"high_contrast_mode": 0,
|
||||
"net_color_mode": 1,
|
||||
"opacity": {
|
||||
"images": 0.6,
|
||||
"pads": 1.0,
|
||||
"tracks": 1.0,
|
||||
"vias": 1.0,
|
||||
"zones": 0.6
|
||||
},
|
||||
"ratsnest_display_mode": 0,
|
||||
"selection_filter": {
|
||||
"dimensions": true,
|
||||
"footprints": true,
|
||||
"graphics": true,
|
||||
"keepouts": true,
|
||||
"lockedItems": true,
|
||||
"otherItems": true,
|
||||
"pads": true,
|
||||
"text": true,
|
||||
"tracks": true,
|
||||
"vias": true,
|
||||
"zones": true
|
||||
},
|
||||
"visible_items": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36
|
||||
],
|
||||
"visible_layers": "00290aa_80000007",
|
||||
"zone_display_mode": 0
|
||||
},
|
||||
"git": {
|
||||
"repo_password": "",
|
||||
"repo_type": "",
|
||||
"repo_username": "",
|
||||
"ssh_key": ""
|
||||
},
|
||||
"meta": {
|
||||
"filename": "OSO-SWAT-C1-rounded.kicad_prl",
|
||||
"version": 3
|
||||
},
|
||||
"project": {
|
||||
"files": []
|
||||
}
|
||||
}
|
692
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-rounded.kicad_pro
Normal file
692
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1-rounded.kicad_pro
Normal file
@ -0,0 +1,692 @@
|
||||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"apply_defaults_to_fp_fields": false,
|
||||
"apply_defaults_to_fp_shapes": false,
|
||||
"apply_defaults_to_fp_text": false,
|
||||
"board_outline_line_width": 0.05,
|
||||
"copper_line_width": 0.2,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"copper_text_upright": false,
|
||||
"courtyard_line_width": 0.05,
|
||||
"dimension_precision": 4,
|
||||
"dimension_units": 3,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": false,
|
||||
"text_position": 0,
|
||||
"units_format": 1
|
||||
},
|
||||
"fab_line_width": 0.1,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.1,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": false,
|
||||
"pads": {
|
||||
"drill": 0.9,
|
||||
"height": 0.9,
|
||||
"width": 0.9
|
||||
},
|
||||
"silk_line_width": 0.12,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 1.0,
|
||||
"silk_text_size_v": 1.0,
|
||||
"silk_text_thickness": 0.15,
|
||||
"silk_text_upright": false,
|
||||
"zones": {
|
||||
"45_degree_only": false,
|
||||
"min_clearance": 1e-06
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [
|
||||
{
|
||||
"gap": 0.0,
|
||||
"via_gap": 0.0,
|
||||
"width": 0.0
|
||||
}
|
||||
],
|
||||
"drc_exclusions": [
|
||||
"clearance|6549579|23514621|0dac23a8-f43b-4e30-9a10-b757851281ba|192908ec-7c4c-4ab1-a565-bc709c96b57f",
|
||||
"clearance|7950000|22690000|821d722e-241b-43f8-bcb8-12290d54f4d9|192908ec-7c4c-4ab1-a565-bc709c96b57f",
|
||||
"clearance|7970521|23400521|e003e765-2ee5-400f-abaa-d669dc68a0c6|192908ec-7c4c-4ab1-a565-bc709c96b57f",
|
||||
"clearance|8581179|22000000|3dde5b5d-55b0-42ee-abfb-5429896be16c|192908ec-7c4c-4ab1-a565-bc709c96b57f",
|
||||
"clearance|8581179|22002512|3cab235c-f7da-46c2-8b4d-9d21002f2b49|192908ec-7c4c-4ab1-a565-bc709c96b57f",
|
||||
"items_not_allowed|6130279|23400521|0dac23a8-f43b-4e30-9a10-b757851281ba|00000000-0000-0000-0000-000000000000",
|
||||
"items_not_allowed|7050400|23400521|e003e765-2ee5-400f-abaa-d669dc68a0c6|00000000-0000-0000-0000-000000000000",
|
||||
"items_not_allowed|7950000|23035000|821d722e-241b-43f8-bcb8-12290d54f4d9|00000000-0000-0000-0000-000000000000",
|
||||
"items_not_allowed|8640000|22000000|3cab235c-f7da-46c2-8b4d-9d21002f2b49|00000000-0000-0000-0000-000000000000",
|
||||
"items_not_allowed|8780000|22000000|3dde5b5d-55b0-42ee-abfb-5429896be16c|00000000-0000-0000-0000-000000000000"
|
||||
],
|
||||
"meta": {
|
||||
"filename": "board_design_settings.json",
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"connection_width": "warning",
|
||||
"copper_edge_clearance": "warning",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "warning",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"footprint": "error",
|
||||
"footprint_symbol_mismatch": "warning",
|
||||
"footprint_type_mismatch": "error",
|
||||
"hole_clearance": "error",
|
||||
"hole_near_hole": "error",
|
||||
"holes_co_located": "warning",
|
||||
"invalid_outline": "error",
|
||||
"isolated_copper": "warning",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "warning",
|
||||
"lib_footprint_mismatch": "warning",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"npth_inside_courtyard": "ignore",
|
||||
"padstack": "error",
|
||||
"pth_inside_courtyard": "ignore",
|
||||
"shorting_items": "error",
|
||||
"silk_edge_clearance": "warning",
|
||||
"silk_over_copper": "warning",
|
||||
"silk_overlap": "warning",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "warning",
|
||||
"starved_thermal": "warning",
|
||||
"text_height": "warning",
|
||||
"text_thickness": "warning",
|
||||
"through_hole_pad_without_hole": "error",
|
||||
"too_many_vias": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rules": {
|
||||
"allow_blind_buried_vias": false,
|
||||
"allow_microvias": false,
|
||||
"max_error": 0.005,
|
||||
"min_clearance": 0.0889,
|
||||
"min_connection": 0.0,
|
||||
"min_copper_edge_clearance": 0.0889,
|
||||
"min_hole_clearance": 0.0889,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.2,
|
||||
"min_microvia_drill": 0.1,
|
||||
"min_resolved_spokes": 2,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.8,
|
||||
"min_text_thickness": 0.08,
|
||||
"min_through_hole_diameter": 0.2,
|
||||
"min_track_width": 0.0889,
|
||||
"min_via_annular_width": 0.125,
|
||||
"min_via_diameter": 0.45,
|
||||
"solder_mask_to_copper_clearance": 0.0,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"teardrop_options": [
|
||||
{
|
||||
"td_onpadsmd": true,
|
||||
"td_onroundshapesonly": false,
|
||||
"td_ontrackend": false,
|
||||
"td_onviapad": true
|
||||
}
|
||||
],
|
||||
"teardrop_parameters": [
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_round_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_rect_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_track_end",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
}
|
||||
],
|
||||
"track_widths": [
|
||||
0.0,
|
||||
0.0762,
|
||||
0.0889,
|
||||
0.1016,
|
||||
0.127,
|
||||
0.1524,
|
||||
0.1778,
|
||||
0.2032,
|
||||
0.254,
|
||||
0.3048,
|
||||
0.55
|
||||
],
|
||||
"tuning_pattern_settings": {
|
||||
"diff_pair_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 1.0
|
||||
},
|
||||
"diff_pair_skew_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"single_track_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
}
|
||||
},
|
||||
"via_dimensions": [
|
||||
{
|
||||
"diameter": 0.0,
|
||||
"drill": 0.0
|
||||
},
|
||||
{
|
||||
"diameter": 0.5588,
|
||||
"drill": 0.3048
|
||||
}
|
||||
],
|
||||
"zones_allow_external_fillets": false,
|
||||
"zones_use_no_outline": true
|
||||
},
|
||||
"ipc2581": {
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
},
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"conflicting_netclasses": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "error",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"simulation_model_issue": "error",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "OSO-SWAT-C1-rounded.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.0889,
|
||||
"diff_pair_gap": 0.0889,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.0889,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.45,
|
||||
"microvia_drill": 0.2,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.0889,
|
||||
"via_diameter": 0.45,
|
||||
"via_drill": 0.2,
|
||||
"wire_width": 6
|
||||
},
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.0889,
|
||||
"diff_pair_gap": 0.0889,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.0889,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.45,
|
||||
"microvia_drill": 0.2,
|
||||
"name": "gnd",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2032,
|
||||
"via_diameter": 0.45,
|
||||
"via_drill": 0.2,
|
||||
"wire_width": 6
|
||||
},
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.0889,
|
||||
"diff_pair_gap": 0.0889,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.0889,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.45,
|
||||
"microvia_drill": 0.2,
|
||||
"name": "power",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2032,
|
||||
"via_diameter": 0.45,
|
||||
"via_drill": 0.2,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 3
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": [
|
||||
{
|
||||
"netclass": "gnd",
|
||||
"pattern": "GND"
|
||||
},
|
||||
{
|
||||
"netclass": "power",
|
||||
"pattern": "VCC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"plot": "./OSO-SWAT-C1-06",
|
||||
"pos_files": "",
|
||||
"specctra_dsn": "",
|
||||
"step": "OSO-SWAT-C1.step",
|
||||
"svg": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"bom_export_filename": "OSO-SWAT-C1-05.csv",
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
"field_delimiter": ",",
|
||||
"keep_line_breaks": false,
|
||||
"keep_tabs": false,
|
||||
"name": "CSV",
|
||||
"ref_delimiter": ",",
|
||||
"ref_range_delimiter": "",
|
||||
"string_delimiter": "\""
|
||||
},
|
||||
"bom_presets": [],
|
||||
"bom_settings": {
|
||||
"exclude_dnp": false,
|
||||
"fields_ordered": [
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Reference",
|
||||
"name": "Reference",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Value",
|
||||
"name": "Value",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Datasheet",
|
||||
"name": "Datasheet",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Footprint",
|
||||
"name": "Footprint",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "${QUANTITY}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "DNP",
|
||||
"name": "${DNP}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "#",
|
||||
"name": "${ITEM_NUMBER}",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Description",
|
||||
"name": "Description",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"filter_string": "",
|
||||
"group_symbols": true,
|
||||
"name": "",
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"operating_point_overlay_i_precision": 3,
|
||||
"operating_point_overlay_i_range": "~A",
|
||||
"operating_point_overlay_v_precision": 3,
|
||||
"operating_point_overlay_v_range": "~V",
|
||||
"overbar_offset_ratio": 1.23,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": false,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 0,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "empty.kicad_wks",
|
||||
"plot_directory": "",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"3048f5e8-34bb-46da-8fa5-8c5aad2586f2",
|
||||
"Root"
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
1
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_dru
Normal file
1
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_dru
Normal file
@ -0,0 +1 @@
|
||||
(version 1)
|
90383
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_pcb
Normal file
90383
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_pcb
Normal file
File diff suppressed because it is too large
Load Diff
83
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_prl
Normal file
83
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_prl
Normal file
@ -0,0 +1,83 @@
|
||||
{
|
||||
"board": {
|
||||
"active_layer": 0,
|
||||
"active_layer_preset": "",
|
||||
"auto_track_width": true,
|
||||
"hidden_netclasses": [],
|
||||
"hidden_nets": [],
|
||||
"high_contrast_mode": 0,
|
||||
"net_color_mode": 1,
|
||||
"opacity": {
|
||||
"images": 0.6,
|
||||
"pads": 1.0,
|
||||
"tracks": 1.0,
|
||||
"vias": 1.0,
|
||||
"zones": 0.6
|
||||
},
|
||||
"ratsnest_display_mode": 0,
|
||||
"selection_filter": {
|
||||
"dimensions": true,
|
||||
"footprints": true,
|
||||
"graphics": true,
|
||||
"keepouts": true,
|
||||
"lockedItems": true,
|
||||
"otherItems": true,
|
||||
"pads": true,
|
||||
"text": true,
|
||||
"tracks": true,
|
||||
"vias": true,
|
||||
"zones": true
|
||||
},
|
||||
"visible_items": [
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
4,
|
||||
5,
|
||||
8,
|
||||
9,
|
||||
10,
|
||||
11,
|
||||
12,
|
||||
13,
|
||||
14,
|
||||
15,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
20,
|
||||
21,
|
||||
22,
|
||||
23,
|
||||
24,
|
||||
25,
|
||||
26,
|
||||
27,
|
||||
28,
|
||||
29,
|
||||
30,
|
||||
32,
|
||||
33,
|
||||
34,
|
||||
35,
|
||||
36
|
||||
],
|
||||
"visible_layers": "0015055_80000001",
|
||||
"zone_display_mode": 0
|
||||
},
|
||||
"git": {
|
||||
"repo_password": "",
|
||||
"repo_type": "",
|
||||
"repo_username": "",
|
||||
"ssh_key": ""
|
||||
},
|
||||
"meta": {
|
||||
"filename": "OSO-SWAT-C1.kicad_prl",
|
||||
"version": 3
|
||||
},
|
||||
"project": {
|
||||
"files": []
|
||||
}
|
||||
}
|
681
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_pro
Normal file
681
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_pro
Normal file
@ -0,0 +1,681 @@
|
||||
{
|
||||
"board": {
|
||||
"3dviewports": [],
|
||||
"design_settings": {
|
||||
"defaults": {
|
||||
"apply_defaults_to_fp_fields": false,
|
||||
"apply_defaults_to_fp_shapes": false,
|
||||
"apply_defaults_to_fp_text": false,
|
||||
"board_outline_line_width": 0.05,
|
||||
"copper_line_width": 0.2,
|
||||
"copper_text_italic": false,
|
||||
"copper_text_size_h": 1.5,
|
||||
"copper_text_size_v": 1.5,
|
||||
"copper_text_thickness": 0.3,
|
||||
"copper_text_upright": false,
|
||||
"courtyard_line_width": 0.05,
|
||||
"dimension_precision": 4,
|
||||
"dimension_units": 3,
|
||||
"dimensions": {
|
||||
"arrow_length": 1270000,
|
||||
"extension_offset": 500000,
|
||||
"keep_text_aligned": true,
|
||||
"suppress_zeroes": false,
|
||||
"text_position": 0,
|
||||
"units_format": 1
|
||||
},
|
||||
"fab_line_width": 0.1,
|
||||
"fab_text_italic": false,
|
||||
"fab_text_size_h": 1.0,
|
||||
"fab_text_size_v": 1.0,
|
||||
"fab_text_thickness": 0.15,
|
||||
"fab_text_upright": false,
|
||||
"other_line_width": 0.1,
|
||||
"other_text_italic": false,
|
||||
"other_text_size_h": 1.0,
|
||||
"other_text_size_v": 1.0,
|
||||
"other_text_thickness": 0.15,
|
||||
"other_text_upright": false,
|
||||
"pads": {
|
||||
"drill": 0.9,
|
||||
"height": 0.9,
|
||||
"width": 0.9
|
||||
},
|
||||
"silk_line_width": 0.12,
|
||||
"silk_text_italic": false,
|
||||
"silk_text_size_h": 1.0,
|
||||
"silk_text_size_v": 1.0,
|
||||
"silk_text_thickness": 0.15,
|
||||
"silk_text_upright": false,
|
||||
"zones": {
|
||||
"45_degree_only": false,
|
||||
"min_clearance": 1e-06
|
||||
}
|
||||
},
|
||||
"diff_pair_dimensions": [
|
||||
{
|
||||
"gap": 0.0,
|
||||
"via_gap": 0.0,
|
||||
"width": 0.0
|
||||
}
|
||||
],
|
||||
"drc_exclusions": [],
|
||||
"meta": {
|
||||
"filename": "board_design_settings.json",
|
||||
"version": 2
|
||||
},
|
||||
"rule_severities": {
|
||||
"annular_width": "error",
|
||||
"clearance": "error",
|
||||
"connection_width": "warning",
|
||||
"copper_edge_clearance": "warning",
|
||||
"copper_sliver": "warning",
|
||||
"courtyards_overlap": "warning",
|
||||
"diff_pair_gap_out_of_range": "error",
|
||||
"diff_pair_uncoupled_length_too_long": "error",
|
||||
"drill_out_of_range": "error",
|
||||
"duplicate_footprints": "warning",
|
||||
"extra_footprint": "warning",
|
||||
"footprint": "error",
|
||||
"footprint_symbol_mismatch": "warning",
|
||||
"footprint_type_mismatch": "error",
|
||||
"hole_clearance": "error",
|
||||
"hole_near_hole": "error",
|
||||
"holes_co_located": "warning",
|
||||
"invalid_outline": "error",
|
||||
"isolated_copper": "warning",
|
||||
"item_on_disabled_layer": "error",
|
||||
"items_not_allowed": "error",
|
||||
"length_out_of_range": "error",
|
||||
"lib_footprint_issues": "warning",
|
||||
"lib_footprint_mismatch": "warning",
|
||||
"malformed_courtyard": "error",
|
||||
"microvia_drill_out_of_range": "error",
|
||||
"missing_courtyard": "ignore",
|
||||
"missing_footprint": "warning",
|
||||
"net_conflict": "warning",
|
||||
"npth_inside_courtyard": "ignore",
|
||||
"padstack": "error",
|
||||
"pth_inside_courtyard": "ignore",
|
||||
"shorting_items": "error",
|
||||
"silk_edge_clearance": "warning",
|
||||
"silk_over_copper": "warning",
|
||||
"silk_overlap": "warning",
|
||||
"skew_out_of_range": "error",
|
||||
"solder_mask_bridge": "warning",
|
||||
"starved_thermal": "warning",
|
||||
"text_height": "warning",
|
||||
"text_thickness": "warning",
|
||||
"through_hole_pad_without_hole": "error",
|
||||
"too_many_vias": "error",
|
||||
"track_dangling": "warning",
|
||||
"track_width": "error",
|
||||
"tracks_crossing": "error",
|
||||
"unconnected_items": "error",
|
||||
"unresolved_variable": "error",
|
||||
"via_dangling": "warning",
|
||||
"zones_intersect": "error"
|
||||
},
|
||||
"rules": {
|
||||
"allow_blind_buried_vias": false,
|
||||
"allow_microvias": false,
|
||||
"max_error": 0.005,
|
||||
"min_clearance": 0.0889,
|
||||
"min_connection": 0.0,
|
||||
"min_copper_edge_clearance": 0.0889,
|
||||
"min_hole_clearance": 0.0889,
|
||||
"min_hole_to_hole": 0.25,
|
||||
"min_microvia_diameter": 0.2,
|
||||
"min_microvia_drill": 0.1,
|
||||
"min_resolved_spokes": 2,
|
||||
"min_silk_clearance": 0.0,
|
||||
"min_text_height": 0.8,
|
||||
"min_text_thickness": 0.08,
|
||||
"min_through_hole_diameter": 0.2,
|
||||
"min_track_width": 0.0889,
|
||||
"min_via_annular_width": 0.125,
|
||||
"min_via_diameter": 0.45,
|
||||
"solder_mask_to_copper_clearance": 0.0,
|
||||
"use_height_for_length_calcs": true
|
||||
},
|
||||
"teardrop_options": [
|
||||
{
|
||||
"td_onpadsmd": true,
|
||||
"td_onroundshapesonly": false,
|
||||
"td_ontrackend": false,
|
||||
"td_onviapad": true
|
||||
}
|
||||
],
|
||||
"teardrop_parameters": [
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_round_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_rect_shape",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
},
|
||||
{
|
||||
"td_allow_use_two_tracks": true,
|
||||
"td_curve_segcount": 0,
|
||||
"td_height_ratio": 1.0,
|
||||
"td_length_ratio": 0.5,
|
||||
"td_maxheight": 2.0,
|
||||
"td_maxlen": 1.0,
|
||||
"td_on_pad_in_zone": false,
|
||||
"td_target_name": "td_track_end",
|
||||
"td_width_to_size_filter_ratio": 0.9
|
||||
}
|
||||
],
|
||||
"track_widths": [
|
||||
0.0,
|
||||
0.0762,
|
||||
0.0889,
|
||||
0.1016,
|
||||
0.127,
|
||||
0.1524,
|
||||
0.1778,
|
||||
0.2032,
|
||||
0.254,
|
||||
0.3048,
|
||||
0.55
|
||||
],
|
||||
"tuning_pattern_settings": {
|
||||
"diff_pair_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 1.0
|
||||
},
|
||||
"diff_pair_skew_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
},
|
||||
"single_track_defaults": {
|
||||
"corner_radius_percentage": 80,
|
||||
"corner_style": 1,
|
||||
"max_amplitude": 1.0,
|
||||
"min_amplitude": 0.2,
|
||||
"single_sided": false,
|
||||
"spacing": 0.6
|
||||
}
|
||||
},
|
||||
"via_dimensions": [
|
||||
{
|
||||
"diameter": 0.0,
|
||||
"drill": 0.0
|
||||
},
|
||||
{
|
||||
"diameter": 0.5588,
|
||||
"drill": 0.3048
|
||||
}
|
||||
],
|
||||
"zones_allow_external_fillets": false,
|
||||
"zones_use_no_outline": true
|
||||
},
|
||||
"ipc2581": {
|
||||
"dist": "",
|
||||
"distpn": "",
|
||||
"internal_id": "",
|
||||
"mfg": "",
|
||||
"mpn": ""
|
||||
},
|
||||
"layer_presets": [],
|
||||
"viewports": []
|
||||
},
|
||||
"boards": [],
|
||||
"cvpcb": {
|
||||
"equivalence_files": []
|
||||
},
|
||||
"erc": {
|
||||
"erc_exclusions": [],
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"pin_map": [
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
0,
|
||||
2,
|
||||
1,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
2,
|
||||
0,
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2,
|
||||
2
|
||||
]
|
||||
],
|
||||
"rule_severities": {
|
||||
"bus_definition_conflict": "error",
|
||||
"bus_entry_needed": "error",
|
||||
"bus_to_bus_conflict": "error",
|
||||
"bus_to_net_conflict": "error",
|
||||
"conflicting_netclasses": "error",
|
||||
"different_unit_footprint": "error",
|
||||
"different_unit_net": "error",
|
||||
"duplicate_reference": "error",
|
||||
"duplicate_sheet_names": "error",
|
||||
"endpoint_off_grid": "warning",
|
||||
"extra_units": "error",
|
||||
"global_label_dangling": "warning",
|
||||
"hier_label_mismatch": "error",
|
||||
"label_dangling": "error",
|
||||
"lib_symbol_issues": "warning",
|
||||
"missing_bidi_pin": "warning",
|
||||
"missing_input_pin": "warning",
|
||||
"missing_power_pin": "error",
|
||||
"missing_unit": "warning",
|
||||
"multiple_net_names": "warning",
|
||||
"net_not_bus_member": "warning",
|
||||
"no_connect_connected": "warning",
|
||||
"no_connect_dangling": "warning",
|
||||
"pin_not_connected": "error",
|
||||
"pin_not_driven": "error",
|
||||
"pin_to_pin": "error",
|
||||
"power_pin_not_driven": "error",
|
||||
"similar_labels": "warning",
|
||||
"simulation_model_issue": "error",
|
||||
"unannotated": "error",
|
||||
"unit_value_mismatch": "error",
|
||||
"unresolved_variable": "error",
|
||||
"wire_dangling": "error"
|
||||
}
|
||||
},
|
||||
"libraries": {
|
||||
"pinned_footprint_libs": [],
|
||||
"pinned_symbol_libs": []
|
||||
},
|
||||
"meta": {
|
||||
"filename": "OSO-SWAT-C1.kicad_pro",
|
||||
"version": 1
|
||||
},
|
||||
"net_settings": {
|
||||
"classes": [
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.0889,
|
||||
"diff_pair_gap": 0.0889,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.0889,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.45,
|
||||
"microvia_drill": 0.2,
|
||||
"name": "Default",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.0889,
|
||||
"via_diameter": 0.45,
|
||||
"via_drill": 0.2,
|
||||
"wire_width": 6
|
||||
},
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.0889,
|
||||
"diff_pair_gap": 0.0889,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.0889,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.45,
|
||||
"microvia_drill": 0.2,
|
||||
"name": "gnd",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2032,
|
||||
"via_diameter": 0.45,
|
||||
"via_drill": 0.2,
|
||||
"wire_width": 6
|
||||
},
|
||||
{
|
||||
"bus_width": 12,
|
||||
"clearance": 0.0889,
|
||||
"diff_pair_gap": 0.0889,
|
||||
"diff_pair_via_gap": 0.25,
|
||||
"diff_pair_width": 0.0889,
|
||||
"line_style": 0,
|
||||
"microvia_diameter": 0.45,
|
||||
"microvia_drill": 0.2,
|
||||
"name": "power",
|
||||
"pcb_color": "rgba(0, 0, 0, 0.000)",
|
||||
"schematic_color": "rgba(0, 0, 0, 0.000)",
|
||||
"track_width": 0.2032,
|
||||
"via_diameter": 0.45,
|
||||
"via_drill": 0.2,
|
||||
"wire_width": 6
|
||||
}
|
||||
],
|
||||
"meta": {
|
||||
"version": 3
|
||||
},
|
||||
"net_colors": null,
|
||||
"netclass_assignments": null,
|
||||
"netclass_patterns": [
|
||||
{
|
||||
"netclass": "gnd",
|
||||
"pattern": "GND"
|
||||
},
|
||||
{
|
||||
"netclass": "power",
|
||||
"pattern": "VCC"
|
||||
}
|
||||
]
|
||||
},
|
||||
"pcbnew": {
|
||||
"last_paths": {
|
||||
"gencad": "",
|
||||
"idf": "",
|
||||
"netlist": "",
|
||||
"plot": "./OSO-SWAT-C1-06",
|
||||
"pos_files": "./temp/",
|
||||
"specctra_dsn": "",
|
||||
"step": "OSO-SWAT-C1.step",
|
||||
"svg": "",
|
||||
"vrml": ""
|
||||
},
|
||||
"page_layout_descr_file": ""
|
||||
},
|
||||
"schematic": {
|
||||
"annotate_start_num": 0,
|
||||
"bom_export_filename": "OSO-SWAT-C1-05-bottom.csv",
|
||||
"bom_fmt_presets": [],
|
||||
"bom_fmt_settings": {
|
||||
"field_delimiter": ",",
|
||||
"keep_line_breaks": false,
|
||||
"keep_tabs": false,
|
||||
"name": "CSV",
|
||||
"ref_delimiter": ",",
|
||||
"ref_range_delimiter": "",
|
||||
"string_delimiter": "\""
|
||||
},
|
||||
"bom_presets": [],
|
||||
"bom_settings": {
|
||||
"exclude_dnp": false,
|
||||
"fields_ordered": [
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Reference",
|
||||
"name": "Reference",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Value",
|
||||
"name": "Value",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Datasheet",
|
||||
"name": "Datasheet",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "Footprint",
|
||||
"name": "Footprint",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Qty",
|
||||
"name": "${QUANTITY}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": true,
|
||||
"label": "DNP",
|
||||
"name": "${DNP}",
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "#",
|
||||
"name": "${ITEM_NUMBER}",
|
||||
"show": false
|
||||
},
|
||||
{
|
||||
"group_by": false,
|
||||
"label": "Description",
|
||||
"name": "Description",
|
||||
"show": false
|
||||
}
|
||||
],
|
||||
"filter_string": "",
|
||||
"group_symbols": true,
|
||||
"name": "",
|
||||
"sort_asc": true,
|
||||
"sort_field": "Reference"
|
||||
},
|
||||
"connection_grid_size": 50.0,
|
||||
"drawing": {
|
||||
"dashed_lines_dash_length_ratio": 12.0,
|
||||
"dashed_lines_gap_length_ratio": 3.0,
|
||||
"default_line_thickness": 6.0,
|
||||
"default_text_size": 50.0,
|
||||
"field_names": [],
|
||||
"intersheets_ref_own_page": false,
|
||||
"intersheets_ref_prefix": "",
|
||||
"intersheets_ref_short": false,
|
||||
"intersheets_ref_show": false,
|
||||
"intersheets_ref_suffix": "",
|
||||
"junction_size_choice": 3,
|
||||
"label_size_ratio": 0.375,
|
||||
"operating_point_overlay_i_precision": 3,
|
||||
"operating_point_overlay_i_range": "~A",
|
||||
"operating_point_overlay_v_precision": 3,
|
||||
"operating_point_overlay_v_range": "~V",
|
||||
"overbar_offset_ratio": 1.23,
|
||||
"pin_symbol_size": 25.0,
|
||||
"text_offset_ratio": 0.15
|
||||
},
|
||||
"legacy_lib_dir": "",
|
||||
"legacy_lib_list": [],
|
||||
"meta": {
|
||||
"version": 1
|
||||
},
|
||||
"net_format_name": "",
|
||||
"ngspice": {
|
||||
"fix_include_paths": true,
|
||||
"fix_passive_vals": false,
|
||||
"meta": {
|
||||
"version": 0
|
||||
},
|
||||
"model_mode": 0,
|
||||
"workbook_filename": ""
|
||||
},
|
||||
"page_layout_descr_file": "empty.kicad_wks",
|
||||
"plot_directory": "",
|
||||
"spice_adjust_passive_values": false,
|
||||
"spice_current_sheet_as_root": false,
|
||||
"spice_external_command": "spice \"%I\"",
|
||||
"spice_model_current_sheet_as_root": true,
|
||||
"spice_save_all_currents": false,
|
||||
"spice_save_all_dissipations": false,
|
||||
"spice_save_all_voltages": false,
|
||||
"subpart_first_id": 65,
|
||||
"subpart_id_separator": 0
|
||||
},
|
||||
"sheets": [
|
||||
[
|
||||
"3048f5e8-34bb-46da-8fa5-8c5aad2586f2",
|
||||
"Root"
|
||||
]
|
||||
],
|
||||
"text_variables": {}
|
||||
}
|
15111
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_sch
Normal file
15111
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.kicad_sch
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
154
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.pretty/ELT3KN.kicad_mod
Normal file
154
PCB/Main Boards/OSO-SWAT-C1/OSO-SWAT-C1.pretty/ELT3KN.kicad_mod
Normal file
@ -0,0 +1,154 @@
|
||||
(footprint "ELT3KN"
|
||||
(version 20240108)
|
||||
(generator "pcbnew")
|
||||
(generator_version "8.0")
|
||||
(layer "F.Cu")
|
||||
(property "Reference" "REF**"
|
||||
(at 0 -2.5 0)
|
||||
(unlocked yes)
|
||||
(layer "F.SilkS")
|
||||
(uuid "a169e63e-29cc-4564-a621-b8211c147892")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.2)
|
||||
(bold yes)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Value" "ELT3KN"
|
||||
(at 0 2.5 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(uuid "12f117ff-fc54-4392-9702-20053568a437")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at 0 0 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "4696eff2-7885-4247-8d7f-ea328aeb61b3")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" ""
|
||||
(at 0 0 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "38e32ed5-5bed-49cc-a302-cc80b63f7eca")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" ""
|
||||
(at 0 0 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "bbe09b54-7873-4c59-90a5-708f27e5af76")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(attr smd)
|
||||
(fp_arc
|
||||
(start -1.495202 -0.697761)
|
||||
(mid -0.886339 -1.391726)
|
||||
(end 0 -1.65)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type default)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "2b5cd3f8-b18c-4557-94e3-1779ca1608f1")
|
||||
)
|
||||
(fp_arc
|
||||
(start 0 -1.65)
|
||||
(mid 0.886339 -1.391727)
|
||||
(end 1.495202 -0.697761)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type default)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "d473595f-e35a-4857-8449-1d9f3feacdc9")
|
||||
)
|
||||
(fp_arc
|
||||
(start 0 1.65)
|
||||
(mid -0.886339 1.391727)
|
||||
(end -1.495202 0.697761)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type default)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "d37347f0-9221-4e4b-a029-a04f185819ec")
|
||||
)
|
||||
(fp_arc
|
||||
(start 1.495202 0.697761)
|
||||
(mid 0.886339 1.391726)
|
||||
(end 0 1.65)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type default)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "f12bf60f-5b3d-45b5-82f7-79448488ae21")
|
||||
)
|
||||
(fp_circle
|
||||
(center 0 0)
|
||||
(end 1.65 0)
|
||||
(stroke
|
||||
(width 0.1)
|
||||
(type default)
|
||||
)
|
||||
(fill none)
|
||||
(layer "F.Fab")
|
||||
(uuid "3ab1094b-f4c1-4436-87a3-fa43bddd0a8d")
|
||||
)
|
||||
(fp_text user "${REFERENCE}"
|
||||
(at 0 0 0)
|
||||
(unlocked yes)
|
||||
(layer "F.Fab")
|
||||
(uuid "0739cf1b-8f40-4d32-91d0-496ba0ec98b8")
|
||||
(effects
|
||||
(font
|
||||
(size 1 1)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(pad "1" smd roundrect
|
||||
(at -2.15 0)
|
||||
(size 1.4 1.05)
|
||||
(layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(roundrect_rratio 0.25)
|
||||
(thermal_bridge_angle 45)
|
||||
(uuid "e742aada-aafd-47f3-8447-3fbf9c4a7579")
|
||||
)
|
||||
(pad "2" smd roundrect
|
||||
(at 2.15 0)
|
||||
(size 1.4 1.05)
|
||||
(layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(roundrect_rratio 0.25)
|
||||
(thermal_bridge_angle 45)
|
||||
(uuid "fa457dd1-8427-41f4-83ec-ab02d543d005")
|
||||
)
|
||||
)
|
@ -0,0 +1,47 @@
|
||||
(footprint "FH19C9S05SH10" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(descr "<b>FH19C-9S-0.5SH(10)-1</b><br>\n")
|
||||
(fp_text reference "REF**" (at 0 -1.425) (layer "F.SilkS")
|
||||
(effects (font (size 1.1684 1.1684) (thickness 0.1016)))
|
||||
(tstamp f001c7f4-3bac-4901-bfec-55e6729b7a2d)
|
||||
)
|
||||
(fp_text value ">VALUE" (at 0 -1.425) (layer "F.Fab")
|
||||
(effects (font (size 1.1684 1.1684) (thickness 0.1016)))
|
||||
(tstamp 561aeca9-49f1-4f98-93e2-6788ec46bd30)
|
||||
)
|
||||
(fp_line (start -2.75 -2.25) (end -3.25 -2.25) (layer "F.SilkS") (width 0.1) (tstamp 1eac27e8-d706-4fd3-9d7e-f44c3bceecb7))
|
||||
(fp_line (start -3.25 0.75) (end 3.25 0.75) (layer "F.SilkS") (width 0.1) (tstamp 2954b329-e121-4506-a75a-9fd0ad6fb160))
|
||||
(fp_line (start -3.25 -2.25) (end -3.25 -0.75) (layer "F.SilkS") (width 0.1) (tstamp 707c871c-221c-430b-8a6b-9066bbe6a8b7))
|
||||
(fp_line (start 3.25 -2.25) (end 3.25 -0.75) (layer "F.SilkS") (width 0.1) (tstamp c93c51a4-9fbb-472e-8b27-c730f1646c88))
|
||||
(fp_line (start 2.75 -2.25) (end 3.25 -2.25) (layer "F.SilkS") (width 0.1) (tstamp f62c7b3a-070f-4127-95d5-3042f710b35c))
|
||||
(fp_arc (start -2.457 -2.572) (mid -2.407 -2.622) (end -2.357 -2.572) (layer "F.SilkS") (width 0.2) (tstamp 99032ce3-83f4-4d78-bc12-cfc846be0db6))
|
||||
(fp_arc (start -2.357 -2.572) (mid -2.407 -2.522) (end -2.457 -2.572) (layer "F.SilkS") (width 0.2) (tstamp cc85bc5e-d12e-4c30-b330-62e6d8cd831e))
|
||||
(fp_arc (start -2.457 -2.572) (mid -2.407 -2.622) (end -2.357 -2.572) (layer "F.SilkS") (width 0.2) (tstamp e306135f-93e3-4c31-83e0-8c60a6608eec))
|
||||
(fp_line (start 3.25 0.75) (end -3.25 0.75) (layer "F.Fab") (width 0.2) (tstamp 4524f199-9890-4fbd-90ec-2bd6babdbf89))
|
||||
(fp_line (start 3.25 -2.25) (end 3.25 0.75) (layer "F.Fab") (width 0.2) (tstamp 855f1cc0-31ef-4190-b476-18e3b5158686))
|
||||
(fp_line (start -3.25 0.75) (end -3.25 -2.25) (layer "F.Fab") (width 0.2) (tstamp a7aeadd1-064c-4dec-839a-d3cb8b0a8559))
|
||||
(fp_line (start -3.25 -2.25) (end 3.25 -2.25) (layer "F.Fab") (width 0.2) (tstamp b29496a7-f051-4b0c-a792-56f5b1d5ae06))
|
||||
(pad "1" smd rect (at -2 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp acda55bd-5be5-40b1-a960-d198db4ec672))
|
||||
(pad "2" smd rect (at -1.5 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 45b21120-703c-4698-9c56-6564d6e1bf81))
|
||||
(pad "3" smd rect (at -1 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 8b754c17-ed29-4271-a8ee-1331ac5995ef))
|
||||
(pad "4" smd rect (at -0.5 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 9ccadf67-4eb3-4873-b5dd-5cc11b45344d))
|
||||
(pad "5" smd rect (at 0 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp bda542d0-ecb7-417f-8c5a-7bba95d4eba5))
|
||||
(pad "6" smd rect (at 0.5 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 8e3054c6-288a-41ce-abc0-f8e853b26354))
|
||||
(pad "7" smd rect (at 1 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 1f1c1390-fe89-4a71-a866-c4e1f01372f9))
|
||||
(pad "8" smd rect (at 1.5 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 83315760-4e59-4aea-8656-92a90fbb73b7))
|
||||
(pad "9" smd rect (at 2 -2.5 90) (size 0.8 0.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp f1470e81-8bfa-4c7b-9a4f-907119981553))
|
||||
(pad "MP1" smd rect (at -3 0 90) (size 0.8 0.4) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 5d56d96c-0e59-4d80-b122-61ae0456f87e))
|
||||
(pad "MP2" smd rect (at 3 0 90) (size 0.8 0.4) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 65badac9-bbc1-4323-b96e-20b366a5c013))
|
||||
)
|
@ -0,0 +1,22 @@
|
||||
(footprint "FIDUCIAL_1MM" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at 0 0) (layer "F.SilkS")
|
||||
(effects (font (size 1.27 1.27) (thickness 0.15)))
|
||||
(tstamp 084b231a-a841-4989-ba78-c80f52a1d530)
|
||||
)
|
||||
(fp_text value "" (at 0 0) (layer "F.Fab")
|
||||
(effects (font (size 1.27 1.27) (thickness 0.15)))
|
||||
(tstamp 5023af4a-f69e-458d-abff-77e97f0c49aa)
|
||||
)
|
||||
(fp_arc (start -0.75 0) (mid -0.53033 -0.53033) (end 0 -0.75) (layer "F.Mask") (width 0.5) (tstamp 243424d9-367c-4c55-9ce2-5c7f6b71c486))
|
||||
(fp_arc (start 0 0.75) (mid -0.53033 0.53033) (end -0.75 0) (layer "F.Mask") (width 0.5) (tstamp 38a261de-e7ad-4359-9a4e-e8325d947b3c))
|
||||
(fp_arc (start 0.75 0) (mid 0.53033 0.53033) (end 0 0.75) (layer "F.Mask") (width 0.5) (tstamp 3e5e4d91-af7b-467f-93be-7757d59f4acd))
|
||||
(fp_arc (start 0 -0.75) (mid 0.53033 -0.53033) (end 0.75 0) (layer "F.Mask") (width 0.5) (tstamp cba0161e-94ca-4df5-83f4-b38d910a40d8))
|
||||
(fp_arc (start 0 -0.75) (mid 0.53033 -0.53033) (end 0.75 0) (layer "F.CrtYd") (width 0.5) (tstamp 24375f2d-9f3c-47f3-bf1b-d9abc9459487))
|
||||
(fp_arc (start 0.75 0) (mid 0.53033 0.53033) (end 0 0.75) (layer "F.CrtYd") (width 0.5) (tstamp 61d35d35-c7e3-45c7-a1f6-4c560b28917a))
|
||||
(fp_arc (start 0 0.75) (mid -0.53033 0.53033) (end -0.75 0) (layer "F.CrtYd") (width 0.5) (tstamp b245f192-3aeb-4a3c-8f5f-5b2ac372cfb6))
|
||||
(fp_arc (start -0.75 0) (mid -0.53033 -0.53033) (end 0 -0.75) (layer "F.CrtYd") (width 0.5) (tstamp f012c0d9-2bab-4b5b-8327-ed4e32f900bb))
|
||||
(pad "1" smd roundrect (at 0 0) (size 1 1) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.5)
|
||||
(solder_mask_margin 0.0635) (tstamp ea46b6d0-c0be-44d4-aa82-47c56ffdb259))
|
||||
)
|
@ -0,0 +1,26 @@
|
||||
(footprint "LED_QBLP655" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at 0.011609 -1.462631) (layer "F.SilkS")
|
||||
(effects (font (size 0.682286 0.682286) (thickness 0.14977)))
|
||||
(tstamp 441c2b28-158a-4d68-a991-31f4c6a03554)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -0.054931 1.580818) (layer "F.Fab")
|
||||
(effects (font (size 0.677435 0.677435) (thickness 0.148705)))
|
||||
(tstamp 2f361345-03db-4c21-a99d-0b9cfab62aee)
|
||||
)
|
||||
(fp_circle (center -3.1 -0.5) (end -3 -0.5) (layer "F.SilkS") (width 0.2) (fill none) (tstamp 0ba68dd4-e618-4da0-b7e7-599817b38c08))
|
||||
(fp_line (start -1.6 -0.6) (end 1.6 -0.6) (layer "F.Fab") (width 0.127) (tstamp 3629e8ab-0a05-463c-9cb0-81d2e314e044))
|
||||
(fp_line (start -1.6 0.6) (end -1.6 -0.6) (layer "F.Fab") (width 0.127) (tstamp 379a3f23-154c-4da8-9d91-714d85fa6b82))
|
||||
(fp_line (start 1.6 -0.6) (end 1.6 0.6) (layer "F.Fab") (width 0.127) (tstamp 78db06e4-b90e-45d6-90ee-f31a25c04c7d))
|
||||
(fp_line (start 1.6 0.6) (end -1.6 0.6) (layer "F.Fab") (width 0.127) (tstamp de669889-6aee-41d8-9167-24b5b7cd2f7a))
|
||||
(fp_circle (center -3.1 -0.5) (end -3 -0.5) (layer "F.Fab") (width 0.2) (fill none) (tstamp a3f31f15-16ea-4248-8fe2-4f1f6cb6fef0))
|
||||
(pad "1" smd rect (at -1.5 -0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp c0b010da-7837-47db-be16-93e46d77ee03))
|
||||
(pad "2" smd rect (at 1.5 -0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 0491e5ac-92c6-4da4-a40f-13768f4f5f7c))
|
||||
(pad "3" smd rect (at -1.5 0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp d96a3b29-ffbb-4252-a695-34388cf2cce8))
|
||||
(pad "4" smd rect (at 1.5 0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp a7b3dfda-cc06-4a25-8ceb-15247a6b386b))
|
||||
)
|
@ -0,0 +1,24 @@
|
||||
(footprint "LED_QBLP655_RGB" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at 0.011609 -1.462631) (layer "F.SilkS")
|
||||
(effects (font (size 0.682286 0.682286) (thickness 0.14977)))
|
||||
(tstamp 441c2b28-158a-4d68-a991-31f4c6a03554)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -0.054931 1.580818) (layer "F.Fab")
|
||||
(effects (font (size 0.677435 0.677435) (thickness 0.148705)))
|
||||
(tstamp 2f361345-03db-4c21-a99d-0b9cfab62aee)
|
||||
)
|
||||
(fp_line (start -1.6 -0.6) (end 1.6 -0.6) (layer "F.Fab") (width 0.127) (tstamp 3629e8ab-0a05-463c-9cb0-81d2e314e044))
|
||||
(fp_line (start -1.6 0.6) (end -1.6 -0.6) (layer "F.Fab") (width 0.127) (tstamp 379a3f23-154c-4da8-9d91-714d85fa6b82))
|
||||
(fp_line (start 1.6 -0.6) (end 1.6 0.6) (layer "F.Fab") (width 0.127) (tstamp 78db06e4-b90e-45d6-90ee-f31a25c04c7d))
|
||||
(fp_line (start 1.6 0.6) (end -1.6 0.6) (layer "F.Fab") (width 0.127) (tstamp de669889-6aee-41d8-9167-24b5b7cd2f7a))
|
||||
(pad "1" smd rect (at 1.5 -0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 0491e5ac-92c6-4da4-a40f-13768f4f5f7c))
|
||||
(pad "2" smd rect (at -1.5 -0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp c0b010da-7837-47db-be16-93e46d77ee03))
|
||||
(pad "3" smd rect (at -1.5 0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp d96a3b29-ffbb-4252-a695-34388cf2cce8))
|
||||
(pad "4" smd rect (at 1.5 0.4) (size 1.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp a7b3dfda-cc06-4a25-8ceb-15247a6b386b))
|
||||
)
|
@ -0,0 +1,15 @@
|
||||
(footprint "MICROBUILDER_TESTPOINT_ROUND_1.5MM" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at 1.143 0.127) (layer "F.SilkS")
|
||||
(effects (font (size 0.666496 0.666496) (thickness 0.146304)) (justify left bottom))
|
||||
(tstamp 3249263f-d424-465a-883e-c9fbfca1c498)
|
||||
)
|
||||
(fp_text value ">VALUE" (at 1.143 0.635) (layer "F.Fab")
|
||||
(effects (font (size 0.36576 0.36576) (thickness 0.04064)) (justify left bottom))
|
||||
(tstamp ffe18277-47dd-48a9-ae75-8daae098595b)
|
||||
)
|
||||
(fp_circle (center 0 0) (end 1 0) (layer "F.SilkS") (width 0.2032) (fill none) (tstamp 10aeb60f-0687-4840-aeb5-a5e914b89db2))
|
||||
(pad "P$1" smd roundrect (at 0 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.5)
|
||||
(solder_mask_margin 0.0635) (tstamp 278b13e7-2a43-4fc5-a675-ea6ed2efdd4b))
|
||||
)
|
@ -0,0 +1,38 @@
|
||||
(footprint "MICROBUILDER__0805MP" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(descr "<b>0805 MicroPitch</b>")
|
||||
(fp_text reference "REF**" (at -1.5875 -0.9525) (layer "F.SilkS")
|
||||
(effects (font (size 0.666496 0.666496) (thickness 0.146304)) (justify left bottom))
|
||||
(tstamp 6d480cb3-ccbc-4f91-b215-36d9b6b90e39)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -1.5875 1.27) (layer "F.Fab")
|
||||
(effects (font (size 0.36576 0.36576) (thickness 0.04064)) (justify left bottom))
|
||||
(tstamp 6bb67786-fe79-4530-a8f0-ca53290823df)
|
||||
)
|
||||
(fp_poly (pts
|
||||
(xy -0.1999 0.5001)
|
||||
(xy 0.1999 0.5001)
|
||||
(xy 0.1999 -0.5001)
|
||||
(xy -0.1999 -0.5001)
|
||||
) (layer "F.Adhes") (width 0) (fill solid) (tstamp 9e351c4d-f895-49c5-ba3f-cecde3dc6e44))
|
||||
(fp_line (start 0 -0.508) (end 0 0.508) (layer "F.SilkS") (width 0.2032) (tstamp 629c7bfb-b888-4932-aba0-6916a21e7f67))
|
||||
(fp_line (start -0.51 0.535) (end 0.51 0.535) (layer "F.Fab") (width 0.1016) (tstamp 22396a4f-3f2f-4a10-9672-ef964a1e15ec))
|
||||
(fp_line (start -0.51 -0.535) (end 0.51 -0.535) (layer "F.Fab") (width 0.1016) (tstamp 90cacfdf-b07f-4151-ac89-23042124f640))
|
||||
(fp_poly (pts
|
||||
(xy 0.4064 0.65)
|
||||
(xy 1 0.65)
|
||||
(xy 1 -0.65)
|
||||
(xy 0.4064 -0.65)
|
||||
) (layer "F.Fab") (width 0) (fill solid) (tstamp 0138f6cb-7190-4a12-af47-1e018fd27b3c))
|
||||
(fp_poly (pts
|
||||
(xy -1 0.65)
|
||||
(xy -0.4168 0.65)
|
||||
(xy -0.4168 -0.65)
|
||||
(xy -1 -0.65)
|
||||
) (layer "F.Fab") (width 0) (fill solid) (tstamp 637ecbcd-a78f-4c8a-8dcf-472bde2de83b))
|
||||
(pad "1" smd rect (at -1.016 0) (size 1.2 1.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp bd23358d-4a17-4f52-b69d-122e91d97c44))
|
||||
(pad "2" smd rect (at 1.016 0) (size 1.2 1.3) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 165d5fb4-7aca-4db2-a5bd-306d43842183))
|
||||
)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,274 @@
|
||||
(footprint "QFN64_9X9MC_MCH" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at 0 -5.715) (layer "F.SilkS")
|
||||
(effects (font (size 0.499872 0.499872) (thickness 0.109728)))
|
||||
(tstamp 3e871d9c-2a1f-438a-ba83-60e5f8d0fa51)
|
||||
)
|
||||
(fp_text value ">VALUE" (at 0 5.715) (layer "F.Fab")
|
||||
(effects (font (size 0.499872 0.499872) (thickness 0.109728)))
|
||||
(tstamp f2dcc10c-546f-4bd9-be1f-368ae783a117)
|
||||
)
|
||||
(fp_poly (pts
|
||||
(xy 2.1606 0.662)
|
||||
(xy 0.8366 0.662)
|
||||
(xy 0.8366 -0.662)
|
||||
(xy 2.1606 -0.662)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp 2ec0ad3d-3957-4524-a3b2-3e97e3345ecf))
|
||||
(fp_poly (pts
|
||||
(xy 2.1606 -0.8366)
|
||||
(xy 0.8366 -0.8366)
|
||||
(xy 0.8366 -2.1606)
|
||||
(xy 2.1606 -2.1606)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp 42a0d4d0-fc9b-4730-8110-13a84ab3bcb0))
|
||||
(fp_poly (pts
|
||||
(xy 0.662 0.662)
|
||||
(xy -0.662 0.662)
|
||||
(xy -0.662 -0.662)
|
||||
(xy 0.662 -0.662)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp 4fbb659c-e71a-4c9b-9e8a-6da964a65cd4))
|
||||
(fp_poly (pts
|
||||
(xy 2.1606 2.1606)
|
||||
(xy 0.8366 2.1606)
|
||||
(xy 0.8366 0.8366)
|
||||
(xy 2.1606 0.8366)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp 655728ed-daf4-477f-8a3b-b5624d1a73df))
|
||||
(fp_poly (pts
|
||||
(xy -0.8366 2.1606)
|
||||
(xy -2.1606 2.1606)
|
||||
(xy -2.1606 0.8366)
|
||||
(xy -0.8366 0.8366)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp 6566a81c-4902-448f-a6df-8bc32a765ffa))
|
||||
(fp_poly (pts
|
||||
(xy -0.8366 -0.8366)
|
||||
(xy -2.1606 -0.8366)
|
||||
(xy -2.1606 -2.1606)
|
||||
(xy -0.8366 -2.1606)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp 99ce666e-158b-4f82-b57f-184f0eedda5c))
|
||||
(fp_poly (pts
|
||||
(xy 0.662 -0.8366)
|
||||
(xy -0.662 -0.8366)
|
||||
(xy -0.662 -2.1606)
|
||||
(xy 0.662 -2.1606)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp ddf6c3a2-a910-45ea-844b-a8db2b458e91))
|
||||
(fp_poly (pts
|
||||
(xy -0.8366 0.662)
|
||||
(xy -2.1606 0.662)
|
||||
(xy -2.1606 -0.662)
|
||||
(xy -0.8366 -0.662)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp e3f7e99a-4f59-4e18-a5cb-6900c4b08cae))
|
||||
(fp_poly (pts
|
||||
(xy 0.662 2.1606)
|
||||
(xy -0.662 2.1606)
|
||||
(xy -0.662 0.8366)
|
||||
(xy 0.662 0.8366)
|
||||
) (layer "F.Paste") (width 0) (fill solid) (tstamp f934416f-45a1-43f5-b5e1-fba1dddf1aa4))
|
||||
(fp_line (start 4.2164 4.6228) (end 4.6228 4.6228) (layer "F.SilkS") (width 0.1524) (tstamp 2015e2d6-2795-4247-a207-acb4cf8886e6))
|
||||
(fp_line (start -4.2164 -4.6228) (end -4.6228 -4.6228) (layer "F.SilkS") (width 0.1524) (tstamp 2252c90a-7ebf-4d2d-a791-89982b21117b))
|
||||
(fp_line (start 4.6228 -4.6228) (end 4.2164 -4.6228) (layer "F.SilkS") (width 0.1524) (tstamp 2c7437bb-66d1-4b20-ab25-e4022916701f))
|
||||
(fp_line (start -4.6228 4.6228) (end -4.2164 4.6228) (layer "F.SilkS") (width 0.1524) (tstamp 32c6b15e-f755-475e-b73e-6c7fffdfa53a))
|
||||
(fp_line (start -4.6228 -4.6228) (end -4.6228 -4.2164) (layer "F.SilkS") (width 0.1524) (tstamp 450f1cc5-825a-4891-8a52-c72891a373f0))
|
||||
(fp_line (start 4.6228 4.6228) (end 4.6228 4.2164) (layer "F.SilkS") (width 0.1524) (tstamp 82e659cf-ebcc-4fcd-a243-d4894e4c531e))
|
||||
(fp_line (start 4.6228 -4.2164) (end 4.6228 -4.6228) (layer "F.SilkS") (width 0.1524) (tstamp 8caa9a3a-8461-464c-9a5d-58f28cc73fdb))
|
||||
(fp_line (start -4.6228 4.2164) (end -4.6228 4.6228) (layer "F.SilkS") (width 0.1524) (tstamp 9d03b0af-f67a-4b75-88d5-3fdc2fb53147))
|
||||
(fp_circle (center -5.207 -5.207) (end -5.08 -5.207) (layer "F.SilkS") (width 0.254) (fill none) (tstamp d8471eec-d281-4956-8871-df001c4b9d0e))
|
||||
(fp_line (start 4.4958 -2.5908) (end 4.4958 -2.8956) (layer "F.Fab") (width 0.1524) (tstamp 049458dd-1cf1-4608-bc61-728d12d853ec))
|
||||
(fp_line (start -4.4958 -3.9116) (end -4.4958 -3.6068) (layer "F.Fab") (width 0.1524) (tstamp 05d31c0e-dc59-4cfd-8b11-9750f532f89d))
|
||||
(fp_line (start 4.4958 -0.1016) (end 4.4958 -0.4064) (layer "F.Fab") (width 0.1524) (tstamp 0c83150d-4515-4bc6-947c-a18bb0f583b5))
|
||||
(fp_line (start -3.9116 4.4958) (end -3.6068 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 10420e88-4a28-4643-b21a-9465d0057a73))
|
||||
(fp_line (start 4.4958 0.4064) (end 4.4958 0.1016) (layer "F.Fab") (width 0.1524) (tstamp 10e57a60-62de-407e-b340-5e48d8af51a1))
|
||||
(fp_line (start -4.4958 -2.8956) (end -4.4958 -2.5908) (layer "F.Fab") (width 0.1524) (tstamp 15822844-ae2b-47a9-8d24-dd3b08c9541d))
|
||||
(fp_line (start 4.4958 4.4958) (end 4.4958 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 189f4344-d732-4381-8d0f-4a31c3fa9319))
|
||||
(fp_line (start 4.4958 -3.0988) (end 4.4958 -3.4036) (layer "F.Fab") (width 0.1524) (tstamp 1da5d536-ffc3-40be-9afa-f932c35159bf))
|
||||
(fp_line (start -0.6096 -4.4958) (end -0.9144 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 1e512696-3bdf-43ca-8ca3-64344bcd8de6))
|
||||
(fp_line (start -4.4958 -3.4036) (end -4.4958 -3.0988) (layer "F.Fab") (width 0.1524) (tstamp 1efbd3c4-f6bc-449a-85e1-e54dc088704f))
|
||||
(fp_line (start -1.6002 -4.4958) (end -1.905 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 1fd0b84b-3048-4a24-b2ab-7960a733598e))
|
||||
(fp_line (start 4.4958 1.397) (end 4.4958 1.0922) (layer "F.Fab") (width 0.1524) (tstamp 256bd16a-a961-4e7c-bc57-c47218be0e9b))
|
||||
(fp_line (start 0.1016 4.4958) (end 0.4064 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 2610c8d8-02ed-46ba-b8ce-b15585c89028))
|
||||
(fp_line (start -0.1016 -4.4958) (end -0.4064 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 2b9a3dd0-e1a1-405a-ac7d-c3e3d878560b))
|
||||
(fp_line (start -4.4958 0.6096) (end -4.4958 0.9144) (layer "F.Fab") (width 0.1524) (tstamp 3132d241-d7f6-4a55-9503-29f1062b517f))
|
||||
(fp_line (start 0.6096 4.4958) (end 0.9144 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 31daf2d4-3957-4ce7-98d3-a043649dd97e))
|
||||
(fp_line (start -4.4958 3.0988) (end -4.4958 3.4036) (layer "F.Fab") (width 0.1524) (tstamp 337e4bb2-4de6-409d-8061-54d04950842d))
|
||||
(fp_line (start 4.4958 -4.4958) (end -4.4958 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 4115dd93-f2eb-4a67-8dbd-532f41b7a69f))
|
||||
(fp_line (start -4.4958 -0.9144) (end -4.4958 -0.6096) (layer "F.Fab") (width 0.1524) (tstamp 453e6bba-48de-4666-a7eb-66bef0e2b02c))
|
||||
(fp_line (start 3.9116 -4.4958) (end 3.6068 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 4cda505e-c23d-4504-823e-c4f0c3948a9d))
|
||||
(fp_line (start 4.4958 -1.0922) (end 4.4958 -1.397) (layer "F.Fab") (width 0.1524) (tstamp 503e0041-3118-4b51-83f1-b9c14f77f4b1))
|
||||
(fp_line (start -4.4958 -3.2258) (end -3.2258 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 54b28547-cb8b-489a-a9df-6ad15177b2e9))
|
||||
(fp_line (start -3.0988 -4.4958) (end -3.4036 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 5918fd35-f23c-42ff-9fba-9c5a9ac207d3))
|
||||
(fp_line (start 4.4958 3.4036) (end 4.4958 3.0988) (layer "F.Fab") (width 0.1524) (tstamp 5f822173-84ee-42a7-a838-54e1cfc17adf))
|
||||
(fp_line (start 3.6068 4.4958) (end 3.9116 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 632e8422-a140-4238-81b2-8829c7485b2e))
|
||||
(fp_line (start -4.4958 -2.413) (end -4.4958 -2.1082) (layer "F.Fab") (width 0.1524) (tstamp 67448bdd-3f5c-4a5e-8105-da8836876044))
|
||||
(fp_line (start 2.1082 4.4958) (end 2.413 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 69ab593b-1948-43ac-9d69-727c88e9b459))
|
||||
(fp_line (start -2.8956 4.4958) (end -2.5908 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 6dc5284f-c6ff-453d-b163-9f63ed7892ad))
|
||||
(fp_line (start -1.905 4.4958) (end -1.6002 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 6df1e081-1245-47a6-86a6-0c79f1f9db56))
|
||||
(fp_line (start 1.6002 4.4958) (end 1.905 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 709494b8-7fc2-496a-8451-57d7441e8505))
|
||||
(fp_line (start -4.4958 3.6068) (end -4.4958 3.9116) (layer "F.Fab") (width 0.1524) (tstamp 7212588c-17f7-4956-b77b-065540b4ee49))
|
||||
(fp_line (start 2.8956 -4.4958) (end 2.5908 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 7ce7324c-91ea-47c6-b7c2-bd1b2f2a14c2))
|
||||
(fp_line (start -3.4036 4.4958) (end -3.0988 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 7fb70e9b-db47-465c-b7f5-3f144c3fe511))
|
||||
(fp_line (start 4.4958 -2.1082) (end 4.4958 -2.413) (layer "F.Fab") (width 0.1524) (tstamp 832b785c-4536-49cf-b6de-cedea7d015a6))
|
||||
(fp_line (start 2.5908 4.4958) (end 2.8956 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 838b54da-8d76-4af0-a533-f421e7be02c2))
|
||||
(fp_line (start -4.4958 2.5908) (end -4.4958 2.8956) (layer "F.Fab") (width 0.1524) (tstamp 8c3c449f-a035-419f-9950-338baab558f6))
|
||||
(fp_line (start 4.4958 -1.6002) (end 4.4958 -1.905) (layer "F.Fab") (width 0.1524) (tstamp 8e588935-ced6-458a-a187-91e74c238ac8))
|
||||
(fp_line (start -1.397 4.4958) (end -1.0922 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 8fe96cfe-a951-426f-80b8-9a4ee6265385))
|
||||
(fp_line (start -4.4958 1.0922) (end -4.4958 1.397) (layer "F.Fab") (width 0.1524) (tstamp 8ff9eeba-c353-40da-b499-b20afa11f353))
|
||||
(fp_line (start -4.4958 -4.4958) (end -4.4958 4.4958) (layer "F.Fab") (width 0.1524) (tstamp 93722526-b9c8-4550-8cdd-369ecb315477))
|
||||
(fp_line (start -1.0922 -4.4958) (end -1.397 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 9a7cda4c-e257-4759-beca-0a008c33f019))
|
||||
(fp_line (start 0.9144 -4.4958) (end 0.6096 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp 9c8602d4-958b-412c-8bb3-0d75d4a4147b))
|
||||
(fp_line (start 4.4958 2.8956) (end 4.4958 2.5908) (layer "F.Fab") (width 0.1524) (tstamp ab68518b-68f5-4fed-903c-3d10b7662e9c))
|
||||
(fp_line (start -4.4958 -0.4064) (end -4.4958 -0.1016) (layer "F.Fab") (width 0.1524) (tstamp ae845f43-7bd0-4d9b-b6ce-ea24c3f78b67))
|
||||
(fp_line (start 4.4958 2.413) (end 4.4958 2.1082) (layer "F.Fab") (width 0.1524) (tstamp ae9df4c2-28e5-48f0-aff2-79a0c1a8a15a))
|
||||
(fp_line (start -0.4064 4.4958) (end -0.1016 4.4958) (layer "F.Fab") (width 0.1524) (tstamp b27f2059-e221-491a-8338-8399fdb6602a))
|
||||
(fp_line (start 1.905 -4.4958) (end 1.6002 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp b30b8721-3fe1-41c3-8198-1a4ccb7ceb74))
|
||||
(fp_line (start -4.4958 4.4958) (end 4.4958 4.4958) (layer "F.Fab") (width 0.1524) (tstamp b476f917-8b6e-4132-b869-771909a051c6))
|
||||
(fp_line (start 1.397 -4.4958) (end 1.0922 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp b5382627-0c47-465b-972a-a305e2e8c255))
|
||||
(fp_line (start -4.4958 0.1016) (end -4.4958 0.4064) (layer "F.Fab") (width 0.1524) (tstamp b6e57a1a-77bc-4011-8ab7-3ca5980c960f))
|
||||
(fp_line (start 4.4958 1.905) (end 4.4958 1.6002) (layer "F.Fab") (width 0.1524) (tstamp b8b1c0a5-6e37-467f-b8f0-bf600730b7aa))
|
||||
(fp_line (start 2.413 -4.4958) (end 2.1082 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp b8c56df8-3039-424a-9681-56118c58b690))
|
||||
(fp_line (start 1.0922 4.4958) (end 1.397 4.4958) (layer "F.Fab") (width 0.1524) (tstamp bb394421-3605-4756-9508-929d6758f654))
|
||||
(fp_line (start -3.6068 -4.4958) (end -3.9116 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp be1b6c3d-7e5b-4a40-908c-b936697a3a15))
|
||||
(fp_line (start 4.4958 -0.6096) (end 4.4958 -0.9144) (layer "F.Fab") (width 0.1524) (tstamp c1182e1e-de77-4a90-a154-0b526180f4ec))
|
||||
(fp_line (start -4.4958 2.1082) (end -4.4958 2.413) (layer "F.Fab") (width 0.1524) (tstamp c1bc3314-d8be-4ff1-a3c3-ed1c9b2d7f54))
|
||||
(fp_line (start -2.1082 -4.4958) (end -2.413 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp c2f4caf6-9472-4b57-8792-997c7297ad6f))
|
||||
(fp_line (start 3.4036 -4.4958) (end 3.0988 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp c580dbd6-b23d-4473-a656-cd0cbd690fa4))
|
||||
(fp_line (start 4.4958 0.9144) (end 4.4958 0.6096) (layer "F.Fab") (width 0.1524) (tstamp c8e7357a-ffca-40b2-9f1f-0e667dd778c7))
|
||||
(fp_line (start 4.4958 -3.6068) (end 4.4958 -3.9116) (layer "F.Fab") (width 0.1524) (tstamp c968c46a-836c-481d-9a49-06172946f81e))
|
||||
(fp_line (start -4.4958 -1.905) (end -4.4958 -1.6002) (layer "F.Fab") (width 0.1524) (tstamp cd74684a-5938-4604-a11c-848de541a8a6))
|
||||
(fp_line (start 0.4064 -4.4958) (end 0.1016 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp d06a81a3-464e-4192-865d-76347fe63188))
|
||||
(fp_line (start -4.4958 1.6002) (end -4.4958 1.905) (layer "F.Fab") (width 0.1524) (tstamp e08784ed-8b2a-49ee-bef9-7b2d3857e5ba))
|
||||
(fp_line (start 4.4958 3.9116) (end 4.4958 3.6068) (layer "F.Fab") (width 0.1524) (tstamp e40896aa-4f74-4b18-add9-342665b200b4))
|
||||
(fp_line (start -0.9144 4.4958) (end -0.6096 4.4958) (layer "F.Fab") (width 0.1524) (tstamp e9b70cd9-c935-4ef0-8469-421eb4fd1bac))
|
||||
(fp_line (start -4.4958 -1.397) (end -4.4958 -1.0922) (layer "F.Fab") (width 0.1524) (tstamp eb56c15a-02df-4139-84ab-d8a1651203fa))
|
||||
(fp_line (start 3.0988 4.4958) (end 3.4036 4.4958) (layer "F.Fab") (width 0.1524) (tstamp f58471ed-0cee-4f6a-b2e5-1373fa172f0d))
|
||||
(fp_line (start -2.5908 -4.4958) (end -2.8956 -4.4958) (layer "F.Fab") (width 0.1524) (tstamp f9ac7fe7-3a4d-4488-bc27-2d7e673008b2))
|
||||
(fp_line (start -2.413 4.4958) (end -2.1082 4.4958) (layer "F.Fab") (width 0.1524) (tstamp f9cb66b4-6171-4d5f-b302-fa11feb7e25e))
|
||||
(pad "1" smd rect (at -4.3942 -3.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 0962937a-7e17-49c2-843a-309b9e705166))
|
||||
(pad "2" smd rect (at -4.3942 -3.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp a2fedbd9-479b-4398-baab-86589de39528))
|
||||
(pad "3" smd rect (at -4.3942 -2.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp e98112c7-b41a-4ab2-8cb2-235538dcf529))
|
||||
(pad "4" smd rect (at -4.3942 -2.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 01c8af07-90ff-4b3d-b404-db01135cbcbd))
|
||||
(pad "5" smd rect (at -4.3942 -1.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 36cd9aaf-ae25-480f-827b-e14d53a73530))
|
||||
(pad "6" smd rect (at -4.3942 -1.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 89a4dae4-94d7-4e16-b389-021d58b92093))
|
||||
(pad "7" smd rect (at -4.3942 -0.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp e79aeb81-b0e9-42dc-9659-8a0783bf4de2))
|
||||
(pad "8" smd rect (at -4.3942 -0.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 7c204068-d0aa-459b-b4fa-71e8935dd9dd))
|
||||
(pad "9" smd rect (at -4.3942 0.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 1c34ed7b-f29c-48ab-a67f-7e34e10696d9))
|
||||
(pad "10" smd rect (at -4.3942 0.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 4b62ffb5-f26f-42ce-b28d-6d417a8eb453))
|
||||
(pad "11" smd rect (at -4.3942 1.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp b93c79ac-77e5-4fb0-abe6-0f662be65153))
|
||||
(pad "12" smd rect (at -4.3942 1.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp a82deada-b3dc-43d8-9675-ea9e287e99f4))
|
||||
(pad "13" smd rect (at -4.3942 2.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp f89abcc5-9507-4994-b7ec-08e99b565c34))
|
||||
(pad "14" smd rect (at -4.3942 2.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 3b07801d-fbc1-4f67-a403-def8cd01c41d))
|
||||
(pad "15" smd rect (at -4.3942 3.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp fc1fc9cb-2099-4de4-8cdd-d83af9dd5f90))
|
||||
(pad "16" smd rect (at -4.3942 3.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp bc1d3611-8bc5-4413-b9ae-8a04bfaa0730))
|
||||
(pad "17" smd rect (at -3.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp eae353fe-5b10-44d1-aee2-527fb697339e))
|
||||
(pad "18" smd rect (at -3.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 0be2d7ef-74f7-4c54-9c11-567b325a3550))
|
||||
(pad "19" smd rect (at -2.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 94af1e4e-830f-47d9-b4af-1d2f77f0e846))
|
||||
(pad "20" smd rect (at -2.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 0c875dfd-527c-4ba5-84fd-4d171caf74bb))
|
||||
(pad "21" smd rect (at -1.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp f8327bac-2bfe-4f25-b58b-a76fe59386c6))
|
||||
(pad "22" smd rect (at -1.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 39a31cfe-a89d-4f7b-b480-a9458bbbaeec))
|
||||
(pad "23" smd rect (at -0.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp e1e0568d-368c-488e-902b-8d4d2ca00d90))
|
||||
(pad "24" smd rect (at -0.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp b4c8b1b6-b104-424e-b3ae-e10a63946100))
|
||||
(pad "25" smd rect (at 0.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 43bd0070-dd63-4c69-be69-c4ea652b922a))
|
||||
(pad "26" smd rect (at 0.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 4a1cf31f-d5f4-4210-ac17-84340c530d59))
|
||||
(pad "27" smd rect (at 1.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp a6955bbd-8e2f-47ac-9d2d-1dc038277299))
|
||||
(pad "28" smd rect (at 1.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 7ffcf02c-15fa-481f-81f2-bd642d7f79cb))
|
||||
(pad "29" smd rect (at 2.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 41a0665e-4d1a-4fa6-90c8-82faf5e06664))
|
||||
(pad "30" smd rect (at 2.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp cc003555-3729-46c6-8945-cbd09db502b4))
|
||||
(pad "31" smd rect (at 3.25 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 5c77f960-ade6-4efb-9c4b-dcf559c7eac2))
|
||||
(pad "32" smd rect (at 3.75 4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp d89499ae-4014-4f85-949d-db2745a5c1be))
|
||||
(pad "33" smd rect (at 4.3942 3.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp a15c3c43-a66d-4557-9dd1-9291285217ad))
|
||||
(pad "34" smd rect (at 4.3942 3.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 5654db23-3f90-4ce8-879c-12ebe3c1b2f7))
|
||||
(pad "35" smd rect (at 4.3942 2.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp cf36d037-47b9-4211-a0ba-1b21c826386c))
|
||||
(pad "36" smd rect (at 4.3942 2.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 7446c48e-88d2-43f3-9107-02dc8c28c890))
|
||||
(pad "37" smd rect (at 4.3942 1.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp dc190b06-ebe1-480f-9f26-814b886ca30e))
|
||||
(pad "38" smd rect (at 4.3942 1.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp f31d87cd-a520-48c6-bd59-16ce7a0c8a4c))
|
||||
(pad "39" smd rect (at 4.3942 0.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 3fa7895a-6817-41c8-b122-323e15af05f5))
|
||||
(pad "40" smd rect (at 4.3942 0.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 0af777e9-db83-44e5-82b3-4d0cc1118c82))
|
||||
(pad "41" smd rect (at 4.3942 -0.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp cc198b2a-7c6d-448a-ba27-a1a291727e63))
|
||||
(pad "42" smd rect (at 4.3942 -0.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 4f4f7230-a137-4430-aeca-4b9793e7ef29))
|
||||
(pad "43" smd rect (at 4.3942 -1.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 09e93bbc-81b5-4780-a105-25986af4e57c))
|
||||
(pad "44" smd rect (at 4.3942 -1.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 80626780-24b0-434f-a133-1859aa0ffc80))
|
||||
(pad "45" smd rect (at 4.3942 -2.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp e213e53b-8e52-48ca-828a-5f55b9135f2a))
|
||||
(pad "46" smd rect (at 4.3942 -2.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 4c7b79ca-8f05-473a-80e6-3bebce2e229f))
|
||||
(pad "47" smd rect (at 4.3942 -3.25 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 2cab5ab7-2cc3-4048-816f-20e4725e4987))
|
||||
(pad "48" smd rect (at 4.3942 -3.75 270) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 8441a91d-f48e-4251-bcaf-dc7094507898))
|
||||
(pad "49" smd rect (at 3.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 3c1b33ef-acb9-4266-b8c6-bb013e5dae2c))
|
||||
(pad "50" smd rect (at 3.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp a8a245a0-1165-437d-87fe-7eee7997aee7))
|
||||
(pad "51" smd rect (at 2.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 1e99a129-c646-417d-b055-3f37123cf8ef))
|
||||
(pad "52" smd rect (at 2.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 82864969-1aa8-49df-9eac-4458700e6ca7))
|
||||
(pad "53" smd rect (at 1.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 4d35c705-5a51-4806-a126-12c937c6b1e7))
|
||||
(pad "54" smd rect (at 1.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp d491f121-2845-455d-8541-44fa2ec6c594))
|
||||
(pad "55" smd rect (at 0.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 2186d0aa-6d37-46d1-8257-2c34c61fca1c))
|
||||
(pad "56" smd rect (at 0.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 732ba6d0-6193-4c48-8070-6779e2d08aac))
|
||||
(pad "57" smd rect (at -0.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp f7f108f5-a5d2-4a71-bd92-4b7a64cd67ef))
|
||||
(pad "58" smd rect (at -0.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 5a9c3c03-bc6d-4d54-97af-ccd4b0ec62bd))
|
||||
(pad "59" smd rect (at -1.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 02619e26-a84a-4ced-aa63-185f88279688))
|
||||
(pad "60" smd rect (at -1.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 92a99c1b-1f77-4822-9ef0-404ea7ef9b34))
|
||||
(pad "61" smd rect (at -2.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 90707762-bc1e-4e07-b417-1728eca9f661))
|
||||
(pad "62" smd rect (at -2.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 3db20676-41a3-4cd5-aaaa-fb7aac0e3ef9))
|
||||
(pad "63" smd rect (at -3.25 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 2a66cae8-a800-4958-8ae7-e7d7f25b2674))
|
||||
(pad "64" smd rect (at -3.75 -4.3942 180) (size 0.254 0.8128) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 70110040-44aa-4caf-9824-f55720183967))
|
||||
(pad "65" smd rect (at 0 0) (size 4.572 4.572) (layers "F.Cu" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 1a1fa73c-dc68-468e-8e77-2f7147d220c5))
|
||||
)
|
@ -0,0 +1,29 @@
|
||||
(footprint "SOD-323F" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at -1.8 -0.9) (layer "F.SilkS")
|
||||
(effects (font (size 0.747776 0.747776) (thickness 0.065024)) (justify left bottom))
|
||||
(tstamp 8d130de6-21ac-49e1-b622-a95fb15425d4)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -2.1 1.7) (layer "F.Fab")
|
||||
(effects (font (size 0.747776 0.747776) (thickness 0.065024)) (justify left bottom))
|
||||
(tstamp f5198c37-c2af-4b4a-ace7-b957cdea8352)
|
||||
)
|
||||
(fp_line (start 0.4 -0.6) (end 0.4 0.6) (layer "F.SilkS") (width 0.127) (tstamp 0165360a-2e66-4636-a3c0-be1ba6b7146b))
|
||||
(fp_line (start 0.4 0.6) (end 0.3 0.6) (layer "F.SilkS") (width 0.127) (tstamp 31d6649e-2cb0-4b56-9f6f-94a0dc543d5a))
|
||||
(fp_line (start 0.85 -0.65) (end 0.85 0.65) (layer "F.SilkS") (width 0.127) (tstamp 320884e5-1885-40b5-8b79-b48357d2fa56))
|
||||
(fp_line (start 0.3 0.6) (end 0.3 -0.6) (layer "F.SilkS") (width 0.127) (tstamp 3a4ae6db-a2ad-4e01-be88-bd3d813a8e29))
|
||||
(fp_line (start -0.85 0.65) (end -0.85 -0.65) (layer "F.SilkS") (width 0.127) (tstamp 4fef4a0d-c874-4fe4-9bb4-3b8d64e9347b))
|
||||
(fp_line (start 0.85 0.65) (end -0.85 0.65) (layer "F.SilkS") (width 0.127) (tstamp 7ebd6805-bd0d-4272-b0ea-a17483d80ca5))
|
||||
(fp_line (start -0.85 -0.65) (end 0.85 -0.65) (layer "F.SilkS") (width 0.127) (tstamp cb3724d9-81a8-487f-80a1-8ccce53d6d55))
|
||||
(fp_line (start -0.9 -0.2) (end -1.2 -0.2) (layer "F.Fab") (width 0.127) (tstamp 9290e464-7c10-4d28-b961-53ead5d00f7c))
|
||||
(fp_line (start 1.2 0.2) (end 0.9 0.2) (layer "F.Fab") (width 0.127) (tstamp 9a951f19-776d-408e-9dd7-550047b0e2a6))
|
||||
(fp_line (start -1.2 0.2) (end -0.9 0.2) (layer "F.Fab") (width 0.127) (tstamp c213b2e9-ebc1-49b9-ad72-5803127305a5))
|
||||
(fp_line (start 0.9 -0.2) (end 1.2 -0.2) (layer "F.Fab") (width 0.127) (tstamp c31a6350-0001-4420-90f8-12019bfccaf7))
|
||||
(fp_line (start 1.2 -0.2) (end 1.2 0.2) (layer "F.Fab") (width 0.127) (tstamp d0e73230-a9c2-4595-9b95-ba35aa96b070))
|
||||
(fp_line (start -1.2 -0.2) (end -1.2 0.2) (layer "F.Fab") (width 0.127) (tstamp d91a4af6-4bb8-467f-b69b-1a906bc211a7))
|
||||
(pad "A" smd rect (at -1 0) (size 1 0.8) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 72b76f37-b628-4712-9ff6-021da3f7a013))
|
||||
(pad "C" smd rect (at 1 0) (size 1 0.8) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp cb8dd863-14d8-4470-ad3e-b81fad315442))
|
||||
)
|
@ -0,0 +1,34 @@
|
||||
(footprint "SOT65P210X110-5N" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at -1.8 -1.4) (layer "F.SilkS")
|
||||
(effects (font (size 0.747776 0.747776) (thickness 0.065024)) (justify left bottom))
|
||||
(tstamp 457cb9de-fc22-4a85-9c82-7438f85d137d)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -1.8 1.4) (layer "F.Fab")
|
||||
(effects (font (size 0.747776 0.747776) (thickness 0.065024)) (justify left top))
|
||||
(tstamp 674ecd7e-5cc8-4469-9690-04223952bf82)
|
||||
)
|
||||
(fp_line (start -0.625 1.17) (end 0.625 1.17) (layer "F.SilkS") (width 0.127) (tstamp 2f22abf8-16bd-42ad-a0ee-757b9dc94627))
|
||||
(fp_line (start 0.625 -1.17) (end -0.625 -1.17) (layer "F.SilkS") (width 0.127) (tstamp 7fba8434-1fa5-492e-93c3-f5210db0af84))
|
||||
(fp_circle (center -2.1 -0.9) (end -2 -0.9) (layer "F.SilkS") (width 0.2) (fill none) (tstamp 687a4ff9-95c3-4e33-9daa-47acc0e40e1e))
|
||||
(fp_line (start -1.805 -1.2625) (end -1.805 1.2625) (layer "F.CrtYd") (width 0.05) (tstamp 17863368-ebf9-4b76-8a27-2431df2a120c))
|
||||
(fp_line (start 1.805 -1.2625) (end -1.805 -1.2625) (layer "F.CrtYd") (width 0.05) (tstamp 62cf88fb-d482-4b99-9b0f-281e43055f8b))
|
||||
(fp_line (start -1.805 1.2625) (end 1.805 1.2625) (layer "F.CrtYd") (width 0.05) (tstamp b5135559-37a4-492d-a6dc-8ab982428252))
|
||||
(fp_line (start 1.805 1.2625) (end 1.805 -1.2625) (layer "F.CrtYd") (width 0.05) (tstamp dcf4a5aa-5c00-4b2e-ba11-24374e17c340))
|
||||
(fp_line (start 0.625 1.0125) (end 0.625 -1.0125) (layer "F.Fab") (width 0.127) (tstamp 0d92b703-ef1a-45ad-8945-076840a3419d))
|
||||
(fp_line (start 0.625 -1.0125) (end -0.625 -1.0125) (layer "F.Fab") (width 0.127) (tstamp 3b31ae4c-5100-4114-b54f-c515c85e31ef))
|
||||
(fp_line (start -0.625 -1.0125) (end -0.625 1.0125) (layer "F.Fab") (width 0.127) (tstamp 4479abbf-71f9-42d6-b915-553dfa74ac7a))
|
||||
(fp_line (start -0.625 1.0125) (end 0.625 1.0125) (layer "F.Fab") (width 0.127) (tstamp a7b3fdba-c9c6-4541-aa58-e7d5af1159f7))
|
||||
(fp_circle (center -2.1 -0.9) (end -2 -0.9) (layer "F.Fab") (width 0.2) (fill none) (tstamp 4b3d66f1-3431-45ab-8164-ecd0988102d2))
|
||||
(pad "1" smd rect (at -0.97 -0.65) (size 1.17 0.4) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 79539752-66ac-4cde-9791-7e50fc9c08e9))
|
||||
(pad "2" smd rect (at -0.97 0) (size 1.17 0.4) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 412a873e-1c99-4a4b-86e1-a676f2285a25))
|
||||
(pad "3" smd rect (at -0.97 0.65) (size 1.17 0.4) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp d56e9cb4-6e4a-4ec0-a67f-7fd53cd17c95))
|
||||
(pad "4" smd rect (at 0.97 0.65) (size 1.17 0.4) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp bed9dd9c-f127-43c3-a252-0194a4ef1905))
|
||||
(pad "5" smd rect (at 0.97 -0.65) (size 1.17 0.4) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 468863fa-6e22-4082-9c4f-d4c63b16d5f2))
|
||||
)
|
@ -0,0 +1,282 @@
|
||||
(footprint "SW_EVP-BB1AAB000"
|
||||
(version 20240108)
|
||||
(generator "pcbnew")
|
||||
(generator_version "8.0")
|
||||
(layer "F.Cu")
|
||||
(property "Reference" "REF**"
|
||||
(at -2.628409 -1.50195 0)
|
||||
(layer "F.SilkS")
|
||||
(uuid "5bfc1104-d8e6-463d-96bf-3b297940d17a")
|
||||
(effects
|
||||
(font
|
||||
(size 1.169909 1.169909)
|
||||
(thickness 0.101731)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
)
|
||||
(property "Value" ">VALUE"
|
||||
(at -2.629818 3.005518 0)
|
||||
(layer "F.Fab")
|
||||
(uuid "0d6e3660-78d4-4c9d-aa40-0c2181937185")
|
||||
(effects
|
||||
(font
|
||||
(size 1.170545 1.170545)
|
||||
(thickness 0.101786)
|
||||
)
|
||||
(justify left bottom)
|
||||
)
|
||||
)
|
||||
(property "Footprint" ""
|
||||
(at 0 0 0)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "adf19691-fa3b-4d7a-abc1-3f78748c21cf")
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Datasheet" ""
|
||||
(at 0 0 0)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "e644642e-886c-44ac-b86f-d6c911d62221")
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(property "Description" ""
|
||||
(at 0 0 0)
|
||||
(layer "F.Fab")
|
||||
(hide yes)
|
||||
(uuid "36f34cd2-251b-4e5d-9062-61208ddf5d26")
|
||||
(effects
|
||||
(font
|
||||
(size 1.27 1.27)
|
||||
(thickness 0.15)
|
||||
)
|
||||
)
|
||||
)
|
||||
(fp_line
|
||||
(start -1.325 -0.375)
|
||||
(end -1.325 0.375)
|
||||
(stroke
|
||||
(width 0.465)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Paste")
|
||||
(uuid "4d800587-4919-426d-b1ba-7b44b3e9466f")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.325 -0.375)
|
||||
(end 1.325 0.375)
|
||||
(stroke
|
||||
(width 0.465)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Paste")
|
||||
(uuid "ce64bb60-7755-4c83-8701-9a2cef3a1c7b")
|
||||
)
|
||||
(fp_poly
|
||||
(pts
|
||||
(xy -1.095 -0.145) (xy -1.555 -0.145) (xy -1.555 -0.605) (xy -1.095 -0.605)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type solid)
|
||||
)
|
||||
(fill solid)
|
||||
(layer "F.Paste")
|
||||
(uuid "6db398f8-2729-450b-aef1-8242c2cd2e0f")
|
||||
)
|
||||
(fp_poly
|
||||
(pts
|
||||
(xy -1.095 0.605) (xy -1.555 0.605) (xy -1.555 0.145) (xy -1.095 0.145)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type solid)
|
||||
)
|
||||
(fill solid)
|
||||
(layer "F.Paste")
|
||||
(uuid "84da75db-45c9-4044-8d1e-347621238750")
|
||||
)
|
||||
(fp_poly
|
||||
(pts
|
||||
(xy 1.555 -0.145) (xy 1.095 -0.145) (xy 1.095 -0.605) (xy 1.555 -0.605)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type solid)
|
||||
)
|
||||
(fill solid)
|
||||
(layer "F.Paste")
|
||||
(uuid "e8fb6dd3-e158-4257-9e15-870695c296b7")
|
||||
)
|
||||
(fp_poly
|
||||
(pts
|
||||
(xy 1.555 0.605) (xy 1.095 0.605) (xy 1.095 0.145) (xy 1.555 0.145)
|
||||
)
|
||||
(stroke
|
||||
(width 0)
|
||||
(type solid)
|
||||
)
|
||||
(fill solid)
|
||||
(layer "F.Paste")
|
||||
(uuid "85bec7d7-877b-406c-bad8-abaa99fcbe23")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.3 -0.9635)
|
||||
(end 1.3 -0.9635)
|
||||
(stroke
|
||||
(width 0.127)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "daeab9ff-4ca6-4d3e-8486-53bc65dc2c70")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.3 0.9635)
|
||||
(end 1.3 0.9635)
|
||||
(stroke
|
||||
(width 0.127)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.SilkS")
|
||||
(uuid "2a0673e1-384a-4091-aad2-73c6b1e7babd")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.325 -0.375)
|
||||
(end -1.325 0.375)
|
||||
(stroke
|
||||
(width 0.55)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Mask")
|
||||
(uuid "573428fa-1f2a-49c8-b999-dc918c489ec0")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.325 -0.375)
|
||||
(end 1.325 0.375)
|
||||
(stroke
|
||||
(width 0.55)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Mask")
|
||||
(uuid "3f0f8722-1483-4aa6-bcae-dcff8ecba59b")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.85 -1.05)
|
||||
(end 1.85 -1.05)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "d6daa52c-633b-4f9e-9611-999747c83ff7")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.85 1.05)
|
||||
(end -1.85 -1.05)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "b1dcf4ab-520c-4ad1-8398-87f8dd8fec29")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.85 -1.05)
|
||||
(end 1.85 1.05)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "4939d836-3fdc-47f9-b885-f87382603570")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.85 1.05)
|
||||
(end -1.85 1.05)
|
||||
(stroke
|
||||
(width 0.05)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.CrtYd")
|
||||
(uuid "e4f415ce-fdbb-4c24-b2a1-e501eae24f60")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.3 -0.8)
|
||||
(end 1.3 -0.8)
|
||||
(stroke
|
||||
(width 0.127)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "8e13a383-d573-4545-b914-42a75e606b8c")
|
||||
)
|
||||
(fp_line
|
||||
(start -1.3 0.8)
|
||||
(end -1.3 -0.8)
|
||||
(stroke
|
||||
(width 0.127)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "1e090053-4c0c-424f-8664-54986066ef27")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.3 -0.8)
|
||||
(end 1.3 0.8)
|
||||
(stroke
|
||||
(width 0.127)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "df66859c-c21f-4048-8e27-8d86d5f411f0")
|
||||
)
|
||||
(fp_line
|
||||
(start 1.3 0.8)
|
||||
(end -1.3 0.8)
|
||||
(stroke
|
||||
(width 0.127)
|
||||
(type solid)
|
||||
)
|
||||
(layer "F.Fab")
|
||||
(uuid "31b618ce-8704-4bd2-948f-25d290b97ca7")
|
||||
)
|
||||
(pad "A1" smd rect
|
||||
(at -1.325 -0.375)
|
||||
(size 0.55 0.55)
|
||||
(layers "F.Cu" "F.Mask")
|
||||
(solder_mask_margin 0.0635)
|
||||
(uuid "efeb691d-5593-439a-a931-ffe8a985f2c4")
|
||||
)
|
||||
(pad "A2" smd rect
|
||||
(at -1.325 0.375)
|
||||
(size 0.55 0.55)
|
||||
(layers "F.Cu" "F.Mask")
|
||||
(solder_mask_margin 0.0635)
|
||||
(uuid "4ceaa3e3-568f-42dd-8491-a773d8add0f9")
|
||||
)
|
||||
(pad "B1" smd rect
|
||||
(at 1.325 -0.375)
|
||||
(size 0.55 0.55)
|
||||
(layers "F.Cu" "F.Mask")
|
||||
(solder_mask_margin 0.0635)
|
||||
(uuid "5bdc0a88-b8c1-4c56-b2c0-8737e7eeb5ed")
|
||||
)
|
||||
(pad "B2" smd rect
|
||||
(at 1.325 0.375)
|
||||
(size 0.55 0.55)
|
||||
(layers "F.Cu" "F.Mask")
|
||||
(solder_mask_margin 0.0635)
|
||||
(uuid "fb158033-514b-4126-84ba-b82cd884d9a2")
|
||||
)
|
||||
)
|
@ -0,0 +1,32 @@
|
||||
(footprint "XTAL3215" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(fp_text reference "REF**" (at -2.3 2.2) (layer "F.SilkS")
|
||||
(effects (font (size 0.93472 0.93472) (thickness 0.08128)) (justify left bottom))
|
||||
(tstamp a9c6df82-9b3d-430b-ac3d-773dba21edac)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -2.6 -1.2) (layer "F.Fab")
|
||||
(effects (font (size 0.93472 0.93472) (thickness 0.08128)) (justify left bottom))
|
||||
(tstamp 2d0c10c9-abbe-4218-b4a2-a2a06a7ca92f)
|
||||
)
|
||||
(fp_line (start -1.6 0.4172) (end -1.6 -0.4764) (layer "F.SilkS") (width 0.127) (tstamp 078a622d-2e6e-4da6-9441-6376052c47eb))
|
||||
(fp_line (start -1.1 -0.4) (end 1 -0.4) (layer "F.SilkS") (width 0.127) (tstamp 16000523-6636-4a7c-90fe-2f09fce78d5e))
|
||||
(fp_line (start -1.3 0.2) (end -1.3 -0.1) (layer "F.SilkS") (width 0.127) (tstamp 46b2dcb4-bf9c-401f-993d-249e79f10a6f))
|
||||
(fp_line (start 1 0.4) (end -1 0.4) (layer "F.SilkS") (width 0.127) (tstamp 519e3fa1-ccf8-482c-80ef-bd5f407c1c5f))
|
||||
(fp_line (start 1.3172 0.7) (end -1.3172 0.7) (layer "F.SilkS") (width 0.127) (tstamp 93307323-bd88-4ddc-ab8a-4f2d823906f4))
|
||||
(fp_line (start -1.3764 -0.7) (end 1.2838 -0.7) (layer "F.SilkS") (width 0.127) (tstamp 96d8ac11-ef54-4b37-87dc-dbd4ca0b1cb4))
|
||||
(fp_line (start 1.6 -0.3838) (end 1.6 0.4172) (layer "F.SilkS") (width 0.127) (tstamp bec9dc30-b160-4d84-ad5b-772b0009be76))
|
||||
(fp_line (start 1.3 -0.1) (end 1.3 0.1) (layer "F.SilkS") (width 0.127) (tstamp f4ad8862-e14a-4b15-bbdf-fb0b7a3f55f3))
|
||||
(fp_arc (start -1.3172 0.7) (mid -1.51717 0.61717) (end -1.6 0.4172) (layer "F.SilkS") (width 0.127) (tstamp 0c48587a-6c32-4781-9323-526f5fdc2492))
|
||||
(fp_arc (start 1.3 0.1) (mid 1.212131 0.312132) (end 0.999999 0.399999) (layer "F.SilkS") (width 0.127) (tstamp 11535cde-6a05-4f6a-a42d-7840292384eb))
|
||||
(fp_arc (start -1 0.4) (mid -1.191422 0.362132) (end -1.300001 0.199999) (layer "F.SilkS") (width 0.127) (tstamp 1d879171-52ed-4187-9c41-72a9e6c6b120))
|
||||
(fp_arc (start -1.6 -0.4764) (mid -1.534509 -0.634509) (end -1.3764 -0.7) (layer "F.SilkS") (width 0.127) (tstamp 285901dd-7be7-4fde-bb96-976224872c4a))
|
||||
(fp_arc (start -1.3 -0.1) (mid -1.262161 -0.291441) (end -1.099999 -0.399999) (layer "F.SilkS") (width 0.127) (tstamp 2eacfb6a-d7d1-4bde-b6bc-6096465bc8c1))
|
||||
(fp_arc (start 1.2838 -0.7) (mid 1.507387 -0.607387) (end 1.6 -0.3838) (layer "F.SilkS") (width 0.127) (tstamp 499a51d8-52e8-4eb8-aeac-96a1be49503b))
|
||||
(fp_arc (start 1.6 0.4172) (mid 1.51717 0.61717) (end 1.3172 0.7) (layer "F.SilkS") (width 0.127) (tstamp ab55d0d5-009c-4663-a9bc-dfc975cfe4f8))
|
||||
(fp_arc (start 1 -0.4) (mid 1.212103 -0.312103) (end 1.3 -0.1) (layer "F.SilkS") (width 0.127) (tstamp e095b566-4c68-4a1b-a41d-59524889820a))
|
||||
(pad "P$1" smd rect (at 1.2 0) (size 1.1 1.9) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 4ee07c5d-9f78-4558-bf26-a2f36b7ff744))
|
||||
(pad "P$2" smd rect (at -1.2 0 180) (size 1.1 1.9) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 4d20cca2-e97b-4688-a784-b838b6ce3b76))
|
||||
)
|
@ -0,0 +1,38 @@
|
||||
(footprint "_0402MP" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(descr "<b>0402 MicroPitch<p>")
|
||||
(fp_text reference "REF**" (at -0.635 -0.4763) (layer "F.SilkS")
|
||||
(effects (font (size 0.499872 0.499872) (thickness 0.109728)) (justify left bottom))
|
||||
(tstamp 66f54e50-362a-4456-a671-e8b742aabfe7)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -0.635 0.7938) (layer "F.Fab")
|
||||
(effects (font (size 0.36576 0.36576) (thickness 0.04064)) (justify left bottom))
|
||||
(tstamp 7205e05a-db5d-40d5-aa8d-0965b4d6a0a3)
|
||||
)
|
||||
(fp_poly (pts
|
||||
(xy -0.1 0.2)
|
||||
(xy 0.1 0.2)
|
||||
(xy 0.1 -0.2)
|
||||
(xy -0.1 -0.2)
|
||||
) (layer "F.Adhes") (width 0) (fill solid) (tstamp 151adedc-3095-4283-bc8b-67b6c834501c))
|
||||
(fp_line (start 0 -0.127) (end 0 0.127) (layer "F.SilkS") (width 0.2032) (tstamp a31d0c78-4bd5-4839-be72-14af5f3f165d))
|
||||
(fp_line (start -0.245 -0.174) (end 0.245 -0.174) (layer "F.Fab") (width 0.1016) (tstamp ddaa21a2-edd4-401c-ac76-6f183cf5be3d))
|
||||
(fp_line (start 0.245 0.174) (end -0.245 0.174) (layer "F.Fab") (width 0.1016) (tstamp ec8c18e2-500a-4935-81c1-76a24c731e63))
|
||||
(fp_poly (pts
|
||||
(xy -0.5 0.25)
|
||||
(xy -0.254 0.25)
|
||||
(xy -0.254 -0.25)
|
||||
(xy -0.5 -0.25)
|
||||
) (layer "F.Fab") (width 0) (fill solid) (tstamp 335257f6-f886-460f-b838-e2d8232128c8))
|
||||
(fp_poly (pts
|
||||
(xy 0.2588 0.25)
|
||||
(xy 0.5 0.25)
|
||||
(xy 0.5 -0.25)
|
||||
(xy 0.2588 -0.25)
|
||||
) (layer "F.Fab") (width 0) (fill solid) (tstamp 3d7cd32b-2bab-4b7c-a3da-482a6d596be7))
|
||||
(pad "1" smd rect (at -0.508 0) (size 0.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp c609a9e6-5647-44af-a743-b732a2a0c37d))
|
||||
(pad "2" smd rect (at 0.508 0) (size 0.5 0.5) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 1249fd1b-9f93-42c3-bb42-dae4056aa043))
|
||||
)
|
@ -0,0 +1,38 @@
|
||||
(footprint "_0603MP" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(descr "<b>0603 MicroPitch</b>")
|
||||
(fp_text reference "REF**" (at -0.9525 -0.635) (layer "F.SilkS")
|
||||
(effects (font (size 0.666496 0.666496) (thickness 0.146304)) (justify left bottom))
|
||||
(tstamp a1f3b960-720c-4050-8c7b-e4fb81f7c447)
|
||||
)
|
||||
(fp_text value ">VALUE" (at -0.9525 0.9525) (layer "F.Fab")
|
||||
(effects (font (size 0.36576 0.36576) (thickness 0.04064)) (justify left bottom))
|
||||
(tstamp f7454cc9-a5be-454b-b5bb-decc69423e09)
|
||||
)
|
||||
(fp_poly (pts
|
||||
(xy -0.1999 0.25)
|
||||
(xy 0.1999 0.25)
|
||||
(xy 0.1999 -0.25)
|
||||
(xy -0.1999 -0.25)
|
||||
) (layer "F.Adhes") (width 0) (fill solid) (tstamp 23d6168b-6030-48a2-96be-111de678cbf9))
|
||||
(fp_line (start 0 -0.254) (end 0 0.254) (layer "F.SilkS") (width 0.2032) (tstamp ebb6e458-b901-41c0-b269-52de840ade47))
|
||||
(fp_line (start -0.432 0.306) (end 0.432 0.306) (layer "F.Fab") (width 0.1016) (tstamp 0ff59386-9f8f-4bc5-871b-4804e001e34f))
|
||||
(fp_line (start 0.432 -0.306) (end -0.432 -0.306) (layer "F.Fab") (width 0.1016) (tstamp c1b693b3-0c6a-47f3-bd85-e73de386676a))
|
||||
(fp_poly (pts
|
||||
(xy 0.4318 0.4)
|
||||
(xy 0.8 0.4)
|
||||
(xy 0.8 -0.4)
|
||||
(xy 0.4318 -0.4)
|
||||
) (layer "F.Fab") (width 0) (fill solid) (tstamp 98d6e8c0-7c85-4056-b142-5a49d5f78f6a))
|
||||
(fp_poly (pts
|
||||
(xy -0.8 0.4)
|
||||
(xy -0.4318 0.4)
|
||||
(xy -0.4318 -0.4)
|
||||
(xy -0.8 -0.4)
|
||||
) (layer "F.Fab") (width 0) (fill solid) (tstamp c67e1e1d-f03c-4cd2-855a-6f77ed9840d4))
|
||||
(pad "1" smd rect (at -0.762 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp 261178c6-668c-4d25-9316-e97dc5e52e2d))
|
||||
(pad "2" smd rect (at 0.762 0) (size 0.8 0.8) (layers "F.Cu" "F.Paste" "F.Mask")
|
||||
(solder_mask_margin 0.0635) (tstamp aece925f-4ef2-4a3b-a64c-72600b766d22))
|
||||
)
|
@ -0,0 +1,4 @@
|
||||
Default True 2.0 3
|
||||
gnd True 2.0 3
|
||||
power True 2.0 3
|
||||
True True False
|
@ -0,0 +1,42 @@
|
||||
(footprint "OSO_SWD_2x3" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(attr smd)
|
||||
(fp_text reference "REF**" (at 0 -2.032 unlocked) (layer "F.SilkS") hide
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp cc97765e-03dd-40c8-bc09-9942f8485d23)
|
||||
)
|
||||
(fp_text value "OSO_SWD_2x3" (at 0 -4.572 unlocked) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 3723f1be-f632-4091-a098-c9348aec63f6)
|
||||
)
|
||||
(fp_text user "C" (at -0.508 -0.762 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp 88931c8d-237f-4e79-b244-24354b5507cc)
|
||||
)
|
||||
(fp_text user "+" (at -0.508 1.778 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp b2d594d3-dac9-41e7-b515-19ad22df4cd2)
|
||||
)
|
||||
(fp_text user "D" (at 2.032 1.778 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp c41801cb-4840-4a63-9b83-a0b86093de8d)
|
||||
)
|
||||
(fp_text user "-" (at 2.032 -0.762 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp d116e34b-7d96-49fa-980e-61f5adbb5cc2)
|
||||
)
|
||||
(fp_text user "~{R}" (at -0.508 -3.302 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp e48e1604-d489-45a4-9587-152a042c354a)
|
||||
)
|
||||
(fp_text user "${REFERENCE}" (at 0 4.318 unlocked) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 3cf253e6-b3d8-4b70-990a-3a9df456d233)
|
||||
)
|
||||
(pad "1" smd circle (at 1.27 2.54) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp c93a3c51-b06c-47bc-b2c8-dcd43fd3bce4))
|
||||
(pad "2" smd circle (at 1.27 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 657a0b8d-9c0a-4efd-920e-1742e80dbd77))
|
||||
(pad "3" smd circle (at -1.27 2.54) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 110879b7-d820-400e-83c2-2ba83b15a32d))
|
||||
(pad "4" smd circle (at -1.27 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 0da5021b-2960-4fb1-abd4-df913ada6e37))
|
||||
(pad "5" smd circle (at -1.27 -2.54) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 5e6b9662-455f-4d0d-8334-3f95b2cc20e1))
|
||||
)
|
@ -0,0 +1,42 @@
|
||||
(footprint "OSO_SWD_Linear" (version 20211014) (generator pcbnew)
|
||||
(layer "F.Cu")
|
||||
(tedit 0)
|
||||
(attr smd)
|
||||
(fp_text reference "REF**" (at 0 -2.032 unlocked) (layer "F.SilkS") hide
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp cc97765e-03dd-40c8-bc09-9942f8485d23)
|
||||
)
|
||||
(fp_text value "OSO_SWD_Linear" (at 0 -1.5 unlocked) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 3723f1be-f632-4091-a098-c9348aec63f6)
|
||||
)
|
||||
(fp_text user "SWC" (at 2.54 1.524 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp 88931c8d-237f-4e79-b244-24354b5507cc)
|
||||
)
|
||||
(fp_text user "3V3" (at 0 1.524 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp b2d594d3-dac9-41e7-b515-19ad22df4cd2)
|
||||
)
|
||||
(fp_text user "SWD" (at -5.08 1.524 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp c41801cb-4840-4a63-9b83-a0b86093de8d)
|
||||
)
|
||||
(fp_text user "GND" (at -2.54 1.524 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp d116e34b-7d96-49fa-980e-61f5adbb5cc2)
|
||||
)
|
||||
(fp_text user "~{RST}" (at 5.08 1.524 unlocked) (layer "F.SilkS")
|
||||
(effects (font (size 0.5 0.5) (thickness 0.1)))
|
||||
(tstamp e48e1604-d489-45a4-9587-152a042c354a)
|
||||
)
|
||||
(fp_text user "${REFERENCE}" (at 0 3.048 unlocked) (layer "F.Fab")
|
||||
(effects (font (size 1 1) (thickness 0.15)))
|
||||
(tstamp 3cf253e6-b3d8-4b70-990a-3a9df456d233)
|
||||
)
|
||||
(pad "1" smd circle (at -5.08 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp c93a3c51-b06c-47bc-b2c8-dcd43fd3bce4))
|
||||
(pad "2" smd circle (at -2.54 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 657a0b8d-9c0a-4efd-920e-1742e80dbd77))
|
||||
(pad "3" smd circle (at 0 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 110879b7-d820-400e-83c2-2ba83b15a32d))
|
||||
(pad "4" smd circle (at 2.54 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 0da5021b-2960-4fb1-abd4-df913ada6e37))
|
||||
(pad "5" smd circle (at 5.08 0) (size 1.5 1.5) (layers "F.Cu" "F.Mask") (tstamp 5e6b9662-455f-4d0d-8334-3f95b2cc20e1))
|
||||
)
|
44
PCB/Main Boards/OSO-SWAT-C1/OSO_SWD.kicad_sym
Normal file
44
PCB/Main Boards/OSO-SWAT-C1/OSO_SWD.kicad_sym
Normal file
@ -0,0 +1,44 @@
|
||||
(kicad_symbol_lib (version 20211014) (generator kicad_symbol_editor)
|
||||
(symbol "OSO_SWD" (in_bom yes) (on_board yes)
|
||||
(property "Reference" "J" (id 0) (at 0 -7.62 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Value" "OSO_SWD" (id 1) (at 0 7.62 0)
|
||||
(effects (font (size 1.27 1.27)))
|
||||
)
|
||||
(property "Footprint" "" (id 2) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(property "Datasheet" "" (id 3) (at 0 0 0)
|
||||
(effects (font (size 1.27 1.27)) hide)
|
||||
)
|
||||
(symbol "OSO_SWD_0_1"
|
||||
(rectangle (start -5.08 6.35) (end 5.08 -6.35)
|
||||
(stroke (width 0) (type default) (color 0 0 0 0))
|
||||
(fill (type background))
|
||||
)
|
||||
)
|
||||
(symbol "OSO_SWD_1_1"
|
||||
(pin bidirectional line (at -7.62 5.08 0) (length 2.54)
|
||||
(name "SWDIO" (effects (font (size 1.27 1.27))))
|
||||
(number "1" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin power_in line (at -7.62 2.54 0) (length 2.54)
|
||||
(name "GND" (effects (font (size 1.27 1.27))))
|
||||
(number "2" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin power_in line (at -7.62 0 0) (length 2.54)
|
||||
(name "VCC" (effects (font (size 1.27 1.27))))
|
||||
(number "3" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -7.62 -2.54 0) (length 2.54)
|
||||
(name "SWCLK" (effects (font (size 1.27 1.27))))
|
||||
(number "4" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
(pin bidirectional line (at -7.62 -5.08 0) (length 2.54)
|
||||
(name "~{RESET}" (effects (font (size 1.27 1.27))))
|
||||
(number "5" (effects (font (size 1.27 1.27))))
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
10807
PCB/Main Boards/OSO-SWAT-C1/QBLP655_QBLP655R_BI_TRI.step
Normal file
10807
PCB/Main Boards/OSO-SWAT-C1/QBLP655_QBLP655R_BI_TRI.step
Normal file
File diff suppressed because it is too large
Load Diff
2612
PCB/Main Boards/OSO-SWAT-C1/contact_adjusted_angle.step
Normal file
2612
PCB/Main Boards/OSO-SWAT-C1/contact_adjusted_angle.step
Normal file
File diff suppressed because it is too large
Load Diff
5
PCB/Main Boards/OSO-SWAT-C1/empty.kicad_wks
Normal file
5
PCB/Main Boards/OSO-SWAT-C1/empty.kicad_wks
Normal file
@ -0,0 +1,5 @@
|
||||
(kicad_wks (version 20210606) (generator pl_editor)
|
||||
(setup (textsize 1.5 1.5)(linewidth 0.15)(textlinewidth 0.15)
|
||||
(left_margin 10)(right_margin 10)(top_margin 10)(bottom_margin 10))
|
||||
(line (name "segm1:Line") (start 0 0) (end 0 0))
|
||||
)
|
4
PCB/Main Boards/OSO-SWAT-C1/fp-lib-table
Normal file
4
PCB/Main Boards/OSO-SWAT-C1/fp-lib-table
Normal file
@ -0,0 +1,4 @@
|
||||
(fp_lib_table
|
||||
(lib (name "OSO-SWAT-A1-05")(type "KiCad")(uri "$(KIPRJMOD)/OSO-SWAT-C1.pretty")(options "")(descr ""))
|
||||
(lib (name "OSO-SWD")(type "KiCad")(uri "${KIPRJMOD}/OSO-SWD.pretty")(options "")(descr ""))
|
||||
)
|
4
PCB/Main Boards/OSO-SWAT-C1/sym-lib-table
Normal file
4
PCB/Main Boards/OSO-SWAT-C1/sym-lib-table
Normal file
@ -0,0 +1,4 @@
|
||||
(sym_lib_table
|
||||
(lib (name "OSO-SWAT-A1-05-eagle-import")(type "KiCad")(uri "${KIPRJMOD}/OSO-SWAT-A1-05-eagle-import.kicad_sym")(options "")(descr ""))
|
||||
(lib (name "OSO-SWD")(type "KiCad")(uri "${KIPRJMOD}/OSO_SWD.kicad_sym")(options "")(descr ""))
|
||||
)
|
11
README.md
11
README.md
@ -74,6 +74,17 @@ python3 -m http.server -d build-sim
|
||||
|
||||
Finally, visit [watch.html](http://localhost:8000/watch.html) to see your work.
|
||||
|
||||
Hardware Schematics and PCBs
|
||||
----------------------------
|
||||
|
||||
| Name | Color | Schematic | Gerbers |
|
||||
| ---- | ----- | --------- | ------- |
|
||||
| Sensorwatch Lite | RED | [PCB/Main Boards/OSO-SWAT-B1](PCB/Main%20Boards/OSO-SWAT-B1) | [OSO-SWAT-B1-03](PCB/Main%20Boards/OSO-SWAT-B1/OSO-SWAT-B1-03.zip) |
|
||||
| Sensorwatch | GREEN | [OSO-SWAT-A1-05](PCB/Main%20Boards/OSO-SWAT-A1/OSO-SWAT-A1-05.sch) (Eagle format) | ? |
|
||||
| Sensorwatch Pro | TBD | TBD | TBD |
|
||||
|
||||
|
||||
|
||||
License
|
||||
-------
|
||||
Different components of the project are licensed differently, see [LICENSE.md](https://github.com/joeycastillo/Sensor-Watch/blob/main/LICENSE.md).
|
||||
|
420
apps/sensor-watch-pro-test/app.c
Normal file
420
apps/sensor-watch-pro-test/app.c
Normal file
@ -0,0 +1,420 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "watch.h"
|
||||
#include "spiflash.h"
|
||||
|
||||
bool has_ticked = false;
|
||||
extern struct io_descriptor *uart_io;
|
||||
|
||||
// array of lcd pins from pins.h
|
||||
const uint8_t lcd_pins[] = {
|
||||
SLCD26, // SEG23
|
||||
SLCD25, // SEG22
|
||||
SLCD24, // SEG21
|
||||
SLCD23, // SEG20
|
||||
SLCD22, // SEG19
|
||||
SLCD21, // SEG18
|
||||
SLCD20, // SEG17
|
||||
SLCD19, // SEG16
|
||||
SLCD18, // SEG15
|
||||
SLCD17, // SEG14
|
||||
SLCD16, // SEG13
|
||||
SLCD15, // SEG12
|
||||
SLCD14, // SEG11
|
||||
SLCD13, // SEG10
|
||||
SLCD12, // SEG9
|
||||
SLCD11, // SEG8
|
||||
SLCD10, // SEG7
|
||||
SLCD9, // SEG6
|
||||
SLCD8, // SEG5
|
||||
SLCD7, // SEG4
|
||||
SLCD6, // SEG3
|
||||
SLCD5, // SEG2
|
||||
SLCD4, // SEG1
|
||||
SLCD3, // SEG0
|
||||
SLCD2, // COM2
|
||||
SLCD1, // COM1
|
||||
SLCD0, // COM0
|
||||
};
|
||||
|
||||
void cb_tick(void);
|
||||
void cb_tick(void) {
|
||||
has_ticked = true;
|
||||
watch_rtc_disable_periodic_callback(8);
|
||||
}
|
||||
|
||||
void pass_if(bool passed);
|
||||
void pass_if(bool passed) {
|
||||
if (passed) {
|
||||
watch_set_led_green();
|
||||
delay_ms(100);
|
||||
watch_set_led_off();
|
||||
} else {
|
||||
watch_set_led_red();
|
||||
delay_ms(100);
|
||||
watch_set_led_off();
|
||||
}
|
||||
}
|
||||
|
||||
void app_init(void) {
|
||||
}
|
||||
|
||||
void app_wake_from_backup(void) {
|
||||
}
|
||||
|
||||
static void enable_irda_uart() {
|
||||
gpio_set_pin_direction(IR_ENABLE, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(IR_ENABLE, false);
|
||||
|
||||
SERCOM_USART_CTRLA_Type ctrla;
|
||||
SERCOM_USART_CTRLB_Type ctrlb;
|
||||
ctrla.reg = SERCOM_USART_CTRLA_DORD | SERCOM_USART_CTRLA_MODE(1);
|
||||
ctrlb.reg = SERCOM_USART_CTRLB_CHSIZE(0) | SERCOM_USART_CTRLB_ENC;
|
||||
|
||||
MCLK->APBCMASK.reg |= MCLK_APBCMASK_SERCOM0;
|
||||
GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg = GCLK_PCHCTRL_GEN(0) | GCLK_PCHCTRL_CHEN;
|
||||
|
||||
while (0 == (GCLK->PCHCTRL[SERCOM0_GCLK_ID_CORE].reg & GCLK_PCHCTRL_CHEN));
|
||||
|
||||
usart_sync_init(&USART_0, SERCOM0, (void *)NULL);
|
||||
|
||||
SERCOM0->USART.CTRLA.reg &= ~SERCOM_USART_CTRLA_ENABLE;
|
||||
|
||||
gpio_set_pin_direction(IRSENSE, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_function(IRSENSE, PINMUX_PA04D_SERCOM0_PAD0);
|
||||
ctrla.reg |= SERCOM_USART_CTRLA_RXPO(0);
|
||||
ctrlb.reg |= SERCOM_USART_CTRLB_RXEN;
|
||||
|
||||
SERCOM0->USART.CTRLA.reg = ctrla.reg;
|
||||
SERCOM0->USART.CTRLB.reg = ctrlb.reg;
|
||||
|
||||
if (hri_usbdevice_get_CTRLA_ENABLE_bit(USB)) {
|
||||
uint64_t br = 65536 - ((65536 * 16.0f * 600) / 8000000);
|
||||
SERCOM0->USART.BAUD.reg = (uint16_t)br;
|
||||
} else {
|
||||
uint64_t br = 65536 - ((65536 * 16.0f * 600) / 4000000);
|
||||
SERCOM0->USART.BAUD.reg = (uint16_t)br;
|
||||
}
|
||||
|
||||
SERCOM0->USART.CTRLA.reg |= SERCOM_USART_CTRLA_ENABLE;
|
||||
|
||||
usart_sync_enable(&USART_0);
|
||||
usart_sync_get_io_descriptor(&USART_0, &uart_io);
|
||||
}
|
||||
|
||||
void app_setup(void) {
|
||||
// Set up tick for RTC test
|
||||
watch_rtc_register_periodic_callback(cb_tick, 8);
|
||||
|
||||
// Set up UART for communication with tester
|
||||
enable_irda_uart();
|
||||
|
||||
// Set up LED pins
|
||||
watch_enable_leds();
|
||||
watch_enable_buzzer();
|
||||
|
||||
// Set up buttons with pull-down resistors
|
||||
gpio_set_pin_direction(BTN_ALARM, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(BTN_ALARM, GPIO_PULL_DOWN);
|
||||
gpio_set_pin_direction(BTN_LIGHT, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(BTN_LIGHT, GPIO_PULL_DOWN);
|
||||
gpio_set_pin_direction(BTN_MODE, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(BTN_MODE, GPIO_PULL_DOWN);
|
||||
|
||||
// Set up ADC for thermistor and light sensor tests
|
||||
watch_enable_adc();
|
||||
watch_enable_analog_input(TEMPSENSE);
|
||||
// Pin A0 is the thermistor enable pin
|
||||
gpio_set_pin_direction(TS_ENABLE, GPIO_DIRECTION_OUT);
|
||||
}
|
||||
|
||||
void app_prepare_for_standby(void) {
|
||||
}
|
||||
|
||||
void app_wake_from_standby(void) {
|
||||
}
|
||||
|
||||
static bool test_i2c(void) {
|
||||
watch_enable_i2c();
|
||||
uint16_t device_id = watch_i2c_read8(0x48, 0x0F);
|
||||
printf("%d\n", device_id);
|
||||
|
||||
return device_id == 0x75;
|
||||
}
|
||||
|
||||
static bool test_spi(void) {
|
||||
gpio_set_pin_level(A3, true);
|
||||
gpio_set_pin_direction(A3, GPIO_DIRECTION_OUT);
|
||||
watch_enable_spi();
|
||||
delay_ms(10);
|
||||
|
||||
watch_set_pin_level(A3, false);
|
||||
delay_ms(10);
|
||||
uint8_t read_status_response[3] = {0};
|
||||
bool ok = spi_flash_read_command(0x9F, read_status_response, 3);
|
||||
watch_set_pin_level(A3, true);
|
||||
printf("%d %d %d\n", read_status_response[0], read_status_response[1], read_status_response[2]);
|
||||
|
||||
return (read_status_response[0] == 0xC8 && read_status_response[1] == 0x40 && read_status_response[2] == 0x13);
|
||||
}
|
||||
|
||||
bool app_loop(void) {
|
||||
uint8_t buf[5] = {0};
|
||||
watch_storage_read(10, 0, buf, 4);
|
||||
printf("%s\n", (const char *)buf);
|
||||
|
||||
if (strcmp((const char *)buf, "BEEP") == 0) {
|
||||
watch_set_led_yellow();
|
||||
watch_buzzer_play_note(BUZZER_NOTE_C5, 150);
|
||||
watch_buzzer_play_note(BUZZER_NOTE_REST, 25);
|
||||
watch_buzzer_play_note(BUZZER_NOTE_E5, 150);
|
||||
watch_buzzer_play_note(BUZZER_NOTE_REST, 25);
|
||||
watch_buzzer_play_note(BUZZER_NOTE_G5, 150);
|
||||
watch_buzzer_play_note(BUZZER_NOTE_REST, 25);
|
||||
watch_buzzer_play_note(BUZZER_NOTE_C6, 150);
|
||||
|
||||
watch_storage_erase(10);
|
||||
delay_ms(10);
|
||||
watch_storage_write(10, 0, (const char *)"9PIN", 4);
|
||||
watch_storage_sync();
|
||||
watch_storage_read(10, 0, buf, 4);
|
||||
delay_ms(10);
|
||||
if(strcmp((const char *)buf, (const char *)"9PIN") == 0) {
|
||||
watch_set_led_off();
|
||||
while(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp((const char *)buf, "9PIN") == 0) {
|
||||
bool i2c_passed = test_i2c();
|
||||
bool spi_passed = test_spi();
|
||||
|
||||
if (i2c_passed && spi_passed) {
|
||||
watch_storage_erase(10);
|
||||
delay_ms(10);
|
||||
watch_storage_write(10, 0, (const char *)"PASS", 4);
|
||||
watch_storage_sync();
|
||||
watch_storage_read(10, 0, buf, 4);
|
||||
delay_ms(10);
|
||||
|
||||
if(strcmp((const char *)buf, (const char *)"PASS") == 0) {
|
||||
gpio_set_pin_direction(A0, GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(A0, true);
|
||||
}
|
||||
} else if (i2c_passed) {
|
||||
// SPI failed, RED indicator
|
||||
watch_set_led_color_rgb(128, 0, 0);
|
||||
} else if (spi_passed) {
|
||||
// I2C failed, BLUE indicator
|
||||
watch_set_led_color_rgb(0, 0, 128);
|
||||
} else {
|
||||
// both failed, PURPLE indicator
|
||||
watch_set_led_color_rgb(64, 0, 128);
|
||||
}
|
||||
|
||||
while(1);
|
||||
}
|
||||
|
||||
if(strcmp((const char *)buf, (const char *)"PASS") == 0) {
|
||||
watch_set_led_green();
|
||||
while(1);
|
||||
}
|
||||
|
||||
char char_received = watch_uart_getc();
|
||||
|
||||
if (char_received) {
|
||||
switch (char_received) {
|
||||
// - [X] RTC
|
||||
case 'R':
|
||||
pass_if(has_ticked);
|
||||
break;
|
||||
// - [X] LCD pin continuity
|
||||
case 'O':
|
||||
// Set all LCD pins high
|
||||
for (int i = 0; i < 27; i++) {
|
||||
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
|
||||
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(lcd_pins[i], true);
|
||||
}
|
||||
// It is the tester's responsibility to check that the pins are high
|
||||
break;
|
||||
case 'P':
|
||||
// Set all LCD pins low
|
||||
for (int i = 0; i < 27; i++) {
|
||||
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
|
||||
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(lcd_pins[i], false);
|
||||
}
|
||||
// It is the tester's responsibility to check that the pins are low
|
||||
break;
|
||||
// - [X] LCD pin bridging
|
||||
case 'Q':
|
||||
{
|
||||
bool passed = true;
|
||||
// Pull all LCD pins up
|
||||
for (int i = 0; i < 27; i++) {
|
||||
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
|
||||
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(lcd_pins[i], GPIO_PULL_UP);
|
||||
}
|
||||
// SEG23 is adjacent to the green LED.
|
||||
// setting the LED green drives GREEN low.
|
||||
watch_set_led_green();
|
||||
if (!gpio_get_pin_level(SLCD26)) {
|
||||
// If SEG23 is low, then it must be bridged to the green pin
|
||||
pass_if(false);
|
||||
}
|
||||
// SEG13 is adjacent to the blue LED.
|
||||
// setting the LED blue drives BLUE low.
|
||||
watch_set_led_color_rgb(0, 0, 255);
|
||||
if (!gpio_get_pin_level(SLCD16)) {
|
||||
// If SEG13 is low, then it must be bridged to the blue pin
|
||||
pass_if(false);
|
||||
}
|
||||
// SEG12 is adjacent to the red LED.
|
||||
// setting the LED red drives RED low.
|
||||
watch_set_led_red();
|
||||
if (!gpio_get_pin_level(SLCD15)) {
|
||||
// If SEG12 is low, then it must be bridged to the red pin
|
||||
pass_if(false);
|
||||
}
|
||||
watch_set_led_off();
|
||||
// After this, all LCD pins are adjacent. Test if each pin is bridged to the previous one.
|
||||
for (int i = 1; i < 27; i++) {
|
||||
gpio_set_pin_direction(lcd_pins[i - 1], GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(lcd_pins[i - 1], false);
|
||||
if (!gpio_get_pin_level(lcd_pins[i])) {
|
||||
passed = false;
|
||||
break;
|
||||
}
|
||||
gpio_set_pin_direction(lcd_pins[i - 1], GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(lcd_pins[i - 1], GPIO_PULL_UP);
|
||||
}
|
||||
// Special cases:
|
||||
// SLCD0 neighbors VCC
|
||||
gpio_set_pin_direction(SLCD0, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(SLCD0, GPIO_PULL_DOWN);
|
||||
if (gpio_get_pin_level(SLCD0)) {
|
||||
passed = false;
|
||||
}
|
||||
// SLCD18 neighbors VCC
|
||||
gpio_set_pin_direction(SLCD18, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(SLCD18, GPIO_PULL_DOWN);
|
||||
if (gpio_get_pin_level(SLCD18)) {
|
||||
passed = false;
|
||||
}
|
||||
// SLCD26 neighbors USB_N
|
||||
gpio_set_pin_direction(GPIO(GPIO_PORTA, 24), GPIO_DIRECTION_OUT);
|
||||
gpio_set_pin_level(GPIO(GPIO_PORTA, 24), true);
|
||||
gpio_set_pin_direction(SLCD26, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(SLCD26, GPIO_PULL_DOWN);
|
||||
// if SLCD26 is high, then it is bridged to USB_N
|
||||
if (gpio_get_pin_level(SLCD26)) {
|
||||
passed = false;
|
||||
}
|
||||
// SLCD11 neighbors VLCD
|
||||
watch_enable_display();
|
||||
delay_ms(50);
|
||||
gpio_set_pin_function(SLCD11, GPIO_PIN_FUNCTION_OFF);
|
||||
gpio_set_pin_direction(SLCD11, GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(SLCD11, GPIO_PULL_DOWN);
|
||||
if (gpio_get_pin_level(SLCD11)) {
|
||||
passed = false;
|
||||
}
|
||||
for (int i = 0; i < 27; i++) {
|
||||
gpio_set_pin_function(lcd_pins[i], GPIO_PIN_FUNCTION_OFF);
|
||||
gpio_set_pin_direction(lcd_pins[i], GPIO_DIRECTION_IN);
|
||||
gpio_set_pin_pull_mode(lcd_pins[i], GPIO_PULL_OFF);
|
||||
}
|
||||
|
||||
pass_if(passed);
|
||||
}
|
||||
break;
|
||||
// - [X] Thermistor high
|
||||
case 'U':
|
||||
// Set TS_ENABLE high and read the value of TEMPSENSE via the ADC.
|
||||
// Pass if the value is near VCC.
|
||||
gpio_set_pin_level(TS_ENABLE, true);
|
||||
pass_if(watch_get_analog_pin_level(TEMPSENSE) > 65000);
|
||||
break;
|
||||
// - [X] Thermistor low
|
||||
case 'T':
|
||||
{
|
||||
// Set TS_ENABLE low and read the value of TEMPSENSE via the ADC.
|
||||
// Pass if the value is within the realm of reasonable temperatures.
|
||||
// 15000 is a few minutes in the freezer, 45000 is holding it a few feet above a stovetop
|
||||
gpio_set_pin_level(TS_ENABLE, false);
|
||||
uint16_t value = watch_get_analog_pin_level(TEMPSENSE);
|
||||
pass_if(value < 45000 && value > 15000);
|
||||
}
|
||||
break;
|
||||
// - [X] VLCD low
|
||||
case 'V':
|
||||
watch_enable_display();
|
||||
SLCD->CTRLA.bit.ENABLE = 0;
|
||||
while(SLCD->SYNCBUSY.bit.ENABLE);
|
||||
SLCD->CTRLC.bit.CTST = 0x0;
|
||||
SLCD->CTRLA.bit.ENABLE = 1;
|
||||
while(SLCD->SYNCBUSY.bit.ENABLE);
|
||||
break;
|
||||
// - [X] VLCD high
|
||||
case 'W':
|
||||
watch_enable_display();
|
||||
SLCD->CTRLA.bit.ENABLE = 0;
|
||||
while(SLCD->SYNCBUSY.bit.ENABLE);
|
||||
SLCD->CTRLC.bit.CTST = 0xD;
|
||||
SLCD->CTRLA.bit.ENABLE = 1;
|
||||
while(SLCD->SYNCBUSY.bit.ENABLE);
|
||||
break;
|
||||
/// TODO: LED
|
||||
case 'r':
|
||||
watch_set_led_color_rgb(255, 0, 0);
|
||||
delay_ms(100);
|
||||
watch_set_led_color_rgb(0, 0, 0);
|
||||
// It is the tester's responsibility to check the LED color.
|
||||
break;
|
||||
case 'g':
|
||||
watch_set_led_color_rgb(0, 255, 0);
|
||||
delay_ms(100);
|
||||
watch_set_led_color_rgb(0, 0, 0);
|
||||
// It is the tester's responsibility to check the LED color.
|
||||
break;
|
||||
case 'b':
|
||||
watch_set_led_color_rgb(0, 0, 255);
|
||||
delay_ms(100);
|
||||
watch_set_led_color_rgb(0, 0, 0);
|
||||
// It is the tester's responsibility to check the LED color.
|
||||
break;
|
||||
// - [X] Buttons
|
||||
case 'B':
|
||||
// Pass if all three buttons are low
|
||||
pass_if(!gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_LIGHT) && !gpio_get_pin_level(BTN_MODE));
|
||||
break;
|
||||
case 'L':
|
||||
// pass if BTN_LIGHT is high and the other two are low
|
||||
pass_if(gpio_get_pin_level(BTN_LIGHT) && !gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_MODE));
|
||||
break;
|
||||
case 'A':
|
||||
// pass if BTN_ALARM is high and the other two are low
|
||||
pass_if(gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_LIGHT) && !gpio_get_pin_level(BTN_MODE));
|
||||
break;
|
||||
case 'M':
|
||||
// pass if BTN_MODE is high and the other two are low
|
||||
pass_if(gpio_get_pin_level(BTN_MODE) && !gpio_get_pin_level(BTN_ALARM) && !gpio_get_pin_level(BTN_LIGHT));
|
||||
break;
|
||||
|
||||
// - [X] File system
|
||||
case 'F':
|
||||
watch_storage_erase(10);
|
||||
delay_ms(10);
|
||||
watch_storage_write(10, 0, (const char *)"BEEP", 4);
|
||||
watch_storage_sync();
|
||||
watch_storage_read(10, 0, buf, 4);
|
||||
delay_ms(10);
|
||||
// No need to do anything here; comparison with 'beep' happens at next loop invocation.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
10
apps/sensor-watch-pro-test/make/Makefile
Executable file
10
apps/sensor-watch-pro-test/make/Makefile
Executable file
@ -0,0 +1,10 @@
|
||||
TOP = ../../..
|
||||
include $(TOP)/make.mk
|
||||
|
||||
INCLUDES += \
|
||||
-I../
|
||||
|
||||
SRCS += \
|
||||
../app.c
|
||||
|
||||
include $(TOP)/rules.mk
|
@ -12,6 +12,14 @@
|
||||
#define BTN_MODE GPIO(GPIO_PORTA, 31)
|
||||
#define WATCH_BTN_MODE_EIC_CHANNEL 11
|
||||
|
||||
// Temperature Sensor
|
||||
#define TS_ENABLE GPIO(GPIO_PORTB, 23)
|
||||
#define TEMPSENSE GPIO(GPIO_PORTA, 3)
|
||||
|
||||
// Light Sensor
|
||||
#define IR_ENABLE GPIO(GPIO_PORTB, 22)
|
||||
#define IRSENSE GPIO(GPIO_PORTA, 4)
|
||||
|
||||
// Buzzer
|
||||
#define BUZZER GPIO(GPIO_PORTA, 27)
|
||||
#define WATCH_BUZZER_TCC_PINMUX PINMUX_PA27F_TCC0_WO5
|
||||
|
2
make.mk
2
make.mk
@ -223,7 +223,7 @@ ifndef COLOR
|
||||
$(error Set the COLOR variable to RED, BLUE, or GREEN depending on what board you have.)
|
||||
endif
|
||||
|
||||
COLOR_VALID := $(filter $(COLOR),RED BLUE GREEN)
|
||||
COLOR_VALID := $(filter $(COLOR),RED BLUE GREEN PRO)
|
||||
|
||||
ifeq ($(COLOR_VALID),)
|
||||
$(error COLOR must be RED, BLUE, or GREEN)
|
||||
|
304
movement/lib/moonrise/moonrise.c
Normal file
304
movement/lib/moonrise/moonrise.c
Normal file
@ -0,0 +1,304 @@
|
||||
// Compute times of moonrise and moonset at a specified latitude and longitude.
|
||||
//
|
||||
// This software minimizes computational work by performing the full calculation
|
||||
// of the lunar position three times, at the beginning, middle, and end of the
|
||||
// period of interest. Three point interpolation is used to predict the
|
||||
// position for each hour, and the arithmetic mean is used to predict the
|
||||
// half-hour positions.
|
||||
//
|
||||
// The full computational burden is negligible on modern computers, but the
|
||||
// algorithm is effective and still useful for small embedded systems.
|
||||
//
|
||||
// This software was originally adapted to javascript by Stephen R. Schmitt
|
||||
// from a BASIC program from the 'Astronomical Computing' column of Sky &
|
||||
// Telescope, April 1989, page 78.
|
||||
//
|
||||
// Subsequently adapted from Stephen R. Schmitt's javascript to c++ for the
|
||||
// Arduino by Cyrus Rahman.
|
||||
//
|
||||
// Subsequently adapted from Cyrus Rahman's Arduino C++ to C for the Sensor
|
||||
// Watch by hueso, this work is subject to Stephen Schmitt's copyright:
|
||||
//
|
||||
// Copyright 2007 Stephen R. Schmitt
|
||||
// Subsequent work Copyright 2020 Cyrus Rahman
|
||||
// You may use or modify this source code in any way you find useful, provided
|
||||
// that you agree that the author(s) have no warranty, obligations or liability.
|
||||
// You must determine the suitability of this source code for your use.
|
||||
//
|
||||
// Redistributions of this source code must retain this copyright notice.
|
||||
|
||||
#include "moonrise.h"
|
||||
#include <math.h>
|
||||
|
||||
#define K1 15 * (M_PI / 180) * 1.0027379
|
||||
|
||||
// Determine the nearest moon rise or set event previous, and the nearest
|
||||
// moon rise or set event subsequent, to the specified time in seconds since the
|
||||
// Unix epoch (January 1, 1970) and at the specified latitude and longitude in
|
||||
// degrees.
|
||||
//
|
||||
// We look for events from MR_WINDOW/2 hours in the past to MR_WINDOW/2 hours
|
||||
// in the future.
|
||||
MoonRise MoonRise_calculate(double latitude, double longitude, uint32_t t) {
|
||||
MoonRise self = {};
|
||||
skyCoordinates moonPosition[3];
|
||||
double offsetDays;
|
||||
|
||||
self.queryTime = t;
|
||||
offsetDays = julianDate(t) - 2451545L; // Days since Jan 1, 2000, 1200UTC.
|
||||
// Begin testing (MR_WINDOW / 2) hours before requested time.
|
||||
// offsetDays -= (double)MR_WINDOW / (2 * 24) ;
|
||||
|
||||
// Calculate coordinates at start, middle, and end of search period.
|
||||
for (int i = 0; i < 3; i++) {
|
||||
moonPosition[i] = moon(offsetDays + i * (double)MR_WINDOW / (2 * 24));
|
||||
}
|
||||
|
||||
// If the RA wraps around during this period, unwrap it to keep the
|
||||
// sequence smooth for interpolation.
|
||||
if (moonPosition[1].RA <= moonPosition[0].RA)
|
||||
moonPosition[1].RA += 2 * M_PI;
|
||||
if (moonPosition[2].RA <= moonPosition[1].RA)
|
||||
moonPosition[2].RA += 2 * M_PI;
|
||||
|
||||
// Initialize interpolation array.
|
||||
skyCoordinates mpWindow[3];
|
||||
mpWindow[0].RA = moonPosition[0].RA;
|
||||
mpWindow[0].declination = moonPosition[0].declination;
|
||||
mpWindow[0].distance = moonPosition[0].distance;
|
||||
|
||||
for (int k = 0; k < MR_WINDOW; k++) { // Check each interval of search period
|
||||
float ph = (float)(k + 1) / MR_WINDOW;
|
||||
|
||||
mpWindow[2].RA = interpolate(moonPosition[0].RA, moonPosition[1].RA,
|
||||
moonPosition[2].RA, ph);
|
||||
mpWindow[2].declination =
|
||||
interpolate(moonPosition[0].declination, moonPosition[1].declination,
|
||||
moonPosition[2].declination, ph);
|
||||
mpWindow[2].distance = moonPosition[2].distance;
|
||||
|
||||
// Look for moonrise/set events during this interval.
|
||||
{
|
||||
double ha[3], VHz[3];
|
||||
double lSideTime;
|
||||
|
||||
// Get (local_sidereal_time - MR_WINDOW / 2) hours in radians.
|
||||
lSideTime = localSiderealTime(offsetDays, longitude) * 2 * M_PI / 360;
|
||||
|
||||
// Calculate Hour Angle.
|
||||
ha[0] = lSideTime - mpWindow[0].RA + k * K1;
|
||||
ha[2] = lSideTime - mpWindow[2].RA + k * K1 + K1;
|
||||
|
||||
// Hour Angle and declination at half hour.
|
||||
ha[1] = (ha[2] + ha[0]) / 2;
|
||||
mpWindow[1].declination =
|
||||
(mpWindow[2].declination + mpWindow[0].declination) / 2;
|
||||
|
||||
double s = sin(M_PI / 180 * latitude);
|
||||
double c = cos(M_PI / 180 * latitude);
|
||||
|
||||
// refraction + semidiameter at horizon + distance correction
|
||||
double z = cos(M_PI / 180 * (90.567 - 41.685 / mpWindow[0].distance));
|
||||
|
||||
VHz[0] = s * sin(mpWindow[0].declination) +
|
||||
c * cos(mpWindow[0].declination) * cos(ha[0]) - z;
|
||||
VHz[2] = s * sin(mpWindow[2].declination) +
|
||||
c * cos(mpWindow[2].declination) * cos(ha[2]) - z;
|
||||
|
||||
if (signbit(VHz[0]) == signbit(VHz[2]))
|
||||
goto noevent; // No event this hour.
|
||||
|
||||
VHz[1] = s * sin(mpWindow[1].declination) +
|
||||
c * cos(mpWindow[1].declination) * cos(ha[1]) - z;
|
||||
|
||||
double a, b, d, e, time;
|
||||
a = 2 * VHz[2] - 4 * VHz[1] + 2 * VHz[0];
|
||||
b = 4 * VHz[1] - 3 * VHz[0] - VHz[2];
|
||||
d = b * b - 4 * a * VHz[0];
|
||||
|
||||
if (d < 0)
|
||||
goto noevent; // No event this hour.
|
||||
|
||||
d = sqrt(d);
|
||||
e = (-b + d) / (2 * a);
|
||||
if ((e < 0) || (e > 1))
|
||||
e = (-b - d) / (2 * a);
|
||||
time = k + e + 1 / 120; // Time since k=0 of event (in hours).
|
||||
|
||||
// The time we started searching + the time from the start of the search
|
||||
// to the event is the time of the event.
|
||||
uint32_t eventTime;
|
||||
eventTime = self.queryTime + (time) * 60 * 60;
|
||||
|
||||
double hz, nz, dz, az;
|
||||
hz = ha[0] + e * (ha[2] - ha[0]); // Azimuth of the moon at the event.
|
||||
nz = -cos(mpWindow[1].declination) * sin(hz);
|
||||
dz = c * sin(mpWindow[1].declination) -
|
||||
s * cos(mpWindow[1].declination) * cos(hz);
|
||||
az = atan2(nz, dz) / (M_PI / 180);
|
||||
if (az < 0)
|
||||
az += 360;
|
||||
|
||||
// If there is no previously recorded event of this type, save this event.
|
||||
//
|
||||
// If this event is previous to queryTime, and is the nearest event to
|
||||
// queryTime of events of its type previous to queryType, save this event,
|
||||
// replacing the previously recorded event of its type. Events subsequent
|
||||
// to queryTime are treated similarly, although since events are tested in
|
||||
// chronological order no replacements will occur as successive events
|
||||
// will be further from queryTime.
|
||||
//
|
||||
// If this event is subsequent to queryTime and there is an event of its
|
||||
// type previous to queryTime, then there is an event of the other type
|
||||
// between the two events of this event's type. If the event of the other
|
||||
// type is previous to queryTime, then it is the nearest event to
|
||||
// queryTime that is previous to queryTime. In this case save the current
|
||||
// event, replacing the previously recorded event of its type. Otherwise
|
||||
// discard the current event.
|
||||
//
|
||||
if ((VHz[0] < 0) && (VHz[2] > 0)) {
|
||||
if (!self.hasRise ||
|
||||
((self.riseTime < self.queryTime) == (eventTime < self.queryTime) &&
|
||||
(self.riseTime - self.queryTime) > (eventTime - self.queryTime)) ||
|
||||
((self.riseTime < self.queryTime) != (eventTime < self.queryTime) &&
|
||||
(self.hasSet && (self.riseTime < self.queryTime) ==
|
||||
(self.setTime < self.queryTime)))) {
|
||||
self.riseTime = eventTime;
|
||||
self.riseAz = az;
|
||||
self.hasRise = true;
|
||||
}
|
||||
}
|
||||
if ((VHz[0] > 0) && (VHz[2] < 0)) {
|
||||
if (!self.hasSet ||
|
||||
((self.setTime < self.queryTime) == (eventTime < self.queryTime) &&
|
||||
(self.setTime - self.queryTime) > (eventTime - self.queryTime)) ||
|
||||
((self.setTime < self.queryTime) != (eventTime < self.queryTime) &&
|
||||
(self.hasRise && (self.setTime < self.queryTime) ==
|
||||
(self.riseTime < self.queryTime)))) {
|
||||
self.setTime = eventTime;
|
||||
self.setAz = az;
|
||||
self.hasSet = true;
|
||||
}
|
||||
}
|
||||
|
||||
noevent:
|
||||
// There are obscure cases in the polar regions that require extra logic.
|
||||
if (!self.hasRise && !self.hasSet)
|
||||
self.isVisible = !signbit(VHz[2]);
|
||||
else if (self.hasRise && !self.hasSet)
|
||||
self.isVisible = (self.queryTime > self.riseTime);
|
||||
else if (!self.hasRise && self.hasSet)
|
||||
self.isVisible = (self.queryTime < self.setTime);
|
||||
else
|
||||
self.isVisible =
|
||||
((self.riseTime < self.setTime && self.riseTime < self.queryTime &&
|
||||
self.setTime > self.queryTime) ||
|
||||
(self.riseTime > self.setTime && (self.riseTime < self.queryTime ||
|
||||
self.setTime > self.queryTime)));
|
||||
}
|
||||
|
||||
if (self.hasSet && self.hasRise)
|
||||
break;
|
||||
|
||||
mpWindow[0] = mpWindow[2]; // Advance to next interval.
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// Moon position using fundamental arguments
|
||||
// (Van Flandern & Pulkkinen, 1979)
|
||||
skyCoordinates moon(double dayOffset) {
|
||||
double l = 0.606434 + 0.03660110129 * dayOffset;
|
||||
double m = 0.374897 + 0.03629164709 * dayOffset;
|
||||
double f = 0.259091 + 0.03674819520 * dayOffset;
|
||||
double d = 0.827362 + 0.03386319198 * dayOffset;
|
||||
double n = 0.347343 - 0.00014709391 * dayOffset;
|
||||
double g = 0.993126 + 0.00273777850 * dayOffset;
|
||||
|
||||
l = 2 * M_PI * (l - floor(l));
|
||||
m = 2 * M_PI * (m - floor(m));
|
||||
f = 2 * M_PI * (f - floor(f));
|
||||
d = 2 * M_PI * (d - floor(d));
|
||||
n = 2 * M_PI * (n - floor(n));
|
||||
g = 2 * M_PI * (g - floor(g));
|
||||
|
||||
double v, u, w;
|
||||
v = 0.39558 * sin(f + n)
|
||||
+ 0.08200 * sin(f)
|
||||
+ 0.03257 * sin(m - f - n)
|
||||
+ 0.01092 * sin(m + f + n)
|
||||
+ 0.00666 * sin(m - f)
|
||||
- 0.00644 * sin(m + f - 2*d + n)
|
||||
- 0.00331 * sin(f - 2*d + n)
|
||||
- 0.00304 * sin(f - 2*d)
|
||||
- 0.00240 * sin(m - f - 2*d - n)
|
||||
+ 0.00226 * sin(m + f)
|
||||
- 0.00108 * sin(m + f - 2*d)
|
||||
- 0.00079 * sin(f - n)
|
||||
+ 0.00078 * sin(f + 2*d + n);
|
||||
|
||||
u = 1
|
||||
- 0.10828 * cos(m)
|
||||
- 0.01880 * cos(m - 2*d)
|
||||
- 0.01479 * cos(2*d)
|
||||
+ 0.00181 * cos(2*m - 2*d)
|
||||
- 0.00147 * cos(2*m)
|
||||
- 0.00105 * cos(2*d - g)
|
||||
- 0.00075 * cos(m - 2*d + g);
|
||||
|
||||
w = 0.10478 * sin(m)
|
||||
- 0.04105 * sin(2*f + 2*n)
|
||||
- 0.02130 * sin(m - 2*d)
|
||||
- 0.01779 * sin(2*f + n)
|
||||
+ 0.01774 * sin(n)
|
||||
+ 0.00987 * sin(2*d)
|
||||
- 0.00338 * sin(m - 2*f - 2*n)
|
||||
- 0.00309 * sin(g)
|
||||
- 0.00190 * sin(2*f)
|
||||
- 0.00144 * sin(m + n)
|
||||
- 0.00144 * sin(m - 2*f - n)
|
||||
- 0.00113 * sin(m + 2*f + 2*n)
|
||||
- 0.00094 * sin(m - 2*d + g)
|
||||
- 0.00092 * sin(2*m - 2*d);
|
||||
|
||||
double s;
|
||||
skyCoordinates sc;
|
||||
s = w / sqrt(u - v*v);
|
||||
sc.RA = l + atan(s / sqrt(1 - s*s)); // Right ascension
|
||||
|
||||
s = v / sqrt(u);
|
||||
sc.declination = atan(s / sqrt(1 - s*s)); // Declination
|
||||
sc.distance = 60.40974 * sqrt(u); // Distance
|
||||
return(sc);
|
||||
}
|
||||
|
||||
// 3-point interpolation
|
||||
double interpolate(double f0, double f1, double f2, double p) {
|
||||
double a = f1 - f0;
|
||||
double b = f2 - f1 - a;
|
||||
return(f0 + p * (2*a + b * (2*p - 1)));
|
||||
}
|
||||
|
||||
// Determine Julian date from Unix time.
|
||||
// Provides marginally accurate results with Arduino 4-byte double.
|
||||
double julianDate(uint32_t t) {
|
||||
return (t / 86400.0L + 2440587.5);
|
||||
}
|
||||
|
||||
// Local Sidereal Time
|
||||
// Provides local sidereal time in degrees, requires longitude in degrees
|
||||
// and time in fractional Julian days since Jan 1, 2000, 1200UTC (e.g. the
|
||||
// Julian date - 2451545).
|
||||
// cf. USNO Astronomical Almanac and
|
||||
// https://astronomy.stackexchange.com/questions/24859/local-sidereal-time
|
||||
double localSiderealTime(double offsetDays, double longitude) {
|
||||
double lSideTime = (15.0L * (6.697374558L + 0.06570982441908L * offsetDays +
|
||||
remainder(offsetDays, 1) * 24 + 12 +
|
||||
0.000026 * (offsetDays / 36525) * (offsetDays / 36525))
|
||||
+ longitude) / 360;
|
||||
lSideTime -= floor(lSideTime);
|
||||
lSideTime *= 360; // Convert to degrees.
|
||||
return(lSideTime);
|
||||
}
|
||||
|
43
movement/lib/moonrise/moonrise.h
Normal file
43
movement/lib/moonrise/moonrise.h
Normal file
@ -0,0 +1,43 @@
|
||||
#ifndef MoonRise_h
|
||||
#define MoonRise_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Size of event search window in hours.
|
||||
// Events further away from the search time than MR_WINDOW/2 will not be
|
||||
// found. At higher latitudes the moon rise/set intervals become larger, so if
|
||||
// you want to find the nearest events this will need to increase. Larger
|
||||
// windows will increase interpolation error. Useful values are probably from
|
||||
// 12 - 48 but will depend upon your application.
|
||||
|
||||
#define MR_WINDOW 48 // Even integer
|
||||
|
||||
typedef struct {
|
||||
double RA; // Right ascension
|
||||
double declination; // Declination
|
||||
double distance; // Distance
|
||||
} skyCoordinates;
|
||||
|
||||
typedef struct {
|
||||
uint32_t queryTime;
|
||||
uint32_t riseTime;
|
||||
uint32_t setTime;
|
||||
float riseAz;
|
||||
float setAz;
|
||||
bool hasRise;
|
||||
bool hasSet;
|
||||
bool isVisible;
|
||||
} MoonRise;
|
||||
|
||||
MoonRise MoonRise_calculate(double latitude, double longitude, uint32_t t);
|
||||
|
||||
// private:
|
||||
void testMoonRiseSet(MoonRise *self, int i, double offsetDays, double latitude,
|
||||
double longitude, skyCoordinates *mp);
|
||||
skyCoordinates moon(double dayOffset);
|
||||
double interpolate(double f0, double f1, double f2, double p);
|
||||
double julianDate(uint32_t t);
|
||||
double localSiderealTime(double offsetDays, double longitude);
|
||||
|
||||
#endif
|
3704
movement/lib/smallchesslib/smallchesslib.h
Normal file
3704
movement/lib/smallchesslib/smallchesslib.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -24,6 +24,8 @@ INCLUDES += \
|
||||
-I../lib/vsop87/ \
|
||||
-I../lib/astrolib/ \
|
||||
-I../lib/morsecalc/ \
|
||||
-I../lib/smallchesslib/ \
|
||||
-I../lib/moonrise/ \
|
||||
|
||||
# If you add any other source files you wish to compile, add them after ../app.c
|
||||
# Note that you will need to add a backslash at the end of any line you wish to continue, i.e.
|
||||
@ -39,6 +41,7 @@ SRCS += \
|
||||
../lib/TOTP/TOTP.c \
|
||||
../lib/base32/base32.c \
|
||||
../lib/sunriset/sunriset.c \
|
||||
../lib/moonrise/moonrise.c \
|
||||
../lib/vsop87/vsop87a_milli.c \
|
||||
../lib/astrolib/astrolib.c \
|
||||
../lib/morsecalc/calc.c \
|
||||
@ -119,6 +122,7 @@ SRCS += \
|
||||
../watch_faces/complication/toss_up_face.c \
|
||||
../watch_faces/complication/geomancy_face.c \
|
||||
../watch_faces/clock/simple_clock_bin_led_face.c \
|
||||
../watch_faces/complication/menstrual_cycle_face.c \
|
||||
../watch_faces/complication/flashlight_face.c \
|
||||
../watch_faces/clock/decimal_time_face.c \
|
||||
../watch_faces/clock/wyoscan_face.c \
|
||||
@ -129,7 +133,10 @@ SRCS += \
|
||||
../watch_faces/complication/couch_to_5k_face.c \
|
||||
../watch_faces/clock/minute_repeater_decimal_face.c \
|
||||
../watch_faces/complication/tuning_tones_face.c \
|
||||
../watch_faces/sensor/minmax_face.c \
|
||||
../watch_faces/complication/kitchen_conversions_face.c \
|
||||
../watch_faces/complication/butterfly_game_face.c \
|
||||
../watch_faces/complication/wareki_face.c \
|
||||
../watch_faces/complication/wordle_face.c \
|
||||
../watch_faces/complication/endless_runner_face.c \
|
||||
../watch_faces/complication/periodic_face.c \
|
||||
@ -141,6 +148,10 @@ SRCS += \
|
||||
../watch_faces/complication/simple_calculator_face.c \
|
||||
../watch_faces/sensor/alarm_thermometer_face.c \
|
||||
../watch_faces/demo/beeps_face.c \
|
||||
../watch_faces/sensor/accel_interrupt_count_face.c \
|
||||
../watch_faces/complication/metronome_face.c \
|
||||
../watch_faces/complication/smallchess_face.c \
|
||||
../watch_faces/complication/moonrise_face.c \
|
||||
# New watch faces go above this line.
|
||||
|
||||
# Leave this line at the bottom of the file; it has all the targets for making your project.
|
||||
|
@ -94,6 +94,7 @@
|
||||
#include "geomancy_face.h"
|
||||
#include "dual_timer_face.h"
|
||||
#include "simple_clock_bin_led_face.h"
|
||||
#include "menstrual_cycle_face.h"
|
||||
#include "flashlight_face.h"
|
||||
#include "decimal_time_face.h"
|
||||
#include "wyoscan_face.h"
|
||||
@ -104,7 +105,10 @@
|
||||
#include "couch_to_5k_face.h"
|
||||
#include "minute_repeater_decimal_face.h"
|
||||
#include "tuning_tones_face.h"
|
||||
#include "minmax_face.h"
|
||||
#include "kitchen_conversions_face.h"
|
||||
#include "butterfly_game_face.h"
|
||||
#include "wareki_face.h"
|
||||
#include "wordle_face.h"
|
||||
#include "endless_runner_face.h"
|
||||
#include "periodic_face.h"
|
||||
@ -116,6 +120,10 @@
|
||||
#include "simple_calculator_face.h"
|
||||
#include "alarm_thermometer_face.h"
|
||||
#include "beeps_face.h"
|
||||
#include "accel_interrupt_count_face.h"
|
||||
#include "metronome_face.h"
|
||||
#include "smallchess_face.h"
|
||||
#include "moonrise_face.h"
|
||||
// New includes go above this line.
|
||||
|
||||
#endif // MOVEMENT_FACES_H_
|
||||
|
467
movement/watch_faces/complication/butterfly_game_face.c
Normal file
467
movement/watch_faces/complication/butterfly_game_face.c
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Hugo Chargois
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
// Emulator only: need time() to seed the random number generator
|
||||
#if __EMSCRIPTEN__
|
||||
#include <time.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "butterfly_game_face.h"
|
||||
|
||||
static char butterfly_shapes[][3] = {
|
||||
"[]", "][", "25", "52", "9e", "e9", "6a", "a6", "3E", "E3", "00", "HH", "88"
|
||||
};
|
||||
|
||||
static int8_t single_beep[] = {BUZZER_NOTE_A7, 4, 0};
|
||||
static int8_t round_win_melody[] = {
|
||||
BUZZER_NOTE_C6, 4,
|
||||
BUZZER_NOTE_E6, 4,
|
||||
BUZZER_NOTE_G6, 4,
|
||||
BUZZER_NOTE_C7, 12,
|
||||
0};
|
||||
static int8_t round_lose_melody[] = {
|
||||
BUZZER_NOTE_E6, 4,
|
||||
BUZZER_NOTE_F6, 4,
|
||||
BUZZER_NOTE_D6SHARP_E6FLAT, 4,
|
||||
BUZZER_NOTE_C6, 12,
|
||||
0};
|
||||
static int8_t game_win_melody[] = {
|
||||
BUZZER_NOTE_G6, 4,
|
||||
BUZZER_NOTE_A6, 4,
|
||||
BUZZER_NOTE_B6, 4,
|
||||
BUZZER_NOTE_C7, 12,
|
||||
BUZZER_NOTE_D7, 4,
|
||||
BUZZER_NOTE_E7, 4,
|
||||
BUZZER_NOTE_D7, 4,
|
||||
BUZZER_NOTE_C7, 12,
|
||||
BUZZER_NOTE_B6, 4,
|
||||
BUZZER_NOTE_C7, 4,
|
||||
BUZZER_NOTE_D7, 4,
|
||||
BUZZER_NOTE_G7, 24,
|
||||
0};
|
||||
|
||||
#define NUM_SHAPES (sizeof(butterfly_shapes) / sizeof(butterfly_shapes[0]))
|
||||
|
||||
#define POS_LEFT 4
|
||||
#define POS_CENTER 6
|
||||
#define POS_RIGHT 8
|
||||
|
||||
#define TICK_FREQ 8
|
||||
#define TICKS_PER_SHAPE 8
|
||||
|
||||
#define PLAYER_1 0
|
||||
#define PLAYER_2 1
|
||||
|
||||
|
||||
// returns a random integer r with 0 <= r < max
|
||||
static inline uint8_t _get_rand(uint8_t max) {
|
||||
#if __EMSCRIPTEN__
|
||||
return rand() % max;
|
||||
#else
|
||||
return arc4random_uniform(max);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* The game is built with a simple state machine where each state is called a
|
||||
* "screen". Each screen can draw on the display and handles events, including
|
||||
* the "activate" event, which is repurposed and sent whenever we move from one
|
||||
* screen to another via the _transition_to function. Basically it's a mini
|
||||
* movement inside movement.
|
||||
*/
|
||||
typedef bool (*screen_fn_t)(movement_event_t, butterfly_game_state_t*);
|
||||
|
||||
static screen_fn_t cur_screen_fn;
|
||||
|
||||
static bool _transition_to(screen_fn_t sf, butterfly_game_state_t *state) {
|
||||
movement_event_t ev = {EVENT_ACTIVATE, 0};
|
||||
cur_screen_fn = sf;
|
||||
return sf(ev, state);
|
||||
}
|
||||
|
||||
static uint8_t _pick_wrong_shape(butterfly_game_state_t *state, bool skip_wrong_shape) {
|
||||
if (!skip_wrong_shape) {
|
||||
// easy case, we only need to skip over 1 shape: the correct shape
|
||||
uint8_t r = _get_rand(NUM_SHAPES-1);
|
||||
if (r >= state->correct_shape) {
|
||||
r++;
|
||||
}
|
||||
return r;
|
||||
} else {
|
||||
// a bit more complex, we need to skip over 2 shapes: the correct one
|
||||
// and the current wrong one
|
||||
uint8_t r = _get_rand(NUM_SHAPES-2);
|
||||
uint8_t i1, i2; // the 2 indices to skip over, with i1 < i2
|
||||
if (state->correct_shape < state->current_shape) {
|
||||
i1 = state->correct_shape;
|
||||
i2 = state->current_shape;
|
||||
} else {
|
||||
i1 = state->current_shape;
|
||||
i2 = state->correct_shape;
|
||||
}
|
||||
|
||||
if (r >= i1) {
|
||||
r++;
|
||||
}
|
||||
if (r >= i2) {
|
||||
r++;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
static void _display_shape(uint8_t shape, uint8_t pos) {
|
||||
watch_display_string(butterfly_shapes[shape], pos);
|
||||
}
|
||||
|
||||
static void _display_scores(butterfly_game_state_t *state) {
|
||||
char buf[] = " ";
|
||||
buf[0] = '0' + state->score_p1;
|
||||
watch_display_string(buf, 0);
|
||||
buf[0] = '0' + state->score_p2;
|
||||
watch_display_string(buf, 3);
|
||||
}
|
||||
|
||||
static void _play_sound(butterfly_game_state_t *state, int8_t *seq) {
|
||||
if (state->sound) watch_buzzer_play_sequence(seq, NULL);
|
||||
}
|
||||
|
||||
static bool _round_start_screen(movement_event_t event, butterfly_game_state_t *state);
|
||||
static bool _reset_screen(movement_event_t event, butterfly_game_state_t *state);
|
||||
|
||||
static bool _game_win_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
state->ctr = 4 * TICK_FREQ;
|
||||
watch_clear_display();
|
||||
|
||||
if (state->score_p1 >= state->goal_score) {
|
||||
watch_display_string("pl1 wins", 0);
|
||||
} else {
|
||||
watch_display_string("pl2 wins", 0);
|
||||
}
|
||||
_play_sound(state, game_win_melody);
|
||||
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
state->ctr--;
|
||||
if (state->ctr == 0) {
|
||||
return _transition_to(_reset_screen, state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _round_win_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
state->ctr = TICK_FREQ;
|
||||
|
||||
if (state->round_winner == PLAYER_1) {
|
||||
state->score_p1++;
|
||||
} else {
|
||||
state->score_p2++;
|
||||
}
|
||||
|
||||
watch_clear_display();
|
||||
_display_scores(state);
|
||||
_display_shape(state->correct_shape, state->round_winner == PLAYER_1 ? POS_LEFT : POS_RIGHT);
|
||||
_play_sound(state, round_win_melody);
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
state->ctr--;
|
||||
if (state->ctr == 0) {
|
||||
if (state->score_p1 >= state->goal_score || state->score_p2 >= state->goal_score) {
|
||||
return _transition_to(_game_win_screen, state);
|
||||
}
|
||||
return _transition_to(_round_start_screen, state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _round_lose_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
state->ctr = TICK_FREQ;
|
||||
|
||||
if (state->round_winner == PLAYER_1) {
|
||||
if (state->score_p2 > 0) state->score_p2--;
|
||||
} else {
|
||||
if (state->score_p1 > 0) state->score_p1--;
|
||||
}
|
||||
|
||||
_display_shape(state->correct_shape, POS_CENTER);
|
||||
_play_sound(state, round_lose_melody);
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
if (--state->ctr == 0) {
|
||||
return _transition_to(_round_start_screen, state);
|
||||
}
|
||||
_display_shape(state->ctr%2 ? state->correct_shape : state->current_shape, POS_CENTER);
|
||||
break;
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _correct_shape_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
_display_shape(state->correct_shape, POS_CENTER);
|
||||
_play_sound(state, single_beep);
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
state->round_winner = PLAYER_1;
|
||||
return _transition_to(_round_win_screen, state);
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
state->round_winner = PLAYER_2;
|
||||
return _transition_to(_round_win_screen, state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _wrong_shape_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
state->ctr = TICKS_PER_SHAPE;
|
||||
state->current_shape = _pick_wrong_shape(state, true);
|
||||
_display_shape(state->current_shape, POS_CENTER);
|
||||
_play_sound(state, single_beep);
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
if (--state->ctr == 0) {
|
||||
if (--state->show_correct_shape_after == 0) {
|
||||
return _transition_to(_correct_shape_screen, state);
|
||||
}
|
||||
return _transition_to(_wrong_shape_screen, state);
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
state->round_winner = PLAYER_2;
|
||||
return _transition_to(_round_lose_screen, state);
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
state->round_winner = PLAYER_1;
|
||||
return _transition_to(_round_lose_screen, state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _first_wrong_shape_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
// the first of the wrong shape screens is a bit different than the next
|
||||
// ones, for 2 reasons:
|
||||
// * we can pick any shape except one (the correct shape); whereas in the
|
||||
// subsequent wrong shape screens, we also must not pick the same wrong
|
||||
// shape as the last
|
||||
// * we don't act on the light/alarm button events; they would normally be
|
||||
// a fail in a wrong shape screen, but in this case it may just be that
|
||||
// the 2 players acknowledge the picked shape (in the previous screen) in
|
||||
// quick succession, and we don't want the second player to immediately
|
||||
// fail.
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
state->ctr = TICKS_PER_SHAPE;
|
||||
state->current_shape = _pick_wrong_shape(state, false);
|
||||
_display_shape(state->current_shape, POS_CENTER);
|
||||
_play_sound(state, single_beep);
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
if (--state->ctr == 0) {
|
||||
return _transition_to(_wrong_shape_screen, state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _round_start_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
state->correct_shape = _get_rand(NUM_SHAPES);
|
||||
state->show_correct_shape_after = _get_rand(10) + 1;
|
||||
watch_display_string(" - -", 0);
|
||||
_display_scores(state);
|
||||
_display_shape(state->correct_shape, POS_CENTER);
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
watch_display_string(" ", 4);
|
||||
return _transition_to(_first_wrong_shape_screen, state);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _goal_select_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
watch_clear_display();
|
||||
state->goal_score = 6;
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
return _transition_to(_round_start_screen, state);
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
state->goal_score += 3;
|
||||
if (state->goal_score > 9) state->goal_score = 3;
|
||||
break;
|
||||
}
|
||||
|
||||
char buf[] = "GOaL ";
|
||||
buf[5] = '0' + state->goal_score;
|
||||
watch_display_string(buf, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _reset_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
(void) event;
|
||||
|
||||
state->score_p1 = 0;
|
||||
state->score_p2 = 0;
|
||||
|
||||
return _transition_to(_goal_select_screen, state);
|
||||
}
|
||||
|
||||
static bool _continue_select_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
watch_clear_display();
|
||||
|
||||
// no game in progress, start a new game
|
||||
if (state->score_p1 == 0 && state->score_p2 == 0) {
|
||||
return _transition_to(_goal_select_screen, state);
|
||||
}
|
||||
|
||||
state->cont = false;
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
if (state->cont) {
|
||||
return _transition_to(_round_start_screen, state);
|
||||
}
|
||||
return _transition_to(_reset_screen, state);
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
state->cont = !state->cont;
|
||||
break;
|
||||
}
|
||||
|
||||
if (state->cont) {
|
||||
watch_display_string("Cont y", 4);
|
||||
} else {
|
||||
watch_display_string("Cont n", 4);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _sound_select_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
watch_clear_display();
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
return _transition_to(_continue_select_screen, state);
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
state->sound = !state->sound;
|
||||
break;
|
||||
}
|
||||
|
||||
if (state->sound) {
|
||||
watch_display_string("snd y", 5);
|
||||
} else {
|
||||
watch_display_string("snd n", 5);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _splash_screen(movement_event_t event, butterfly_game_state_t *state) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
state->ctr = TICK_FREQ;
|
||||
|
||||
watch_clear_display();
|
||||
watch_display_string("Btrfly", 4);
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
return _transition_to(_sound_select_screen, state);
|
||||
case EVENT_TICK:
|
||||
if (--state->ctr == 0) {
|
||||
return _transition_to(_sound_select_screen, state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void butterfly_game_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) settings;
|
||||
(void) watch_face_index;
|
||||
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(butterfly_game_state_t));
|
||||
memset(*context_ptr, 0, sizeof(butterfly_game_state_t));
|
||||
// Do any one-time tasks in here; the inside of this conditional happens only at boot.
|
||||
}
|
||||
// Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep.
|
||||
#if __EMSCRIPTEN__
|
||||
// simulator only: seed the random number generator
|
||||
time_t t;
|
||||
srand((unsigned) time(&t));
|
||||
#endif
|
||||
}
|
||||
|
||||
void butterfly_game_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
|
||||
movement_request_tick_frequency(TICK_FREQ);
|
||||
}
|
||||
|
||||
bool butterfly_game_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
butterfly_game_state_t *state = (butterfly_game_state_t *)context;
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
return _transition_to(_splash_screen, state);
|
||||
case EVENT_TICK:
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
return (*cur_screen_fn)(event, state);
|
||||
case EVENT_TIMEOUT:
|
||||
movement_move_to_face(0);
|
||||
return true;
|
||||
default:
|
||||
return movement_default_loop_handler(event, settings);
|
||||
}
|
||||
}
|
||||
|
||||
void butterfly_game_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
|
||||
// handle any cleanup before your watch face goes off-screen.
|
||||
}
|
||||
|
125
movement/watch_faces/complication/butterfly_game_face.h
Normal file
125
movement/watch_faces/complication/butterfly_game_face.h
Normal file
@ -0,0 +1,125 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Hugo Chargois
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BUTTERFLY_GAME_FACE_H_
|
||||
#define BUTTERFLY_GAME_FACE_H_
|
||||
|
||||
#include "movement.h"
|
||||
|
||||
/*
|
||||
* BUTTERFLY
|
||||
*
|
||||
* A GAME OF SHAPE RECOGNITION AND QUICK REFLEXES FOR 2 PLAYERS
|
||||
*
|
||||
* Setup
|
||||
* =====
|
||||
*
|
||||
* The game is played by 2 players, each using a distinct button:
|
||||
* - player 1 plays with the LIGHT (upper left) button
|
||||
* - player 2 plays with the ALARM (lower right) button
|
||||
*
|
||||
* To play, both players need a firm grip on the watch. A suggested method is to
|
||||
* face each other, remove the watch from the wrist, and position it sideways
|
||||
* between you. Hold one side of the strap in your preferred hand (right or
|
||||
* left) and use your thumb to play.
|
||||
*
|
||||
* Start of the game
|
||||
* =================
|
||||
*
|
||||
* After the splash screen (BtrFly) is shown, the game proceeds through a couple
|
||||
* configuration screens. Use ALARM to cycle through the possible values, and
|
||||
* LIGHT to validate and move to the next screen.
|
||||
*
|
||||
* The configuration options are:
|
||||
*
|
||||
* - snd y/n Toggle sound effects on or off
|
||||
* - goal 3/6/9 Choose to play a game of 3, 6 or 9 points
|
||||
* - cont y/n Decide to continue an unfinished game or start a new one
|
||||
* (this option appears only if a game is in progress)
|
||||
*
|
||||
* Rules
|
||||
* =====
|
||||
*
|
||||
* Prior to each round, a symmetrical shape composed of 2 characters is shown in
|
||||
* the center of the screen. This shape, representing a butterfly's wings, is
|
||||
* randomly chosen from a set of a dozen or so possible shapes. For example:
|
||||
*
|
||||
* ][
|
||||
*
|
||||
* Memorize this shape! Your objective in the round will be to "catch" this
|
||||
* "butterfly" by pressing your button before your opponent does.
|
||||
*
|
||||
* Once you believe you've memorized the shape, press your button. The round
|
||||
* officially begins as soon as either player presses their button.
|
||||
*
|
||||
* Various "butterflies" will then appear on the screen, one after the other.
|
||||
* The fastest player to press their button when the correct butterfly is shown
|
||||
* wins the round. However, if a player presses their button when an incorrect
|
||||
* butterfly is shown, they immediately lose the round.
|
||||
*
|
||||
* Scoring
|
||||
* =======
|
||||
*
|
||||
* The scores are displayed at the top of the screen at all times.
|
||||
*
|
||||
* When a round is won by a player, their score increases by one. When a round
|
||||
* is lost by a player, their score decreases by one; unless they have a score
|
||||
* of 0, in which case it remains unchanged.
|
||||
*
|
||||
* The game ends when a player reaches the set point goal (3, 6 or 9 points).
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
bool cont : 1; // continue
|
||||
bool sound : 1;
|
||||
uint8_t goal_score : 4;
|
||||
|
||||
// a generic ctr used by multiple states to display themselves for multiple frames
|
||||
uint8_t ctr : 6;
|
||||
|
||||
uint8_t correct_shape : 5;
|
||||
uint8_t current_shape : 5;
|
||||
uint8_t show_correct_shape_after : 5;
|
||||
uint8_t round_winner : 1;
|
||||
|
||||
uint8_t score_p1 : 5;
|
||||
uint8_t score_p2 : 5;
|
||||
} butterfly_game_state_t;
|
||||
|
||||
void butterfly_game_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void butterfly_game_face_activate(movement_settings_t *settings, void *context);
|
||||
bool butterfly_game_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void butterfly_game_face_resign(movement_settings_t *settings, void *context);
|
||||
|
||||
#define butterfly_game_face ((const watch_face_t){ \
|
||||
butterfly_game_face_setup, \
|
||||
butterfly_game_face_activate, \
|
||||
butterfly_game_face_loop, \
|
||||
butterfly_game_face_resign, \
|
||||
NULL, \
|
||||
})
|
||||
|
||||
#endif // BUTTERFLY_GAME_FACE_H_
|
||||
|
472
movement/watch_faces/complication/menstrual_cycle_face.c
Normal file
472
movement/watch_faces/complication/menstrual_cycle_face.c
Normal file
@ -0,0 +1,472 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Joseph Borne Komosa | @jokomo24
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
* Menstrual Cycle Face
|
||||
*
|
||||
* Background:
|
||||
*
|
||||
* I discovered the Casio F-91W through my partner, appreciated the retro aesthetic of the watch,
|
||||
* and got one for myself. Soon afterward I discovered the Sensor Watch project and ordered two boards!
|
||||
* I introduced the Sensor Watch to my partner who inquired whether she could track her menstrual cycle.
|
||||
* So I decided to implement a menstrual cycle watch face that also calculates the peak fertility window
|
||||
* using The Calendar Method. While this information may be useful when attempting to achieve or avoid
|
||||
* pregnancy, it is important to understand that these are rough estimates at best.
|
||||
*
|
||||
* How to use:
|
||||
*
|
||||
* 1. To begin tracking, go to 'Last Period' page and toggle the alarm button to the number of days since
|
||||
* the last, most recent, period and hold the alarm button to enter. This will perform the following actions:
|
||||
* - Store the corresponding date as the 'first' period in order to calculate the total_days_tracked.
|
||||
* - Turn on the Signal Indicator to signify that tracking has been activated.
|
||||
* - Deactivate this page and instead show the ticking animation.
|
||||
* - Adjust the days left in the 'Period in <num> Days' page accordingly.
|
||||
* - Activate the 'Period Is Here' page and no longer display 'NA'. To prevent accidental user entry,
|
||||
* the page will display the ticking animation until ten days have passed since the date of the last
|
||||
* period entered.
|
||||
* - Activate the 'Peak Fertility' page to begin showing the estimated window,
|
||||
* as well as display the Alarm Indicator, on this page and on the main 'Period in <num> Days' page,
|
||||
* whenever the current date falls within the Peak Fertility Window.
|
||||
*
|
||||
* 2. Toggle and enter 'y' in the 'Period Is Here' page on the day of every sequential period afterward.
|
||||
* DO NOT FORGET TO DO SO!
|
||||
* - If forgotten, the data will become inaccurate and tracking will need to be reset! -> (FIXME, allow one to enter a 'missed' period using the 'Last Period' page).
|
||||
* This will perform the following actions:
|
||||
* - Calculate this completed cycle's length and reevaluate the shortest and longest cycle variables.
|
||||
* - Increment total_cycles by one.
|
||||
* - Recalculate and save the average cycle for 'Average Cycle' page.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "menstrual_cycle_face.h"
|
||||
#include "watch.h"
|
||||
#include "watch_utility.h"
|
||||
|
||||
#define TYPICAL_AVG_CYC 28
|
||||
#define SECONDS_PER_DAY 86400
|
||||
|
||||
#define MENSTRUAL_CYCLE_FACE_NUM_PAGES (6)
|
||||
enum {
|
||||
period_in_num_days,
|
||||
average_cycle,
|
||||
peak_fertility_window,
|
||||
period_is_here,
|
||||
first_period,
|
||||
reset,
|
||||
} page_titles_e;
|
||||
const char menstrual_cycle_face_titles[MENSTRUAL_CYCLE_FACE_NUM_PAGES][11] = {
|
||||
"Prin day", // Period In <num> Days: Estimated days till the next period occurs
|
||||
"Av cycle ", // Average Cycle: The average number of days estimated per cycle
|
||||
"Peak Fert ", // Peak Fertility Window: The first and last day of month (displayed top & bottom right, respectively, once tracking) for the estimated window of fertility
|
||||
"Prishere ", // Period Is Here: Toggle and enter 'y' on the day the actual period occurs to improve Avg and Fert estimations
|
||||
"Last Per ", // Last Period: Enter the number of days since the last period to begin tracking from that corresponding date by storing it as the 'first'
|
||||
" Reset ", // Reset: Toggle and enter 'y' to reset tracking data
|
||||
};
|
||||
|
||||
/* Beep function */
|
||||
static inline void beep(movement_settings_t *settings) {
|
||||
if (settings->bit.button_should_sound)
|
||||
watch_buzzer_play_note(BUZZER_NOTE_E8, 75);
|
||||
}
|
||||
|
||||
// Calculate the total number of days for which menstrual cycle tracking has been active
|
||||
static inline uint32_t total_days_tracked(menstrual_cycle_state_t *state) {
|
||||
|
||||
// If tracking has not yet been activated, return 0
|
||||
if (!(state->dates.reg))
|
||||
return 0;
|
||||
|
||||
// Otherwise, set the start date to the first day of the first tracked cycle
|
||||
watch_date_time date_time_start;
|
||||
date_time_start.unit.second = 0;
|
||||
date_time_start.unit.minute = 0;
|
||||
date_time_start.unit.hour = 0;
|
||||
date_time_start.unit.day = state->dates.bit.first_day;
|
||||
date_time_start.unit.month = state->dates.bit.first_month;
|
||||
date_time_start.unit.year = state->dates.bit.first_year;
|
||||
|
||||
// Get the current date and time
|
||||
watch_date_time date_time_now = watch_rtc_get_date_time();
|
||||
|
||||
// Convert the start date and current date to Unix time
|
||||
uint32_t unix_start = watch_utility_date_time_to_unix_time(date_time_start, state->utc_offset);
|
||||
uint32_t unix_now = watch_utility_date_time_to_unix_time(date_time_now, state->utc_offset);
|
||||
|
||||
// Calculate the total number of days and return it
|
||||
return (unix_now - unix_start) / SECONDS_PER_DAY;
|
||||
}
|
||||
|
||||
// Calculate the number of days until the next menstrual period
|
||||
static inline int8_t days_till_period(menstrual_cycle_state_t *state) {
|
||||
|
||||
// Calculate the number of days left until the next period based on the average cycle length and the number of cycles tracked
|
||||
int8_t days_left = (state->cycles.bit.average_cycle * (state->cycles.bit.total_cycles + 1)) - total_days_tracked(state);
|
||||
|
||||
// If the result is negative, return 0 (i.e., the period is expected to start today or has already started)
|
||||
return (days_left < 0) ? 0 : days_left;
|
||||
}
|
||||
|
||||
static inline void reset_tracking(menstrual_cycle_state_t *state) {
|
||||
|
||||
state->dates.bit.first_day = 0;
|
||||
state->dates.bit.first_month = 0;
|
||||
state->dates.bit.first_year = 0;
|
||||
|
||||
state->dates.bit.prev_day = 0;
|
||||
state->dates.bit.prev_month = 0;
|
||||
state->dates.bit.prev_year = 0;
|
||||
|
||||
state->cycles.bit.shortest_cycle = TYPICAL_AVG_CYC;
|
||||
state->cycles.bit.longest_cycle = TYPICAL_AVG_CYC;
|
||||
state->cycles.bit.average_cycle = TYPICAL_AVG_CYC;
|
||||
state->cycles.bit.total_cycles = 0;
|
||||
|
||||
state->dates.bit.reserved = 0;
|
||||
state->cycles.bit.reserved = 0;
|
||||
|
||||
watch_store_backup_data(state->dates.reg, state->backup_register_dt);
|
||||
watch_store_backup_data(state->cycles.reg, state->backup_register_cy);
|
||||
|
||||
watch_clear_indicator(WATCH_INDICATOR_SIGNAL);
|
||||
}
|
||||
|
||||
/*
|
||||
Fertility Window based on "The Calendar Method"
|
||||
Source: https://www.womenshealth.gov/pregnancy/you-get-pregnant/trying-conceive
|
||||
|
||||
The Calendar Method has several steps:
|
||||
|
||||
Step 1: Track the menstrual cycle for 8–12 months. One cycle is from the first day of one
|
||||
period until the first day of the next period. The average cycle is 28 days, but
|
||||
it may be as short as 24 days or as long as 38 days.
|
||||
Step 2: Subtract 18 from the number of days in the shortest menstrual cycle.
|
||||
Step 3: Subtract 11 from the number of days in the longest menstrual cycle.
|
||||
Step 4: Using a calendar, mark down the start of the next period (using previous instead). Count ahead by the number
|
||||
of days calculated in step 2. This is when peak fertility begins. Peak fertility ends
|
||||
at the number of days calculated in step 3.
|
||||
NOTE: Right now, the fertility window face displays its estimated window as soon as tracking is activated, although
|
||||
it is important to keep in mind that The Calendar Method states that peak accuracy of the window will be
|
||||
reached only after at least 8 months of tracking the menstrual cycle (can make it so that it only displays
|
||||
after total_days_tracked >= 8 months...but the info is interesting and should already be taken with the understanding that,
|
||||
in general, it is a rough estimation at best).
|
||||
*/
|
||||
typedef enum Fertile_Window {first_day, last_day} fertile_window;
|
||||
// Calculate the predicted starting or ending day of peak fertility
|
||||
static inline uint32_t get_day_pk_fert(menstrual_cycle_state_t *state, fertile_window which_day) {
|
||||
|
||||
// Get the date of the previous period
|
||||
watch_date_time date_prev_period;
|
||||
date_prev_period.unit.second = 0;
|
||||
date_prev_period.unit.minute = 0;
|
||||
date_prev_period.unit.hour = 0;
|
||||
date_prev_period.unit.day = state->dates.bit.prev_day;
|
||||
date_prev_period.unit.month = state->dates.bit.prev_month;
|
||||
date_prev_period.unit.year = state->dates.bit.prev_year;
|
||||
|
||||
// Convert the previous period date to Unix time
|
||||
uint32_t unix_prev_period = watch_utility_date_time_to_unix_time(date_prev_period, state->utc_offset);
|
||||
|
||||
// Calculate the Unix time of the predicted peak fertility day based on the length of the shortest/longest cycle
|
||||
uint32_t unix_pk_date;
|
||||
switch(which_day) {
|
||||
case first_day:
|
||||
unix_pk_date = unix_prev_period + ((state->cycles.bit.shortest_cycle - 18) * SECONDS_PER_DAY);
|
||||
break;
|
||||
case last_day:
|
||||
unix_pk_date = unix_prev_period + ((state->cycles.bit.longest_cycle - 11) * SECONDS_PER_DAY);
|
||||
break;
|
||||
}
|
||||
|
||||
// Convert the Unix time of the predicted peak fertility day to a date/time and return the day of the month
|
||||
return watch_utility_date_time_from_unix_time(unix_pk_date, state->utc_offset).unit.day;
|
||||
}
|
||||
|
||||
// Determine if today falls within the predicted peak fertility window
|
||||
static inline bool inside_fert_window(menstrual_cycle_state_t *state) {
|
||||
|
||||
// If tracking has not yet been activated, return false
|
||||
if (!(state->dates.reg))
|
||||
return false;
|
||||
|
||||
// Get the current date/time
|
||||
watch_date_time date_time_now = watch_rtc_get_date_time();
|
||||
|
||||
// Check if the current day falls between the first and last predicted peak fertility days
|
||||
if (get_day_pk_fert(state, first_day) > get_day_pk_fert(state, last_day)) { // We are crossing over the end of the month
|
||||
if (date_time_now.unit.day >= get_day_pk_fert(state, first_day) ||
|
||||
date_time_now.unit.day <= get_day_pk_fert(state, last_day))
|
||||
return true;
|
||||
}
|
||||
else if (date_time_now.unit.day >= get_day_pk_fert(state, first_day) &&
|
||||
date_time_now.unit.day <= get_day_pk_fert(state, last_day))
|
||||
return true;
|
||||
// If the current day does not fall within the predicted peak fertility window, return false
|
||||
return false;
|
||||
}
|
||||
|
||||
// Update the shortest and longest menstrual cycles based on the previous menstrual cycle
|
||||
static inline void update_shortest_longest_cycle(menstrual_cycle_state_t *state) {
|
||||
|
||||
// Get the date of the previous menstrual cycle
|
||||
watch_date_time date_prev_period;
|
||||
date_prev_period.unit.second = 0;
|
||||
date_prev_period.unit.minute = 0;
|
||||
date_prev_period.unit.hour = 0;
|
||||
date_prev_period.unit.day = state->dates.bit.prev_day;
|
||||
date_prev_period.unit.month = state->dates.bit.prev_month;
|
||||
date_prev_period.unit.year = state->dates.bit.prev_year;
|
||||
|
||||
// Convert the date of the previous menstrual cycle to UNIX time
|
||||
uint32_t unix_prev_period = watch_utility_date_time_to_unix_time(date_prev_period, state->utc_offset);
|
||||
|
||||
// Calculate the length of the current menstrual cycle
|
||||
uint8_t cycle_length = total_days_tracked(state) - (unix_prev_period / SECONDS_PER_DAY);
|
||||
|
||||
// Update the shortest or longest cycle length if necessary
|
||||
if (cycle_length < state->cycles.bit.shortest_cycle)
|
||||
state->cycles.bit.shortest_cycle = cycle_length;
|
||||
else if (cycle_length > state->cycles.bit.longest_cycle)
|
||||
state->cycles.bit.longest_cycle = cycle_length;
|
||||
}
|
||||
|
||||
void menstrual_cycle_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) watch_face_index;
|
||||
(void) settings;
|
||||
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(menstrual_cycle_state_t));
|
||||
memset(*context_ptr, 0, sizeof(menstrual_cycle_state_t));
|
||||
menstrual_cycle_state_t *state = ((menstrual_cycle_state_t *)*context_ptr);
|
||||
|
||||
state->dates.bit.first_day = 0;
|
||||
state->dates.bit.first_month = 0;
|
||||
state->dates.bit.first_year = 0;
|
||||
|
||||
state->dates.bit.prev_day = 0;
|
||||
state->dates.bit.prev_month = 0;
|
||||
state->dates.bit.prev_year = 0;
|
||||
|
||||
state->cycles.bit.shortest_cycle = TYPICAL_AVG_CYC;
|
||||
state->cycles.bit.longest_cycle = TYPICAL_AVG_CYC;
|
||||
state->cycles.bit.average_cycle = TYPICAL_AVG_CYC;
|
||||
state->cycles.bit.total_cycles = 0;
|
||||
|
||||
state->dates.bit.reserved = 0;
|
||||
state->cycles.bit.reserved = 0;
|
||||
|
||||
state->backup_register_dt = 0;
|
||||
state->backup_register_cy = 0;
|
||||
}
|
||||
|
||||
menstrual_cycle_state_t *state = ((menstrual_cycle_state_t *)*context_ptr);
|
||||
if (!(state->backup_register_dt && state->backup_register_cy)) {
|
||||
state->backup_register_dt = movement_claim_backup_register();
|
||||
state->backup_register_cy = movement_claim_backup_register();
|
||||
|
||||
if (state->backup_register_dt && state->backup_register_cy) {
|
||||
watch_store_backup_data(state->dates.reg, state->backup_register_dt);
|
||||
watch_store_backup_data(state->cycles.reg, state->backup_register_cy);
|
||||
}
|
||||
}
|
||||
else {
|
||||
state->dates.reg = watch_get_backup_data(state->backup_register_dt);
|
||||
state->cycles.reg = watch_get_backup_data(state->backup_register_cy);
|
||||
}
|
||||
}
|
||||
|
||||
void menstrual_cycle_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
menstrual_cycle_state_t *state = (menstrual_cycle_state_t *)context;
|
||||
state->period_today = 0;
|
||||
state->current_page = 0;
|
||||
state->reset_tracking = 0;
|
||||
state->utc_offset = movement_timezone_offsets[settings->bit.time_zone] * 60;
|
||||
movement_request_tick_frequency(4); // we need to manually blink some pixels
|
||||
}
|
||||
|
||||
bool menstrual_cycle_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
menstrual_cycle_state_t *state = (menstrual_cycle_state_t *)context;
|
||||
watch_date_time date_period;
|
||||
uint8_t current_page = state->current_page;
|
||||
uint8_t first_day_fert;
|
||||
uint8_t last_day_fert;
|
||||
uint32_t unix_now;
|
||||
uint32_t unix_prev_period;
|
||||
switch (event.event_type) {
|
||||
case EVENT_TICK:
|
||||
case EVENT_ACTIVATE:
|
||||
// Do nothing; handled below.
|
||||
break;
|
||||
case EVENT_MODE_BUTTON_UP:
|
||||
movement_move_to_next_face();
|
||||
return false;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
current_page = (current_page + 1) % MENSTRUAL_CYCLE_FACE_NUM_PAGES;
|
||||
state->current_page = current_page;
|
||||
state->days_prev_period = 0;
|
||||
watch_clear_indicator(WATCH_INDICATOR_BELL);
|
||||
if (watch_tick_animation_is_running())
|
||||
watch_stop_tick_animation();
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
switch (current_page) {
|
||||
case period_in_num_days:
|
||||
break;
|
||||
case average_cycle:
|
||||
break;
|
||||
case peak_fertility_window:
|
||||
break;
|
||||
case period_is_here:
|
||||
if (state->period_today && total_days_tracked(state)) {
|
||||
// Calculate before updating date of last period
|
||||
update_shortest_longest_cycle(state);
|
||||
// Update the date of last period after calulating the, now previous, cycle length
|
||||
date_period = watch_rtc_get_date_time();
|
||||
state->dates.bit.prev_day = date_period.unit.day;
|
||||
state->dates.bit.prev_month = date_period.unit.month;
|
||||
state->dates.bit.prev_year = date_period.unit.year;
|
||||
// Calculate new cycle average
|
||||
state->cycles.bit.total_cycles += 1;
|
||||
state->cycles.bit.average_cycle = total_days_tracked(state) / state->cycles.bit.total_cycles;
|
||||
// Store the new data
|
||||
watch_store_backup_data(state->dates.reg, state->backup_register_dt);
|
||||
watch_store_backup_data(state->cycles.reg, state->backup_register_cy);
|
||||
state->period_today = !(state->period_today);
|
||||
beep(settings);
|
||||
}
|
||||
break;
|
||||
case first_period:
|
||||
// If tracking has not yet been activated
|
||||
if (!(state->dates.reg)) {
|
||||
unix_now = watch_utility_date_time_to_unix_time(watch_rtc_get_date_time(), state->utc_offset);
|
||||
unix_prev_period = unix_now - (state->days_prev_period * SECONDS_PER_DAY);
|
||||
date_period = watch_utility_date_time_from_unix_time(unix_prev_period, state->utc_offset);
|
||||
state->dates.bit.first_day = date_period.unit.day;
|
||||
state->dates.bit.first_month = date_period.unit.month;
|
||||
state->dates.bit.first_year = date_period.unit.year;
|
||||
state->dates.bit.prev_day = date_period.unit.day;
|
||||
state->dates.bit.prev_month = date_period.unit.month;
|
||||
state->dates.bit.prev_year = date_period.unit.year;
|
||||
watch_store_backup_data(state->dates.reg, state->backup_register_dt);
|
||||
beep(settings);
|
||||
}
|
||||
break;
|
||||
case reset:
|
||||
if (state->reset_tracking) {
|
||||
reset_tracking(state);
|
||||
state->reset_tracking = !(state->reset_tracking);
|
||||
beep(settings);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
switch (current_page) {
|
||||
case period_in_num_days:
|
||||
break;
|
||||
case average_cycle:
|
||||
break;
|
||||
case peak_fertility_window:
|
||||
break;
|
||||
case period_is_here:
|
||||
if (total_days_tracked(state))
|
||||
state->period_today = !(state->period_today);
|
||||
break;
|
||||
case first_period:
|
||||
if (!(state->dates.reg))
|
||||
state->days_prev_period = (state->days_prev_period > 99) ? 0 : state->days_prev_period + 1; // Cycle through pages to quickly reset to 0
|
||||
break;
|
||||
case reset:
|
||||
state->reset_tracking = !(state->reset_tracking);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case EVENT_TIMEOUT:
|
||||
movement_move_to_face(0);
|
||||
break;
|
||||
default:
|
||||
return movement_default_loop_handler(event, settings);
|
||||
}
|
||||
|
||||
watch_display_string((char *)menstrual_cycle_face_titles[current_page], 0);
|
||||
if (state->dates.reg)
|
||||
watch_set_indicator(WATCH_INDICATOR_SIGNAL); // signal that we are now in a tracking state
|
||||
|
||||
char buf[13];
|
||||
switch (current_page) {
|
||||
case period_in_num_days:
|
||||
sprintf(buf, "%2d", days_till_period(state));
|
||||
if (inside_fert_window(state))
|
||||
watch_set_indicator(WATCH_INDICATOR_BELL);
|
||||
watch_display_string(buf, 4);
|
||||
break;
|
||||
case average_cycle:
|
||||
sprintf(buf, "%2d", state->cycles.bit.average_cycle);
|
||||
watch_display_string(buf, 2);
|
||||
break;
|
||||
case peak_fertility_window:
|
||||
if (event.subsecond % 5 && state->dates.reg) { // blink active for 3 quarter-seconds
|
||||
first_day_fert = get_day_pk_fert(state, first_day);
|
||||
last_day_fert = get_day_pk_fert(state, last_day);
|
||||
sprintf(buf, "Fr%2d To %2d", first_day_fert, last_day_fert); // From: first day | To: last day
|
||||
if (inside_fert_window(state))
|
||||
watch_set_indicator(WATCH_INDICATOR_BELL);
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
break;
|
||||
case period_is_here:
|
||||
if (event.subsecond % 5) { // blink active for 3 quarter-seconds
|
||||
if (!(state->dates.reg))
|
||||
watch_display_string("NA", 8); // Not Applicable: Do not allow period entry until tracking is activated...
|
||||
else if (state->period_today)
|
||||
watch_display_string("y", 9);
|
||||
else
|
||||
watch_display_string("n", 9);
|
||||
}
|
||||
break;
|
||||
case first_period:
|
||||
if (state->dates.reg) {
|
||||
if (!watch_tick_animation_is_running())
|
||||
watch_start_tick_animation(500); // Tracking activated
|
||||
}
|
||||
else if (event.subsecond % 5) { // blink active for 3 quarter-seconds
|
||||
sprintf(buf, "%2d", state->days_prev_period);
|
||||
watch_display_string(buf, 8);
|
||||
}
|
||||
break;
|
||||
case reset:
|
||||
// blink active for 3 quarter-seconds
|
||||
if (event.subsecond % 5 && state->reset_tracking)
|
||||
watch_display_string("y", 9);
|
||||
else if (event.subsecond % 5)
|
||||
watch_display_string("n", 9);
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void menstrual_cycle_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
}
|
80
movement/watch_faces/complication/menstrual_cycle_face.h
Normal file
80
movement/watch_faces/complication/menstrual_cycle_face.h
Normal file
@ -0,0 +1,80 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Joseph Borne Komosa | @jokomo24
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MENSTRUAL_CYCLE_FACE_H_
|
||||
#define MENSTRUAL_CYCLE_FACE_H_
|
||||
|
||||
#include "movement.h"
|
||||
|
||||
typedef struct {
|
||||
// Store the date of the 'first' and the total cycles since to calulate and store the average menstrual cycle.
|
||||
// Store the date of the previous, most recent, period to calculate the cycle length.
|
||||
// Store the shortest and longest cycle to calculate the fertility window for The Calender Method.
|
||||
// NOTE: Not thrilled about using two registers, but could not find a way to perform The Calender Method
|
||||
// without requiring both the 'first' and 'prev' dates.
|
||||
union {
|
||||
struct {
|
||||
uint8_t first_day : 5;
|
||||
uint8_t first_month : 4;
|
||||
uint8_t first_year : 6; // 0-63 (representing 2020-2083)
|
||||
uint8_t prev_day : 5;
|
||||
uint8_t prev_month : 4;
|
||||
uint8_t prev_year : 6; // 0-63 (representing 2020-2083)
|
||||
uint8_t reserved : 2; // left over bit space
|
||||
} bit;
|
||||
uint32_t reg; // Tracking's been activated if > 0
|
||||
} dates;
|
||||
union {
|
||||
struct {
|
||||
uint8_t shortest_cycle : 6; // For step 2 of The Calender Method
|
||||
uint8_t longest_cycle : 6; // For step 3 of The Calender Method
|
||||
uint8_t average_cycle : 6; // The average menstrual cycle lasts 28 days, but normal cycles can vary from 21 to 35 days
|
||||
uint16_t total_cycles : 11; // The total cycles (periods) entered since the start of tracking
|
||||
uint8_t reserved : 3; // left over bit space
|
||||
} bit;
|
||||
uint32_t reg;
|
||||
} cycles;
|
||||
uint8_t backup_register_dt;
|
||||
uint8_t backup_register_cy;
|
||||
uint8_t current_page;
|
||||
uint8_t days_prev_period;
|
||||
int32_t utc_offset;
|
||||
bool period_today;
|
||||
bool reset_tracking;
|
||||
} menstrual_cycle_state_t;
|
||||
|
||||
void menstrual_cycle_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void menstrual_cycle_face_activate(movement_settings_t *settings, void *context);
|
||||
bool menstrual_cycle_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void menstrual_cycle_face_resign(movement_settings_t *settings, void *context);
|
||||
|
||||
#define menstrual_cycle_face ((const watch_face_t){ \
|
||||
menstrual_cycle_face_setup, \
|
||||
menstrual_cycle_face_activate, \
|
||||
menstrual_cycle_face_loop, \
|
||||
menstrual_cycle_face_resign, \
|
||||
NULL, \
|
||||
})
|
||||
|
||||
#endif // MENSTRUAL_CYCLE_FACE_H_
|
263
movement/watch_faces/complication/metronome_face.c
Normal file
263
movement/watch_faces/complication/metronome_face.c
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Austin Teets
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "metronome_face.h"
|
||||
#include "watch.h"
|
||||
|
||||
static const int8_t _sound_seq_start[] = {BUZZER_NOTE_C8, 2, 0};
|
||||
static const int8_t _sound_seq_beat[] = {BUZZER_NOTE_C6, 2, 0};
|
||||
|
||||
void metronome_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) settings;
|
||||
(void) watch_face_index;
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(metronome_state_t));
|
||||
memset(*context_ptr, 0, sizeof(metronome_state_t));
|
||||
}
|
||||
}
|
||||
|
||||
void metronome_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
metronome_state_t *state = (metronome_state_t *)context;
|
||||
movement_request_tick_frequency(2);
|
||||
if (state->bpm == 0) {
|
||||
state->count = 4;
|
||||
state->bpm = 120;
|
||||
state->soundOn = true;
|
||||
}
|
||||
state->mode = metWait;
|
||||
state->correction = 0;
|
||||
state->setCur = hundred;
|
||||
}
|
||||
|
||||
static void _metronome_face_update_lcd(metronome_state_t *state) {
|
||||
char buf[11];
|
||||
if (state->soundOn) {
|
||||
watch_set_indicator(WATCH_INDICATOR_BELL);
|
||||
} else {
|
||||
watch_clear_indicator(WATCH_INDICATOR_BELL);
|
||||
}
|
||||
sprintf(buf, "MN %d %03d%s", state->count, state->bpm, "bp");
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
static void _metronome_start_stop(metronome_state_t *state) {
|
||||
if (state->mode != metRun) {
|
||||
movement_request_tick_frequency(64);
|
||||
state->mode = metRun;
|
||||
watch_clear_display();
|
||||
double ticks = 3840.0 / (double)state->bpm;
|
||||
state->tick = (int) ticks;
|
||||
state->curTick = (int) ticks;
|
||||
state->halfBeat = (int)(state->tick/2);
|
||||
state->curCorrection = ticks - state->tick;
|
||||
state->correction = ticks - state->tick;
|
||||
state->curBeat = 1;
|
||||
} else {
|
||||
state->mode = metWait;
|
||||
movement_request_tick_frequency(2);
|
||||
_metronome_face_update_lcd(state);
|
||||
}
|
||||
}
|
||||
|
||||
static void _metronome_tick_beat(metronome_state_t *state) {
|
||||
char buf[11];
|
||||
if (state->soundOn) {
|
||||
if (state->curBeat == 1) {
|
||||
watch_buzzer_play_sequence((int8_t *)_sound_seq_start, NULL);
|
||||
} else {
|
||||
watch_buzzer_play_sequence((int8_t *)_sound_seq_beat, NULL);
|
||||
}
|
||||
}
|
||||
sprintf(buf, "MN %d %03d%s", state->count, state->bpm, "bp");
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
static void _metronome_event_tick(uint8_t subsecond, metronome_state_t *state) {
|
||||
(void) subsecond;
|
||||
|
||||
if (state->curCorrection >= 1) {
|
||||
state->curCorrection -= 1;
|
||||
state->curTick -= 1;
|
||||
}
|
||||
int diff = state->curTick - state->tick;
|
||||
if(diff == 0) {
|
||||
_metronome_tick_beat(state);
|
||||
state->curTick = 0;
|
||||
state->curCorrection += state->correction;
|
||||
if (state->curBeat < state->count ) {
|
||||
state->curBeat += 1;
|
||||
} else {
|
||||
state->curBeat = 1;
|
||||
}
|
||||
} else {
|
||||
if (state->curTick == state->halfBeat) {
|
||||
watch_clear_display();
|
||||
}
|
||||
state->curTick += 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void _metronome_setting_tick(uint8_t subsecond, metronome_state_t *state) {
|
||||
char buf[13];
|
||||
sprintf(buf, "MN %d %03d%s", state->count, state->bpm, "bp");
|
||||
if (subsecond%2 == 0) {
|
||||
switch (state->setCur) {
|
||||
case hundred:
|
||||
buf[5] = ' ';
|
||||
break;
|
||||
case ten:
|
||||
buf[6] = ' ';
|
||||
break;
|
||||
case one:
|
||||
buf[7] = ' ';
|
||||
break;
|
||||
case count:
|
||||
buf[3] = ' ';
|
||||
break;
|
||||
case alarm:
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (state->setCur == alarm) {
|
||||
sprintf(buf, "MN 8eep%s", state->soundOn ? "On" : " -");
|
||||
}
|
||||
if (state->soundOn) {
|
||||
watch_set_indicator(WATCH_INDICATOR_BELL);
|
||||
} else {
|
||||
watch_clear_indicator(WATCH_INDICATOR_BELL);
|
||||
}
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
static void _metronome_update_setting(metronome_state_t *state) {
|
||||
char buf[13];
|
||||
switch (state->setCur) {
|
||||
case hundred:
|
||||
if (state->bpm < 100) {
|
||||
state->bpm += 100;
|
||||
} else {
|
||||
state->bpm -= 100;
|
||||
}
|
||||
break;
|
||||
case ten:
|
||||
if ((state->bpm / 10) % 10 < 9) {
|
||||
state->bpm += 10;
|
||||
} else {
|
||||
state->bpm -= 90;
|
||||
}
|
||||
break;
|
||||
case one:
|
||||
if (state->bpm%10 < 9) {
|
||||
state->bpm += 1;
|
||||
} else {
|
||||
state->bpm -= 9;
|
||||
}
|
||||
break;
|
||||
case count:
|
||||
if (state->count < 9) {
|
||||
state->count += 1;
|
||||
} else {
|
||||
state->count = 2;
|
||||
}
|
||||
break;
|
||||
case alarm:
|
||||
state->soundOn = !state->soundOn;
|
||||
break;
|
||||
}
|
||||
sprintf(buf, "MN %d %03d%s", state->count % 10, state->bpm, "bp");
|
||||
if (state->setCur == alarm) {
|
||||
sprintf(buf, "MN 8eep%s", state->soundOn ? "On" : " -");
|
||||
}
|
||||
if (state->soundOn) {
|
||||
watch_set_indicator(WATCH_INDICATOR_BELL);
|
||||
} else {
|
||||
watch_clear_indicator(WATCH_INDICATOR_BELL);
|
||||
}
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
bool metronome_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
metronome_state_t *state = (metronome_state_t *)context;
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
_metronome_face_update_lcd(state);
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
if (state->mode == metRun){
|
||||
_metronome_event_tick(event.subsecond, state);
|
||||
} else if (state->mode == setMenu) {
|
||||
_metronome_setting_tick(event.subsecond, state);
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
if (state->mode == setMenu) {
|
||||
_metronome_update_setting(state);
|
||||
} else {
|
||||
_metronome_start_stop(state);
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
if (state->mode == setMenu) {
|
||||
if (state->setCur < alarm) {
|
||||
state->setCur += 1;
|
||||
} else {
|
||||
state->setCur = hundred;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
if (state->mode != metRun && state->mode != setMenu) {
|
||||
movement_request_tick_frequency(2);
|
||||
state->mode = setMenu;
|
||||
_metronome_face_update_lcd(state);
|
||||
} else if (state->mode == setMenu) {
|
||||
state->mode = metWait;
|
||||
_metronome_face_update_lcd(state);
|
||||
}
|
||||
break;
|
||||
case EVENT_MODE_BUTTON_UP:
|
||||
movement_move_to_next_face();
|
||||
break;
|
||||
case EVENT_TIMEOUT:
|
||||
if (state->mode != metRun) {
|
||||
movement_move_to_face(0);
|
||||
}
|
||||
break;
|
||||
case EVENT_LOW_ENERGY_UPDATE:
|
||||
break;
|
||||
default:
|
||||
return movement_default_loop_handler(event, settings);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void metronome_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
}
|
||||
|
86
movement/watch_faces/complication/metronome_face.h
Normal file
86
movement/watch_faces/complication/metronome_face.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Austin Teets
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef METRONOME_FACE_H_
|
||||
#define METRONOME_FACE_H_
|
||||
|
||||
#include "movement.h"
|
||||
|
||||
/*
|
||||
* A Metronome watch complication
|
||||
* Allows the user to set the BPM, counts per measure, beep sound on/off
|
||||
* Screen flashes on on the beat and off on the half beat (1/8th note)
|
||||
* Beep will sound high for downbeat and low for subsequent beats in measure
|
||||
* USE:
|
||||
* Press Alarm to start/stop metronome_face
|
||||
* Hold Alarm to enter settings menu
|
||||
* Short Light press will move through options
|
||||
* Short Alarm press will increment/toggle options
|
||||
* Long alarm press will exit options
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
metWait,
|
||||
metRun,
|
||||
setMenu
|
||||
} metronome_mode_t;
|
||||
|
||||
typedef enum {
|
||||
hundred,
|
||||
ten,
|
||||
one,
|
||||
count,
|
||||
alarm
|
||||
} setting_cursor_t;
|
||||
|
||||
typedef struct {
|
||||
// Anything you need to keep track of, put it here!
|
||||
uint8_t bpm;
|
||||
double correction;
|
||||
double curCorrection;
|
||||
int count;
|
||||
int tick;
|
||||
int curTick;
|
||||
int curBeat;
|
||||
int halfBeat;
|
||||
metronome_mode_t mode : 3;
|
||||
setting_cursor_t setCur : 4;
|
||||
bool soundOn;
|
||||
} metronome_state_t;
|
||||
|
||||
void metronome_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void metronome_face_activate(movement_settings_t *settings, void *context);
|
||||
bool metronome_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void metronome_face_resign(movement_settings_t *settings, void *context);
|
||||
|
||||
#define metronome_face ((const watch_face_t){ \
|
||||
metronome_face_setup, \
|
||||
metronome_face_activate, \
|
||||
metronome_face_loop, \
|
||||
metronome_face_resign, \
|
||||
NULL, \
|
||||
})
|
||||
|
||||
#endif // METRONOME_FACE_H_
|
||||
|
384
movement/watch_faces/complication/moonrise_face.c
Normal file
384
movement/watch_faces/complication/moonrise_face.c
Normal file
@ -0,0 +1,384 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2025 hueso
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "moonrise_face.h"
|
||||
#include "sunrise_sunset_face.h"
|
||||
#include "watch.h"
|
||||
#include "watch_utility.h"
|
||||
#include "moonrise.h"
|
||||
|
||||
#if __EMSCRIPTEN__
|
||||
#include <emscripten.h>
|
||||
#endif
|
||||
|
||||
static const uint8_t _location_count = sizeof(longLatPresets) / sizeof(long_lat_presets_t);
|
||||
|
||||
static void _moonrise_face_update(movement_settings_t *settings, moonrise_state_t *state) {
|
||||
char buf[11];
|
||||
movement_location_t movement_location;
|
||||
|
||||
if (state->longLatToUse == 0 || _location_count <= 1)
|
||||
movement_location = (movement_location_t) watch_get_backup_data(1);
|
||||
else{
|
||||
movement_location.bit.latitude = longLatPresets[state->longLatToUse].latitude;
|
||||
movement_location.bit.longitude = longLatPresets[state->longLatToUse].longitude;
|
||||
}
|
||||
|
||||
if (movement_location.reg == 0) {
|
||||
watch_clear_colon();
|
||||
watch_display_string("Mz no Loc", 0);
|
||||
return;
|
||||
}
|
||||
|
||||
watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time
|
||||
watch_date_time scratch_time; // scratchpad, contains different values at different times
|
||||
scratch_time.reg = date_time.reg;
|
||||
|
||||
double lat = (double)movement_location.bit.latitude / 100.0;
|
||||
double lon = (double)movement_location.bit.longitude / 100.0;
|
||||
|
||||
uint32_t t = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60);
|
||||
MoonRise mr = MoonRise_calculate(lat, lon, t);
|
||||
|
||||
if(mr.isVisible)
|
||||
watch_set_indicator(WATCH_INDICATOR_LAP);
|
||||
else
|
||||
watch_clear_indicator(WATCH_INDICATOR_LAP);
|
||||
|
||||
if ( (state->rise_index == 0 && !mr.hasRise) ||
|
||||
(state->rise_index == 1 && !mr.hasSet) ) {
|
||||
watch_clear_colon();
|
||||
watch_clear_indicator(WATCH_INDICATOR_PM);
|
||||
watch_clear_indicator(WATCH_INDICATOR_24H);
|
||||
snprintf(buf, sizeof(buf), "%s%2d none ", state->rise_index ? "M_" : "M~", scratch_time.unit.day);
|
||||
watch_display_string(buf, 0);
|
||||
return;
|
||||
}
|
||||
watch_set_colon();
|
||||
if (settings->bit.clock_mode_24h && !settings->bit.clock_24h_leading_zero)
|
||||
watch_set_indicator(WATCH_INDICATOR_24H);
|
||||
|
||||
if(state->rise_index == 0)
|
||||
scratch_time = watch_utility_date_time_from_unix_time(mr.riseTime, movement_timezone_offsets[settings->bit.time_zone] * 60);
|
||||
else
|
||||
scratch_time = watch_utility_date_time_from_unix_time(mr.setTime, movement_timezone_offsets[settings->bit.time_zone] * 60);
|
||||
|
||||
state->rise_set_expires.reg = scratch_time.reg;
|
||||
|
||||
bool set_leading_zero = false;
|
||||
if (!settings->bit.clock_mode_24h)
|
||||
if (watch_utility_convert_to_12_hour(&scratch_time))
|
||||
watch_set_indicator(WATCH_INDICATOR_PM);
|
||||
else
|
||||
watch_clear_indicator(WATCH_INDICATOR_PM);
|
||||
else if (settings->bit.clock_24h_leading_zero && scratch_time.unit.hour < 10) {
|
||||
set_leading_zero = true;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "%s%2d%2d%02d%2s", state->rise_index ? "M_" : "M~", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute,longLatPresets[state->longLatToUse].name);
|
||||
watch_display_string(buf, 0);
|
||||
|
||||
if (set_leading_zero)
|
||||
watch_display_string("0", 4);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
static int16_t _moonrise_face_latlon_from_struct(moonrise_lat_lon_settings_t val) {
|
||||
int16_t retval = (val.sign ? -1 : 1) *
|
||||
(
|
||||
val.hundreds * 10000 +
|
||||
val.tens * 1000 +
|
||||
val.ones * 100 +
|
||||
val.tenths * 10 +
|
||||
val.hundredths
|
||||
);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static moonrise_lat_lon_settings_t _moonrise_face_struct_from_latlon(int16_t val) {
|
||||
moonrise_lat_lon_settings_t retval;
|
||||
|
||||
retval.sign = val < 0;
|
||||
val = abs(val);
|
||||
retval.hundredths = val % 10;
|
||||
val /= 10;
|
||||
retval.tenths = val % 10;
|
||||
val /= 10;
|
||||
retval.ones = val % 10;
|
||||
val /= 10;
|
||||
retval.tens = val % 10;
|
||||
val /= 10;
|
||||
retval.hundreds = val % 10;
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void _moonrise_face_update_location_register(moonrise_state_t *state) {
|
||||
if (state->location_changed) {
|
||||
movement_location_t movement_location;
|
||||
int16_t lat = _moonrise_face_latlon_from_struct(state->working_latitude);
|
||||
int16_t lon = _moonrise_face_latlon_from_struct(state->working_longitude);
|
||||
movement_location.bit.latitude = lat;
|
||||
movement_location.bit.longitude = lon;
|
||||
watch_store_backup_data(movement_location.reg, 1);
|
||||
state->location_changed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void _moonrise_face_update_settings_display(movement_event_t event, moonrise_state_t *state) {
|
||||
char buf[12];
|
||||
|
||||
switch (state->page) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
snprintf(buf, sizeof(buf), "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(_moonrise_face_latlon_from_struct(state->working_latitude)));
|
||||
break;
|
||||
case 2:
|
||||
snprintf(buf, sizeof(buf), "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(_moonrise_face_latlon_from_struct(state->working_longitude)));
|
||||
break;
|
||||
}
|
||||
if (event.subsecond % 2) {
|
||||
buf[state->active_digit + 4] = ' ';
|
||||
}
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
static void _moonrise_face_advance_digit(moonrise_state_t *state) {
|
||||
state->location_changed = true;
|
||||
switch (state->page) {
|
||||
case 1: // latitude
|
||||
switch (state->active_digit) {
|
||||
case 0:
|
||||
state->working_latitude.sign++;
|
||||
break;
|
||||
case 1:
|
||||
// we skip this digit
|
||||
break;
|
||||
case 2:
|
||||
state->working_latitude.tens = (state->working_latitude.tens + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_latitude)) > 9000) {
|
||||
// prevent latitude from going over ±90.
|
||||
// TODO: perform these checks when advancing the digit?
|
||||
state->working_latitude.ones = 0;
|
||||
state->working_latitude.tenths = 0;
|
||||
state->working_latitude.hundredths = 0;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
state->working_latitude.ones = (state->working_latitude.ones + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.ones = 0;
|
||||
break;
|
||||
case 4:
|
||||
state->working_latitude.tenths = (state->working_latitude.tenths + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.tenths = 0;
|
||||
break;
|
||||
case 5:
|
||||
state->working_latitude.hundredths = (state->working_latitude.hundredths + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_latitude)) > 9000) state->working_latitude.hundredths = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2: // longitude
|
||||
switch (state->active_digit) {
|
||||
case 0:
|
||||
state->working_longitude.sign++;
|
||||
break;
|
||||
case 1:
|
||||
state->working_longitude.hundreds = (state->working_longitude.hundreds + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_longitude)) > 18000) {
|
||||
// prevent longitude from going over ±180
|
||||
state->working_longitude.tens = 8;
|
||||
state->working_longitude.ones = 0;
|
||||
state->working_longitude.tenths = 0;
|
||||
state->working_longitude.hundredths = 0;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
state->working_longitude.tens = (state->working_longitude.tens + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tens = 0;
|
||||
break;
|
||||
case 3:
|
||||
state->working_longitude.ones = (state->working_longitude.ones + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.ones = 0;
|
||||
break;
|
||||
case 4:
|
||||
state->working_longitude.tenths = (state->working_longitude.tenths + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.tenths = 0;
|
||||
break;
|
||||
case 5:
|
||||
state->working_longitude.hundredths = (state->working_longitude.hundredths + 1) % 10;
|
||||
if (abs(_moonrise_face_latlon_from_struct(state->working_longitude)) > 18000) state->working_longitude.hundredths = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void moonrise_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) settings;
|
||||
(void) watch_face_index;
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(moonrise_state_t));
|
||||
memset(*context_ptr, 0, sizeof(moonrise_state_t));
|
||||
}
|
||||
}
|
||||
|
||||
void moonrise_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
if (watch_tick_animation_is_running()) watch_stop_tick_animation();
|
||||
|
||||
#if __EMSCRIPTEN__
|
||||
int16_t browser_lat = EM_ASM_INT({
|
||||
return lat;
|
||||
});
|
||||
int16_t browser_lon = EM_ASM_INT({
|
||||
return lon;
|
||||
});
|
||||
if ((watch_get_backup_data(1) == 0) && (browser_lat || browser_lon)) {
|
||||
movement_location_t browser_loc;
|
||||
browser_loc.bit.latitude = browser_lat;
|
||||
browser_loc.bit.longitude = browser_lon;
|
||||
watch_store_backup_data(browser_loc.reg, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
moonrise_state_t *state = (moonrise_state_t *)context;
|
||||
movement_location_t movement_location = (movement_location_t) watch_get_backup_data(1);
|
||||
state->working_latitude = _moonrise_face_struct_from_latlon(movement_location.bit.latitude);
|
||||
state->working_longitude = _moonrise_face_struct_from_latlon(movement_location.bit.longitude);
|
||||
}
|
||||
|
||||
bool moonrise_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
moonrise_state_t *state = (moonrise_state_t *)context;
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
_moonrise_face_update(settings, state);
|
||||
break;
|
||||
case EVENT_LOW_ENERGY_UPDATE:
|
||||
case EVENT_TICK:
|
||||
if (state->page == 0) {
|
||||
// if entering low energy mode, start tick animation
|
||||
if (event.event_type == EVENT_LOW_ENERGY_UPDATE && !watch_tick_animation_is_running()) watch_start_tick_animation(1000);
|
||||
// check if we need to update the display
|
||||
watch_date_time date_time = watch_rtc_get_date_time();
|
||||
if (date_time.reg >= state->rise_set_expires.reg) {
|
||||
// and on the off chance that this happened before EVENT_TIMEOUT snapped us back to rise/set 0, go back now
|
||||
state->rise_index = 0;
|
||||
_moonrise_face_update(settings, state);
|
||||
}
|
||||
} else {
|
||||
_moonrise_face_update_settings_display(event, state);
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
if (state->page) {
|
||||
state->active_digit++;
|
||||
if (state->page == 1 && state->active_digit == 1) state->active_digit++; // max latitude is +- 90, no hundreds place
|
||||
if (state->active_digit > 5) {
|
||||
state->active_digit = 0;
|
||||
state->page = (state->page + 1) % 3;
|
||||
_moonrise_face_update_location_register(state);
|
||||
}
|
||||
_moonrise_face_update_settings_display(event, context);
|
||||
} else if (_location_count <= 1) {
|
||||
movement_illuminate_led();
|
||||
}
|
||||
if (state->page == 0) {
|
||||
movement_request_tick_frequency(1);
|
||||
_moonrise_face_update(settings, state);
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
if (_location_count <= 1) break;
|
||||
else if (!state->page) movement_illuminate_led();
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
if (state->page == 0 && _location_count > 1) {
|
||||
state->longLatToUse = (state->longLatToUse + 1) % _location_count;
|
||||
_moonrise_face_update(settings, state);
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
if (state->page) {
|
||||
_moonrise_face_advance_digit(state);
|
||||
_moonrise_face_update_settings_display(event, context);
|
||||
} else {
|
||||
state->rise_index = (state->rise_index + 1) % 2;
|
||||
_moonrise_face_update(settings, state);
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
if (state->page == 0) {
|
||||
if (state->longLatToUse != 0) {
|
||||
state->longLatToUse = 0;
|
||||
_moonrise_face_update(settings, state);
|
||||
break;
|
||||
}
|
||||
state->page++;
|
||||
state->active_digit = 0;
|
||||
watch_clear_display();
|
||||
movement_request_tick_frequency(4);
|
||||
_moonrise_face_update_settings_display(event, context);
|
||||
}
|
||||
else {
|
||||
state->active_digit = 0;
|
||||
state->page = 0;
|
||||
_moonrise_face_update_location_register(state);
|
||||
_moonrise_face_update(settings, state);
|
||||
}
|
||||
break;
|
||||
case EVENT_TIMEOUT:
|
||||
if (watch_get_backup_data(1) == 0) {
|
||||
// if no location set, return home
|
||||
movement_move_to_face(0);
|
||||
} else if (state->page || state->rise_index) {
|
||||
// otherwise on timeout, exit settings mode and return to the next sunrise or sunset
|
||||
state->page = 0;
|
||||
state->rise_index = 0;
|
||||
movement_request_tick_frequency(1);
|
||||
_moonrise_face_update(settings, state);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return movement_default_loop_handler(event, settings);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void moonrise_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
moonrise_state_t *state = (moonrise_state_t *)context;
|
||||
state->page = 0;
|
||||
state->active_digit = 0;
|
||||
state->rise_index = 0;
|
||||
_moonrise_face_update_location_register(state);
|
||||
}
|
90
movement/watch_faces/complication/moonrise_face.h
Normal file
90
movement/watch_faces/complication/moonrise_face.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Joey Castillo
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MOONRISE_FACE_H_
|
||||
#define MOONRISE_FACE_H_
|
||||
|
||||
/*
|
||||
* SUNRISE & SUNSET FACE
|
||||
*
|
||||
* The Sunrise/Sunset face is designed to display the next sunrise or sunset
|
||||
* for a given location. It also functions as an interface for setting the
|
||||
* location register, which other watch faces can use for various purposes.
|
||||
*
|
||||
* Refer to the wiki for usage instructions:
|
||||
* https://www.sensorwatch.net/docs/watchfaces/complication/#sunrisesunset
|
||||
*/
|
||||
|
||||
#include "movement.h"
|
||||
|
||||
typedef struct {
|
||||
uint8_t sign: 1; // 0-1
|
||||
uint8_t hundreds: 1; // 0-1, ignored for latitude
|
||||
uint8_t tens: 4; // 0-9 (must wrap at 10)
|
||||
uint8_t ones: 4; // 0-9 (must wrap at 10)
|
||||
uint8_t tenths: 4; // 0-9 (must wrap at 10)
|
||||
uint8_t hundredths: 4; // 0-9 (must wrap at 10)
|
||||
} moonrise_lat_lon_settings_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t page;
|
||||
uint8_t rise_index;
|
||||
uint8_t active_digit;
|
||||
bool location_changed;
|
||||
watch_date_time rise_set_expires;
|
||||
moonrise_lat_lon_settings_t working_latitude;
|
||||
moonrise_lat_lon_settings_t working_longitude;
|
||||
uint8_t longLatToUse;
|
||||
} moonrise_state_t;
|
||||
|
||||
void moonrise_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void moonrise_face_activate(movement_settings_t *settings, void *context);
|
||||
bool moonrise_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void moonrise_face_resign(movement_settings_t *settings, void *context);
|
||||
|
||||
#define moonrise_face ((const watch_face_t){ \
|
||||
moonrise_face_setup, \
|
||||
moonrise_face_activate, \
|
||||
moonrise_face_loop, \
|
||||
moonrise_face_resign, \
|
||||
NULL, \
|
||||
})
|
||||
|
||||
/*
|
||||
typedef struct {
|
||||
char name[2];
|
||||
int16_t latitude;
|
||||
int16_t longitude;
|
||||
} long_lat_presets_t;
|
||||
|
||||
|
||||
static const long_lat_presets_t longLatPresets[] =
|
||||
{
|
||||
{ .name = " "}, // Default, the long and lat get replaced by what's set in the watch
|
||||
// { .name = "Ny", .latitude = 4072, .longitude = -7401 }, // New York City, NY
|
||||
// { .name = "LA", .latitude = 3405, .longitude = -11824 }, // Los Angeles, CA
|
||||
// { .name = "dE", .latitude = 4221, .longitude = -8305 }, // Detroit, MI
|
||||
};
|
||||
*/
|
||||
#endif // MOONRISE_FACE_H_
|
504
movement/watch_faces/complication/smallchess_face.c
Normal file
504
movement/watch_faces/complication/smallchess_face.c
Normal file
@ -0,0 +1,504 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Jeremy O'Brien
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "smallchesslib.h"
|
||||
|
||||
#include "smallchess_face.h"
|
||||
#include "watch.h"
|
||||
|
||||
#define PIECE_LIST_END_MARKER 0xff
|
||||
|
||||
int8_t cpu_done_beep[] = {BUZZER_NOTE_C5, 5, BUZZER_NOTE_C6, 5, BUZZER_NOTE_C7, 5, 0};
|
||||
|
||||
static void smallchess_init_board(smallchess_face_state_t *state) {
|
||||
SCL_gameInit((SCL_Game *)state->game, 0);
|
||||
memset(state->moveable_pieces, 0xff, sizeof(state->moveable_pieces));
|
||||
memset(state->moveable_dests, 0xff, sizeof(state->moveable_dests));
|
||||
}
|
||||
|
||||
void smallchess_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) settings;
|
||||
(void) watch_face_index;
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(smallchess_face_state_t));
|
||||
memset(*context_ptr, 0, sizeof(smallchess_face_state_t));
|
||||
|
||||
/* now alloc/init the game board */
|
||||
smallchess_face_state_t *state = (smallchess_face_state_t *)*context_ptr;
|
||||
state->game = malloc(sizeof(SCL_Game));
|
||||
smallchess_init_board(*context_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void smallchess_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
}
|
||||
|
||||
static void _smallchess_calc_moveable_pieces(smallchess_face_state_t *state) {
|
||||
int moveable_pieces_idx = 0;
|
||||
SCL_Game *game = (SCL_Game *)state->game;
|
||||
for (int i = 0; i < SCL_BOARD_SQUARES; ++i) {
|
||||
if (game->board[i] != '.' &&
|
||||
SCL_pieceIsWhite(game->board[i]) == SCL_boardWhitesTurn(game->board)) {
|
||||
SCL_SquareSet moveable_pieces = SCL_SQUARE_SET_EMPTY;
|
||||
SCL_boardGetMoves(game->board, i, moveable_pieces);
|
||||
if (SCL_squareSetSize(moveable_pieces) != 0) {
|
||||
state->moveable_pieces[moveable_pieces_idx] = i;
|
||||
moveable_pieces_idx++;
|
||||
}
|
||||
}
|
||||
}
|
||||
state->moveable_pieces[moveable_pieces_idx] = PIECE_LIST_END_MARKER;
|
||||
state->moveable_pieces_idx = 0;
|
||||
}
|
||||
|
||||
static void _smallchess_make_ai_move(smallchess_face_state_t *state) {
|
||||
char ai_from_str[3] = {0};
|
||||
char ai_to_str[3] = {0};
|
||||
uint8_t rep_from, rep_to;
|
||||
char ai_prom;
|
||||
|
||||
watch_clear_display();
|
||||
watch_start_character_blink('C', 100);
|
||||
SCL_gameGetRepetiotionMove(state->game, &rep_from, &rep_to);
|
||||
|
||||
#ifndef __EMSCRIPTEN__
|
||||
hri_oscctrl_write_OSC16MCTRL_FSEL_bf(OSCCTRL, OSCCTRL_OSC16MCTRL_FSEL_16_Val);
|
||||
#endif
|
||||
SCL_getAIMove(state->game, 3, 0, 0, SCL_boardEvaluateStatic, NULL, 0, rep_from, rep_to, &state->ai_from_square, &state->ai_to_square, &ai_prom);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
hri_oscctrl_write_OSC16MCTRL_FSEL_bf(OSCCTRL, OSCCTRL_OSC16MCTRL_FSEL_4_Val);
|
||||
#endif
|
||||
|
||||
SCL_gameMakeMove(state->game, state->ai_from_square, state->ai_to_square, ai_prom);
|
||||
watch_stop_blink();
|
||||
|
||||
watch_buzzer_play_sequence(cpu_done_beep, NULL);
|
||||
|
||||
/* cache the move as a string for SHOW_CPU_MOVE state */
|
||||
SCL_squareToString(state->ai_from_square, ai_from_str);
|
||||
SCL_squareToString(state->ai_to_square, ai_to_str);
|
||||
snprintf(state->last_move_str, sizeof(state->last_move_str), " %s-%s", ai_from_str, ai_to_str);
|
||||
|
||||
/* now cache the list of legal pieces we can move */
|
||||
_smallchess_calc_moveable_pieces(state);
|
||||
}
|
||||
|
||||
static char _smallchess_make_lowercase(char c) {
|
||||
if (c < 0x61)
|
||||
return c + 0x20;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static void _smallchess_get_endgame_string(smallchess_face_state_t *state, char *buf, uint8_t len) {
|
||||
uint8_t endgame_state = ((SCL_Game *)state->game)->state;
|
||||
uint16_t ply = ((SCL_Game *)state->game)->ply;
|
||||
|
||||
switch (endgame_state) {
|
||||
case SCL_GAME_STATE_WHITE_WIN:
|
||||
snprintf(buf, len, "Wh%2dm&ate ", ply);
|
||||
break;
|
||||
case SCL_GAME_STATE_BLACK_WIN:
|
||||
snprintf(buf, len, "bL%2dm&ate ", ply);
|
||||
break;
|
||||
case SCL_GAME_STATE_DRAW:
|
||||
case SCL_GAME_STATE_DRAW_STALEMATE:
|
||||
case SCL_GAME_STATE_DRAW_REPETITION:
|
||||
case SCL_GAME_STATE_DRAW_50:
|
||||
case SCL_GAME_STATE_DRAW_DEAD:
|
||||
snprintf(buf, len, " %2d Drauu", ply);
|
||||
break;
|
||||
default:
|
||||
snprintf(buf, len, " %2d Error", ply);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _smallchess_face_update_lcd(smallchess_face_state_t *state) {
|
||||
uint8_t start_square;
|
||||
uint8_t end_square;
|
||||
char start_coord[3] = {0};
|
||||
char end_coord[3] = {0};
|
||||
char buf[14] = {0};
|
||||
|
||||
uint16_t ply = ((SCL_Game *)state->game)->ply;
|
||||
|
||||
switch (state->state) {
|
||||
case SMALLCHESS_MENU_RESUME:
|
||||
snprintf(buf, sizeof(buf), "SC%2dResume", ply);
|
||||
break;
|
||||
case SMALLCHESS_MENU_UNDO:
|
||||
snprintf(buf, sizeof(buf), "SC%2d Undo ", ply);
|
||||
break;
|
||||
case SMALLCHESS_MENU_SHOW_LAST_MOVE:
|
||||
snprintf(buf, sizeof(buf), "SC%2dShLast", ply);
|
||||
break;
|
||||
case SMALLCHESS_MENU_NEW_WHITE:
|
||||
snprintf(buf, sizeof(buf), "Wh%2dStart ", ply);
|
||||
break;
|
||||
case SMALLCHESS_MENU_NEW_BLACK:
|
||||
snprintf(buf, sizeof(buf), "bL%2dStart ", ply);
|
||||
break;
|
||||
case SMALLCHESS_SHOW_CPU_MOVE:
|
||||
case SMALLCHESS_SHOW_LAST_MOVE:
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
"%c %2d%s",
|
||||
_smallchess_make_lowercase(((SCL_Game *)state->game)->board[state->ai_to_square]),
|
||||
ply,
|
||||
state->last_move_str);
|
||||
|
||||
break;
|
||||
case SMALLCHESS_SELECT_PIECE:
|
||||
if (((SCL_Game *)state->game)->state != SCL_GAME_STATE_PLAYING) {
|
||||
_smallchess_get_endgame_string(state, buf, sizeof(buf));
|
||||
break;
|
||||
}
|
||||
start_square = state->moveable_pieces[state->moveable_pieces_idx];
|
||||
SCL_squareToString(start_square, start_coord);
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
"%c %2d %s- ",
|
||||
_smallchess_make_lowercase(((SCL_Game *)state->game)->board[start_square]),
|
||||
ply + 1,
|
||||
start_coord);
|
||||
break;
|
||||
case SMALLCHESS_SELECT_DEST:
|
||||
start_square = state->moveable_pieces[state->moveable_pieces_idx];
|
||||
SCL_squareToString(start_square, start_coord);
|
||||
end_square = state->moveable_dests[state->moveable_dests_idx];
|
||||
SCL_squareToString(end_square, end_coord);
|
||||
snprintf(buf,
|
||||
sizeof(buf),
|
||||
"%c %2d %s-%s",
|
||||
_smallchess_make_lowercase(((SCL_Game *)state->game)->board[start_square]),
|
||||
ply + 1,
|
||||
start_coord,
|
||||
end_coord);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
static void _smallchess_select_main_menu_subitem(smallchess_face_state_t *state) {
|
||||
char from_str[3] = {0};
|
||||
char to_str[3] = {0};
|
||||
char prom;
|
||||
|
||||
switch (state->state) {
|
||||
case SMALLCHESS_MENU_RESUME:
|
||||
state->state = SMALLCHESS_SELECT_PIECE;
|
||||
break;
|
||||
case SMALLCHESS_MENU_UNDO:
|
||||
/* undo twice to undo the CPU's move and our move */
|
||||
SCL_gameUndoMove((SCL_Game *)state->game);
|
||||
SCL_gameUndoMove((SCL_Game *)state->game);
|
||||
/* and re-calculate the moveable pieces for this new state */
|
||||
_smallchess_calc_moveable_pieces(state);
|
||||
break;
|
||||
case SMALLCHESS_MENU_NEW_WHITE:
|
||||
SCL_gameInit((SCL_Game *)state->game, 0);
|
||||
_smallchess_calc_moveable_pieces(state);
|
||||
state->state = SMALLCHESS_SELECT_PIECE;
|
||||
break;
|
||||
case SMALLCHESS_MENU_NEW_BLACK:
|
||||
SCL_gameInit((SCL_Game *)state->game, 0);
|
||||
/* force a move since black is playing */
|
||||
_smallchess_make_ai_move(state);
|
||||
state->state = SMALLCHESS_SHOW_CPU_MOVE;
|
||||
break;
|
||||
case SMALLCHESS_MENU_SHOW_LAST_MOVE:
|
||||
/* fetch the move */
|
||||
SCL_recordGetMove(((SCL_Game *)state->game)->record, ((SCL_Game *)state->game)->ply - 1, &state->ai_from_square, &state->ai_to_square, &prom);
|
||||
SCL_squareToString(state->ai_from_square, from_str);
|
||||
SCL_squareToString(state->ai_to_square, to_str);
|
||||
snprintf(state->last_move_str, sizeof(state->last_move_str), " %s-%s", from_str, to_str);
|
||||
state->state = SMALLCHESS_SHOW_LAST_MOVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _smallchess_handle_select_piece_button_event(smallchess_face_state_t *state, movement_event_t event) {
|
||||
SCL_SquareSet moveable_dests = SCL_SQUARE_SET_EMPTY;
|
||||
|
||||
/* back to main menu on any event when game ends */
|
||||
if (((SCL_Game *)state->game)->state != SCL_GAME_STATE_PLAYING) {
|
||||
state->state = SMALLCHESS_MENU_RESUME;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
// check for no moves possible state (shouldn't happen but this will prevent weirdness)
|
||||
if (state->moveable_pieces[0] == PIECE_LIST_END_MARKER) {
|
||||
return;
|
||||
}
|
||||
|
||||
state->moveable_pieces_idx += 1;
|
||||
if (state->moveable_pieces_idx >= NUM_ELEMENTS(state->moveable_pieces)) {
|
||||
state->moveable_pieces_idx = 0;
|
||||
}
|
||||
|
||||
if (state->moveable_pieces[state->moveable_pieces_idx] == PIECE_LIST_END_MARKER) {
|
||||
state->moveable_pieces_idx = 0;
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
// check for no moves possible state (shouldn't happen but this will prevent weirdness)
|
||||
if (state->moveable_pieces[0] == PIECE_LIST_END_MARKER) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* handle wrap around */
|
||||
if (state->moveable_pieces_idx == 0) {
|
||||
for (unsigned int i = 0; i < NUM_ELEMENTS(state->moveable_pieces); i++) {
|
||||
if (state->moveable_pieces[i] == 0xff) {
|
||||
state->moveable_pieces_idx = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state->moveable_pieces_idx -= 1;
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
if (((SCL_Game *)state->game)->ply == 0) {
|
||||
state->state = SMALLCHESS_MENU_NEW_WHITE;
|
||||
} else {
|
||||
state->state = SMALLCHESS_MENU_RESUME;
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
/* pre-calculate the possible moves this piece can make */
|
||||
SCL_boardGetMoves(((SCL_Game *)state->game)->board, state->moveable_pieces[state->moveable_pieces_idx], moveable_dests);
|
||||
state->moveable_dests_idx = 0;
|
||||
SCL_SQUARE_SET_ITERATE_BEGIN(moveable_dests)
|
||||
state->moveable_dests[state->moveable_dests_idx] = iteratedSquare;
|
||||
state->moveable_dests_idx++;
|
||||
SCL_SQUARE_SET_ITERATE_END
|
||||
state->moveable_dests[state->moveable_dests_idx] = PIECE_LIST_END_MARKER;
|
||||
state->moveable_dests_idx = 0;
|
||||
state->state = SMALLCHESS_SELECT_DEST;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _smallchess_handle_select_dest_button_event(smallchess_face_state_t *state, movement_event_t event) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
// check for no moves possible state (shouldn't happen but this will prevent weirdness)
|
||||
if (state->moveable_dests[0] == PIECE_LIST_END_MARKER) {
|
||||
return;
|
||||
}
|
||||
state->moveable_dests_idx += 1;
|
||||
if (state->moveable_dests_idx >= (sizeof(state->moveable_dests) / sizeof(state->moveable_dests[0]))) {
|
||||
state->moveable_dests_idx = 0;
|
||||
}
|
||||
|
||||
if (state->moveable_dests[state->moveable_dests_idx] == PIECE_LIST_END_MARKER) {
|
||||
state->moveable_dests_idx = 0;
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
// check for no moves possible state (shouldn't happen but this will prevent weirdness)
|
||||
if (state->moveable_dests[0] == PIECE_LIST_END_MARKER) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* handle wrap around */
|
||||
if (state->moveable_dests_idx == 0) {
|
||||
for (unsigned int i = 0; i < NUM_ELEMENTS(state->moveable_dests); i++) {
|
||||
if (state->moveable_dests[i] == 0xff) {
|
||||
state->moveable_dests_idx = i - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
state->moveable_dests_idx -= 1;
|
||||
}
|
||||
break;
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
state->state = SMALLCHESS_SELECT_PIECE;
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
SCL_gameMakeMove((SCL_Game *)state->game, state->moveable_pieces[state->moveable_pieces_idx], state->moveable_dests[state->moveable_dests_idx], 'q');
|
||||
|
||||
/* if the player didn't win or draw here, calculate a move */
|
||||
if (((SCL_Game *)state->game)->state == SCL_GAME_STATE_PLAYING) {
|
||||
_smallchess_make_ai_move(state);
|
||||
state->state = SMALLCHESS_SHOW_CPU_MOVE;
|
||||
} else {
|
||||
/* player ended the game through mate or draw; jump to select piece screen to show state */
|
||||
state->state = SMALLCHESS_SELECT_PIECE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* this just waits until any button is hit */
|
||||
static void _smallchess_handle_show_cpu_move_button_event(smallchess_face_state_t *state, movement_event_t event) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
state->state = SMALLCHESS_SELECT_PIECE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _smallchess_handle_show_last_move_button_event(smallchess_face_state_t *state, movement_event_t event) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
state->state = SMALLCHESS_MENU_SHOW_LAST_MOVE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _smallchess_handle_playing_button_event(smallchess_face_state_t *state, movement_event_t event) {
|
||||
if (state->state == SMALLCHESS_SELECT_PIECE) {
|
||||
_smallchess_handle_select_piece_button_event(state, event);
|
||||
} else if (state->state == SMALLCHESS_SELECT_DEST) {
|
||||
_smallchess_handle_select_dest_button_event(state, event);
|
||||
} else if (state->state == SMALLCHESS_SHOW_CPU_MOVE) {
|
||||
_smallchess_handle_show_cpu_move_button_event(state, event);
|
||||
} else if (state->state == SMALLCHESS_SHOW_LAST_MOVE) {
|
||||
_smallchess_handle_show_last_move_button_event(state, event);
|
||||
}
|
||||
}
|
||||
|
||||
static void _smallchess_handle_main_menu_button_event(smallchess_face_state_t *state, movement_event_t event) {
|
||||
uint16_t ply = ((SCL_Game *)state->game)->ply;
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
/* no game started; only offer start white/start black */
|
||||
if (ply == 0) {
|
||||
if (state->state == SMALLCHESS_MENU_NEW_WHITE) {
|
||||
state->state = SMALLCHESS_MENU_NEW_BLACK;
|
||||
} else {
|
||||
state->state = SMALLCHESS_MENU_NEW_WHITE;
|
||||
}
|
||||
} else {
|
||||
state->state++;
|
||||
if (state->state >= SMALLCHESS_PLAYING_SPLIT) {
|
||||
state->state = SMALLCHESS_MENU_RESUME;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
/* no game started; only offer start white/start black */
|
||||
if (ply == 0) {
|
||||
if (state->state == SMALLCHESS_MENU_NEW_BLACK) {
|
||||
state->state = SMALLCHESS_MENU_NEW_WHITE;
|
||||
} else {
|
||||
state->state = SMALLCHESS_MENU_NEW_BLACK;
|
||||
}
|
||||
} else {
|
||||
if (state->state == SMALLCHESS_MENU_RESUME) {
|
||||
state->state = SMALLCHESS_PLAYING_SPLIT - 1;
|
||||
} else {
|
||||
state->state--;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
_smallchess_select_main_menu_subitem(state);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void _smallchess_handle_button_event(smallchess_face_state_t *state, movement_event_t event) {
|
||||
if (state->state < SMALLCHESS_PLAYING_SPLIT) {
|
||||
/* in main menu */
|
||||
_smallchess_handle_main_menu_button_event(state, event);
|
||||
} else if (state->state > SMALLCHESS_PLAYING_SPLIT) {
|
||||
/* in piece selection */
|
||||
_smallchess_handle_playing_button_event(state, event);
|
||||
}
|
||||
}
|
||||
|
||||
bool smallchess_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
smallchess_face_state_t *state = (smallchess_face_state_t *)context;
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
if (((SCL_Game *)state->game)->ply == 0) {
|
||||
state->state = SMALLCHESS_MENU_NEW_WHITE;
|
||||
} else {
|
||||
state->state = SMALLCHESS_MENU_RESUME;
|
||||
}
|
||||
_smallchess_face_update_lcd(state);
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
_smallchess_handle_button_event(state, event);
|
||||
_smallchess_face_update_lcd(state);
|
||||
break;
|
||||
case EVENT_TICK:
|
||||
break;
|
||||
case EVENT_TIMEOUT:
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
break;
|
||||
default:
|
||||
movement_default_loop_handler(event, settings);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void smallchess_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
watch_set_led_off();
|
||||
}
|
90
movement/watch_faces/complication/smallchess_face.h
Normal file
90
movement/watch_faces/complication/smallchess_face.h
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Jeremy O'Brien
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef SMALLCHESS_FACE_H_
|
||||
#define SMALLCHESS_FACE_H_
|
||||
|
||||
#include "movement.h"
|
||||
|
||||
/*
|
||||
* Chess watchface
|
||||
*
|
||||
* Implements a (very) simple chess engine.
|
||||
* Uses smallchesslib for the engine: https://codeberg.org/drummyfish/smallchesslib
|
||||
*
|
||||
* When moving a piece, only valid pieces and moves are presented.
|
||||
*
|
||||
* Interaction is done through a simple menu/submenu system:
|
||||
* - Light button: navigate backwards through the current menu
|
||||
* - Alarm button: navigate forwards through the current menu
|
||||
* - Light button (long press): navigate up to the parent menu
|
||||
* - Alarm button (long press): select the current item or submenu
|
||||
*/
|
||||
|
||||
enum smallchess_state {
|
||||
/* main menu */
|
||||
SMALLCHESS_MENU_RESUME,
|
||||
SMALLCHESS_MENU_SHOW_LAST_MOVE,
|
||||
SMALLCHESS_MENU_UNDO,
|
||||
SMALLCHESS_MENU_NEW_WHITE,
|
||||
SMALLCHESS_MENU_NEW_BLACK,
|
||||
|
||||
SMALLCHESS_PLAYING_SPLIT,
|
||||
|
||||
/* playing game submenu */
|
||||
SMALLCHESS_SHOW_LAST_MOVE,
|
||||
SMALLCHESS_SHOW_CPU_MOVE,
|
||||
SMALLCHESS_SELECT_PIECE,
|
||||
SMALLCHESS_SELECT_DEST,
|
||||
};
|
||||
|
||||
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof(a[0]))
|
||||
#define SMALLCHESS_NUM_PIECES 16 // number of pieces each player has
|
||||
|
||||
typedef struct {
|
||||
void *game;
|
||||
enum smallchess_state state;
|
||||
uint8_t moveable_pieces[SMALLCHESS_NUM_PIECES + 1];
|
||||
uint8_t moveable_pieces_idx;
|
||||
uint8_t moveable_dests[29]; // this magic number represents the maximum number of moves a piece can make (queen in center of board)
|
||||
// plus one for the end list marker
|
||||
uint8_t moveable_dests_idx;
|
||||
char last_move_str[7];
|
||||
uint8_t ai_from_square, ai_to_square;
|
||||
} smallchess_face_state_t;
|
||||
|
||||
void smallchess_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void smallchess_face_activate(movement_settings_t *settings, void *context);
|
||||
bool smallchess_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void smallchess_face_resign(movement_settings_t *settings, void *context);
|
||||
|
||||
#define smallchess_face ((const watch_face_t){ \
|
||||
smallchess_face_setup, \
|
||||
smallchess_face_activate, \
|
||||
smallchess_face_loop, \
|
||||
smallchess_face_resign, \
|
||||
NULL, \
|
||||
})
|
||||
|
||||
#endif // SMALLCHESS_FACE_H_
|
@ -45,7 +45,7 @@ static void _sunrise_sunset_set_expiration(sunrise_sunset_state_t *state, watch_
|
||||
}
|
||||
|
||||
static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_sunset_state_t *state) {
|
||||
char buf[14];
|
||||
char buf[11];
|
||||
double rise, set, minutes, seconds;
|
||||
bool show_next_match = false;
|
||||
movement_location_t movement_location;
|
||||
@ -87,7 +87,7 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s
|
||||
watch_clear_colon();
|
||||
watch_clear_indicator(WATCH_INDICATOR_PM);
|
||||
watch_clear_indicator(WATCH_INDICATOR_24H);
|
||||
sprintf(buf, "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day);
|
||||
snprintf(buf, sizeof(buf), "%s%2d none ", (result == 1) ? "SE" : "rI", scratch_time.unit.day);
|
||||
watch_display_string(buf, 0);
|
||||
return;
|
||||
}
|
||||
@ -120,7 +120,7 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s
|
||||
} else if (settings->bit.clock_24h_leading_zero && scratch_time.unit.hour < 10) {
|
||||
set_leading_zero = true;
|
||||
}
|
||||
sprintf(buf, "rI%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute,longLatPresets[state->longLatToUse].name);
|
||||
snprintf(buf, sizeof(buf), "rI%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute,longLatPresets[state->longLatToUse].name);
|
||||
watch_display_string(buf, 0);
|
||||
if (set_leading_zero)
|
||||
watch_display_string("0", 4);
|
||||
@ -152,7 +152,7 @@ static void _sunrise_sunset_face_update(movement_settings_t *settings, sunrise_s
|
||||
} else if (settings->bit.clock_24h_leading_zero && scratch_time.unit.hour < 10) {
|
||||
set_leading_zero = true;
|
||||
}
|
||||
sprintf(buf, "SE%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute, longLatPresets[state->longLatToUse].name);
|
||||
snprintf(buf, sizeof(buf), "SE%2d%2d%02d%s", scratch_time.unit.day, scratch_time.unit.hour, scratch_time.unit.minute, longLatPresets[state->longLatToUse].name);
|
||||
watch_display_string(buf, 0);
|
||||
if (set_leading_zero)
|
||||
watch_display_string("0", 4);
|
||||
@ -212,16 +212,16 @@ static void _sunrise_sunset_face_update_location_register(sunrise_sunset_state_t
|
||||
}
|
||||
|
||||
static void _sunrise_sunset_face_update_settings_display(movement_event_t event, sunrise_sunset_state_t *state) {
|
||||
char buf[12];
|
||||
char buf[11];
|
||||
|
||||
switch (state->page) {
|
||||
case 0:
|
||||
return;
|
||||
case 1:
|
||||
sprintf(buf, "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)));
|
||||
snprintf(buf, sizeof(buf), "LA %c %04d", state->working_latitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_latitude)));
|
||||
break;
|
||||
case 2:
|
||||
sprintf(buf, "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)));
|
||||
snprintf(buf, sizeof(buf), "LO %c%05d", state->working_longitude.sign ? '-' : '+', abs(_sunrise_sunset_face_latlon_from_struct(state->working_longitude)));
|
||||
break;
|
||||
}
|
||||
if (event.subsecond % 2) {
|
||||
|
234
movement/watch_faces/complication/wareki_face.c
Normal file
234
movement/watch_faces/complication/wareki_face.c
Normal file
@ -0,0 +1,234 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "wareki_face.h"
|
||||
#include "filesystem.h"
|
||||
#include "watch_utility.h"
|
||||
|
||||
|
||||
//Long press status flag
|
||||
static bool _alarm_button_press;
|
||||
static bool _light_button_press;
|
||||
|
||||
|
||||
void wareki_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) watch_face_index;
|
||||
|
||||
//printf("wareki_setup() \n");
|
||||
(void) settings;
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(wareki_state_t));
|
||||
memset(*context_ptr, 0, sizeof(wareki_state_t));
|
||||
// Do any one-time tasks in here; the inside of this conditional happens only at boot.
|
||||
|
||||
//debug code
|
||||
// watch_date_time datetime = watch_rtc_get_date_time();
|
||||
// datetime.unit.year = 2022 - WATCH_RTC_REFERENCE_YEAR;
|
||||
// datetime.unit.month = 12;
|
||||
// datetime.unit.day = 31;
|
||||
// datetime.unit.hour = 23;
|
||||
// datetime.unit.minute= 59;
|
||||
// datetime.unit.second= 30;
|
||||
// watch_rtc_set_date_time(datetime);
|
||||
// settings->bit.clock_mode_24h = true; //24時間表記
|
||||
// settings->bit.to_interval = 1;//0=60sec 1=2m 2=5m 3=30m
|
||||
// watch_store_backup_data(settings->reg, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// splash view
|
||||
static void draw_wareki_splash(wareki_state_t *state) {
|
||||
(void) state;
|
||||
char buf[11];
|
||||
|
||||
watch_clear_colon();
|
||||
|
||||
sprintf(buf, "%s","wa ------");
|
||||
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
|
||||
//draw year and Japanese wareki
|
||||
static void draw_year_and_wareki(wareki_state_t *state) {
|
||||
char buf[27];
|
||||
|
||||
if(state->disp_year < REIWA_GANNEN){
|
||||
//Heisei
|
||||
sprintf(buf, " h%2d%4d ", (int)state->disp_year - HEISEI_GANNEN + 1, (int)state->disp_year);
|
||||
}
|
||||
else{
|
||||
//Reiwa
|
||||
sprintf(buf, " r%2d%4d ", (int)state->disp_year - REIWA_GANNEN + 1 , (int)state->disp_year);
|
||||
}
|
||||
watch_display_string(buf, 0);
|
||||
}
|
||||
|
||||
|
||||
void wareki_activate(movement_settings_t *settings, void *context) {
|
||||
|
||||
//printf("wareki_activate() \n");
|
||||
|
||||
(void) settings;
|
||||
wareki_state_t *state = (wareki_state_t *)context;
|
||||
|
||||
if (watch_tick_animation_is_running()) watch_stop_tick_animation();
|
||||
|
||||
state->active = false;
|
||||
|
||||
_alarm_button_press = false;
|
||||
_light_button_press = false;
|
||||
|
||||
state->real_year = watch_rtc_get_date_time().unit.year + WATCH_RTC_REFERENCE_YEAR;
|
||||
state->start_year = state->real_year;
|
||||
state->disp_year = state->real_year;
|
||||
|
||||
movement_request_tick_frequency(1);
|
||||
}
|
||||
|
||||
|
||||
void addYear(wareki_state_t* state,int count){
|
||||
|
||||
state->disp_year = state->disp_year + count;
|
||||
|
||||
if(state->disp_year > REIWA_LIMIT ){
|
||||
state->disp_year = REIWA_LIMIT;
|
||||
}
|
||||
else{
|
||||
//watch_buzzer_play_note(BUZZER_NOTE_C8, 30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void subYear(wareki_state_t* state,int count){
|
||||
|
||||
state->disp_year = state->disp_year - count;
|
||||
|
||||
if(state->disp_year < 1989 ){
|
||||
state->disp_year = 1989;
|
||||
}
|
||||
else{
|
||||
//watch_buzzer_play_note(BUZZER_NOTE_C7, 30);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool wareki_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
wareki_state_t *state = (wareki_state_t *)context;
|
||||
|
||||
state->real_year = watch_rtc_get_date_time().unit.year + WATCH_RTC_REFERENCE_YEAR;
|
||||
|
||||
if( state->real_year != state->start_year ){
|
||||
state->start_year = state->real_year;
|
||||
state->disp_year = state->real_year;
|
||||
}
|
||||
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
draw_wareki_splash(state);
|
||||
break;
|
||||
case EVENT_MODE_BUTTON_UP:
|
||||
movement_move_to_next_face();
|
||||
break;
|
||||
|
||||
case EVENT_LOW_ENERGY_UPDATE:
|
||||
case EVENT_TICK:
|
||||
|
||||
//printf("tick %d\n",state->disp_year );
|
||||
|
||||
if (_alarm_button_press && watch_get_pin_level(BTN_ALARM)){
|
||||
//printf("ALARM ON\n");
|
||||
}
|
||||
else{
|
||||
//printf("ALARM OFF\n");
|
||||
_alarm_button_press = false;
|
||||
}
|
||||
|
||||
if (_light_button_press && watch_get_pin_level(BTN_LIGHT)){
|
||||
//printf("LIGHT ON\n");
|
||||
}
|
||||
else{
|
||||
//printf("LIGHT OFF\n");
|
||||
_light_button_press = false;
|
||||
}
|
||||
|
||||
if (_alarm_button_press) {
|
||||
addYear(state,1);
|
||||
}
|
||||
if (_light_button_press) {
|
||||
subYear(state,1);
|
||||
}
|
||||
|
||||
draw_year_and_wareki(state);
|
||||
|
||||
break;
|
||||
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
//printf("LIGHT DOWN\n");
|
||||
subYear(state,1);
|
||||
break;
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
//printf("LIGHTPRESS \n");
|
||||
_light_button_press = true;
|
||||
movement_request_tick_frequency(8);
|
||||
break;
|
||||
case EVENT_LIGHT_LONG_UP:
|
||||
//printf("LIGHTPRESS UP\n");
|
||||
_light_button_press = false;
|
||||
movement_request_tick_frequency(4);
|
||||
break;
|
||||
case EVENT_LIGHT_BUTTON_UP:
|
||||
//printf("LIGHT UP\n");
|
||||
_light_button_press = false;
|
||||
movement_request_tick_frequency(4);
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_DOWN:
|
||||
//printf("ALARM DOWN\n");
|
||||
addYear(state,1);
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
//printf("LONGPRESS \n");
|
||||
_alarm_button_press = true;
|
||||
movement_request_tick_frequency(8);
|
||||
break;
|
||||
case EVENT_ALARM_LONG_UP:
|
||||
//printf("LONGPRESS UP\n");
|
||||
_alarm_button_press = false;
|
||||
movement_request_tick_frequency(4);
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
//printf("ALARM UP\n");
|
||||
movement_request_tick_frequency(4);
|
||||
break;
|
||||
|
||||
case EVENT_TIMEOUT:
|
||||
//printf("time out ! \n");
|
||||
movement_move_to_face(0);
|
||||
|
||||
|
||||
break;
|
||||
//case EVENT_LOW_ENERGY_UPDATE:
|
||||
// If you did not resign in EVENT_TIMEOUT, you can use this event to update the display once a minute.
|
||||
// Avoid displaying fast-updating values like seconds, since the display won't update again for 60 seconds.
|
||||
// You should also consider starting the tick animation, to show the wearer that this is sleep mode:
|
||||
// watch_start_tick_animation(500);
|
||||
//break;
|
||||
default:
|
||||
// Movement's default loop handler will step in for any cases you don't handle above:
|
||||
// * EVENT_LIGHT_BUTTON_DOWN lights the LED
|
||||
// * EVENT_MODE_BUTTON_UP moves to the next watch face in the list
|
||||
// * EVENT_MODE_LONG_PRESS returns to the first watch face (or skips to the secondary watch face, if configured)
|
||||
// You can override any of these behaviors by adding a case for these events to this switch statement.
|
||||
return movement_default_loop_handler(event, settings);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void wareki_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
}
|
||||
|
34
movement/watch_faces/complication/wareki_face.h
Normal file
34
movement/watch_faces/complication/wareki_face.h
Normal file
@ -0,0 +1,34 @@
|
||||
#ifndef WAREKI_FACE_H_
|
||||
#define WAREKI_FACE_H_
|
||||
|
||||
#include "movement.h"
|
||||
|
||||
#define REIWA_LIMIT 2018 + 31
|
||||
#define REIWA_GANNEN 2019
|
||||
#define HEISEI_GANNEN 1989
|
||||
|
||||
typedef struct {
|
||||
bool active;
|
||||
uint32_t disp_year; //Current displayed year
|
||||
uint32_t start_year; //Year when this screen was launched
|
||||
uint32_t real_year; //The actual current year
|
||||
} wareki_state_t;
|
||||
|
||||
|
||||
void wareki_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void wareki_activate(movement_settings_t *settings, void *context);
|
||||
bool wareki_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void wareki_resign(movement_settings_t *settings, void *context);
|
||||
void addYear(wareki_state_t* state,int count);
|
||||
void subYear(wareki_state_t* state,int count);
|
||||
|
||||
#define wareki_face ((const watch_face_t){ \
|
||||
wareki_setup, \
|
||||
wareki_activate, \
|
||||
wareki_loop, \
|
||||
wareki_resign, \
|
||||
NULL, \
|
||||
})
|
||||
|
||||
#endif // WAREKI_FACE_H_
|
||||
|
@ -38,7 +38,7 @@ void beeps_face_setup(movement_settings_t *settings, uint8_t watch_face_index, v
|
||||
|
||||
void beeps_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
beeps_state_t *state = (beeps_state_t *)context;
|
||||
(void) context;
|
||||
}
|
||||
|
||||
static void _beep_face_update_lcd(beeps_state_t *state) {
|
||||
|
@ -94,6 +94,7 @@ static void _lis2dw_logging_face_update_display(movement_settings_t *settings, l
|
||||
watch_display_string(buf, 0);
|
||||
if (set_leading_zero)
|
||||
watch_display_string("0", 4);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
static void _lis2dw_logging_face_log_data(lis2dw_logger_state_t *logger_state) {
|
||||
@ -142,7 +143,7 @@ void lis2dw_logging_face_activate(movement_settings_t *settings, void *context)
|
||||
|
||||
logger_state->display_index = 0;
|
||||
logger_state->log_ticks = 0;
|
||||
watch_enable_digital_input(A0);
|
||||
watch_enable_digital_input(A4);
|
||||
}
|
||||
|
||||
bool lis2dw_logging_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
@ -196,7 +197,7 @@ bool lis2dw_logging_face_loop(movement_event_t event, movement_settings_t *setti
|
||||
void lis2dw_logging_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
watch_disable_digital_input(A0);
|
||||
watch_disable_digital_input(A4);
|
||||
}
|
||||
|
||||
bool lis2dw_logging_face_wants_background_task(movement_settings_t *settings, void *context) {
|
||||
|
162
movement/watch_faces/sensor/accel_interrupt_count_face.c
Normal file
162
movement/watch_faces/sensor/accel_interrupt_count_face.c
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Joey Castillo
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "accel_interrupt_count_face.h"
|
||||
#include "lis2dw.h"
|
||||
#include "watch.h"
|
||||
|
||||
// hacky hacky!
|
||||
uint32_t *ptr_to_count = 0;
|
||||
|
||||
void accel_interrupt_handler(void);
|
||||
void accel_interrupt_handler(void) {
|
||||
(*ptr_to_count)++;
|
||||
}
|
||||
|
||||
static void _accel_interrupt_count_face_update_display(accel_interrupt_count_state_t *state) {
|
||||
char buf[11];
|
||||
|
||||
if (state->running) {
|
||||
watch_set_indicator(WATCH_INDICATOR_SIGNAL);
|
||||
} else {
|
||||
watch_clear_indicator(WATCH_INDICATOR_SIGNAL);
|
||||
}
|
||||
|
||||
// "AC"celerometer "IN"terrupts
|
||||
snprintf(buf, 11, "AC1N%6ld", state->count);
|
||||
watch_display_string(buf, 0);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
|
||||
static void _accel_interrupt_count_face_configure_threshold(uint8_t threshold) {
|
||||
lis2dw_configure_wakeup_int1(threshold, false, true);
|
||||
}
|
||||
|
||||
void accel_interrupt_count_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) settings;
|
||||
(void) watch_face_index;
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(accel_interrupt_count_state_t));
|
||||
memset(*context_ptr, 0, sizeof(accel_interrupt_count_state_t));
|
||||
ptr_to_count = &((accel_interrupt_count_state_t *)*context_ptr)->count;
|
||||
watch_enable_i2c();
|
||||
lis2dw_begin();
|
||||
lis2dw_set_low_power_mode(LIS2DW_LP_MODE_2); // lowest power 14-bit mode, 25 Hz is 3.5 µA @ 1.8V w/ low noise, 3µA without
|
||||
lis2dw_set_low_noise_mode(true); // consumes a little more power
|
||||
lis2dw_set_range(LIS2DW_CTRL6_VAL_RANGE_4G);
|
||||
lis2dw_set_data_rate(LIS2DW_DATA_RATE_25_HZ); // is this enough?
|
||||
|
||||
// threshold is 1/64th of full scale, so for a FS of ±4G this is 1.25G
|
||||
((accel_interrupt_count_state_t *)*context_ptr)->threshold = 10;
|
||||
_accel_interrupt_count_face_configure_threshold(((accel_interrupt_count_state_t *)*context_ptr)->threshold);
|
||||
}
|
||||
}
|
||||
|
||||
void accel_interrupt_count_face_activate(movement_settings_t *settings, void *context) {
|
||||
accel_interrupt_count_state_t *state = (accel_interrupt_count_state_t *)context;
|
||||
|
||||
// never in settings mode at the start
|
||||
state->is_setting = false;
|
||||
|
||||
// force LE interval to never sleep
|
||||
settings->bit.le_interval = 0;
|
||||
}
|
||||
|
||||
bool accel_interrupt_count_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
accel_interrupt_count_state_t *state = (accel_interrupt_count_state_t *)context;
|
||||
|
||||
if (state->is_setting) {
|
||||
switch (event.event_type) {
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
state->new_threshold = (state->new_threshold + 1) % 64;
|
||||
// fall through
|
||||
case EVENT_TICK:
|
||||
{
|
||||
char buf[11];
|
||||
snprintf(buf, 11, "TH %4d ", state->new_threshold);
|
||||
watch_display_string(buf, 0);
|
||||
printf("%s\n", buf);
|
||||
}
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
lis2dw_configure_wakeup_int1(state->threshold, false, true);
|
||||
state->threshold = state->new_threshold;
|
||||
state->is_setting = false;
|
||||
break;
|
||||
default:
|
||||
movement_default_loop_handler(event, settings);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (event.event_type) {
|
||||
case EVENT_LIGHT_BUTTON_DOWN:
|
||||
movement_illuminate_led();
|
||||
|
||||
// if stopped, reset the count
|
||||
if (!state->running) {
|
||||
state->count = 0;
|
||||
}
|
||||
_accel_interrupt_count_face_update_display(state);
|
||||
break;
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
if (state->running) {
|
||||
state->running = false;
|
||||
watch_register_interrupt_callback(A4, NULL, INTERRUPT_TRIGGER_RISING);
|
||||
} else {
|
||||
state->running = true;
|
||||
watch_register_interrupt_callback(A4, accel_interrupt_handler, INTERRUPT_TRIGGER_RISING);
|
||||
}
|
||||
_accel_interrupt_count_face_update_display(state);
|
||||
break;
|
||||
case EVENT_ACTIVATE:
|
||||
case EVENT_TICK:
|
||||
_accel_interrupt_count_face_update_display(state);
|
||||
break;
|
||||
case EVENT_ALARM_LONG_PRESS:
|
||||
if (!state->running) {
|
||||
state->new_threshold = state->threshold;
|
||||
state->is_setting = true;
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
movement_default_loop_handler(event, settings);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void accel_interrupt_count_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
}
|
||||
|
||||
bool accel_interrupt_count_face_wants_background_task(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
return false;
|
||||
}
|
58
movement/watch_faces/sensor/accel_interrupt_count_face.h
Normal file
58
movement/watch_faces/sensor/accel_interrupt_count_face.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2022 Joey Castillo
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* Accelerometer Interrupt Counter
|
||||
*
|
||||
* This is an experimental watch face for counting the number of interrupts that
|
||||
* the Sensor Watch Motion acceleromoeter board fires. I expect it will be removed
|
||||
* once we integrate accelerometer functionality more deeply into Movement.
|
||||
*/
|
||||
|
||||
#include "movement.h"
|
||||
#include "watch.h"
|
||||
|
||||
typedef struct {
|
||||
uint32_t count;
|
||||
uint8_t new_threshold;
|
||||
uint8_t threshold;
|
||||
bool running;
|
||||
bool is_setting;
|
||||
} accel_interrupt_count_state_t;
|
||||
|
||||
void accel_interrupt_count_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void accel_interrupt_count_face_activate(movement_settings_t *settings, void *context);
|
||||
bool accel_interrupt_count_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void accel_interrupt_count_face_resign(movement_settings_t *settings, void *context);
|
||||
bool accel_interrupt_count_face_wants_background_task(movement_settings_t *settings, void *context);
|
||||
|
||||
#define accel_interrupt_count_face ((const watch_face_t){ \
|
||||
accel_interrupt_count_face_setup, \
|
||||
accel_interrupt_count_face_activate, \
|
||||
accel_interrupt_count_face_loop, \
|
||||
accel_interrupt_count_face_resign, \
|
||||
accel_interrupt_count_face_wants_background_task, \
|
||||
})
|
154
movement/watch_faces/sensor/minmax_face.c
Normal file
154
movement/watch_faces/sensor/minmax_face.c
Normal file
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Mark Blyth
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "minmax_face.h"
|
||||
#include "thermistor_driver.h"
|
||||
#include "watch.h"
|
||||
|
||||
|
||||
static float _get_displayed_temperature_c(minmax_state_t *state){
|
||||
float min_temp = 1000;
|
||||
float max_temp = -1000;
|
||||
for(int i = 0; i < LOGGING_DATA_POINTS; i++){
|
||||
if(state->hourly_maxs[i] > max_temp){
|
||||
max_temp = state->hourly_maxs[i];
|
||||
}
|
||||
if(state->hourly_mins[i] < min_temp){
|
||||
min_temp = state->hourly_mins[i];
|
||||
}
|
||||
}
|
||||
if(state->show_min) return min_temp;
|
||||
return max_temp;
|
||||
}
|
||||
|
||||
|
||||
static void _minmax_face_log_data(minmax_state_t *logger_state) {
|
||||
thermistor_driver_enable();
|
||||
size_t pos = (size_t) watch_rtc_get_date_time().unit.hour;
|
||||
float temp_c = thermistor_driver_get_temperature();
|
||||
// If no data yet, initialise with current temperature
|
||||
if(!logger_state->have_logged){
|
||||
logger_state->have_logged = true;
|
||||
for(int i=0; i<LOGGING_DATA_POINTS; i++){
|
||||
logger_state->hourly_mins[i] = temp_c;
|
||||
logger_state->hourly_maxs[i] = temp_c;
|
||||
}
|
||||
}
|
||||
// On new hour, update lists to current temperature
|
||||
else if(watch_rtc_get_date_time().unit.minute < 2){
|
||||
logger_state->hourly_mins[pos] = temp_c;
|
||||
logger_state->hourly_maxs[pos] = temp_c;
|
||||
}
|
||||
// Log hourly highs and lows
|
||||
else if(logger_state->hourly_mins[pos] > temp_c){
|
||||
logger_state->hourly_mins[pos] = temp_c;
|
||||
}
|
||||
else if(logger_state->hourly_maxs[pos] < temp_c){
|
||||
logger_state->hourly_maxs[pos] = temp_c;
|
||||
}
|
||||
thermistor_driver_disable();
|
||||
}
|
||||
|
||||
static void _minmax_face_update_display(float temperature_c, bool in_fahrenheit) {
|
||||
char buf[14];
|
||||
if (in_fahrenheit) {
|
||||
sprintf(buf, "%4.0f#F", temperature_c * 1.8 + 32.0);
|
||||
} else {
|
||||
sprintf(buf, "%4.0f#C", temperature_c);
|
||||
}
|
||||
watch_display_string(buf, 4);
|
||||
}
|
||||
|
||||
|
||||
void minmax_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) {
|
||||
(void) settings;
|
||||
(void) watch_face_index;
|
||||
if (*context_ptr == NULL) {
|
||||
*context_ptr = malloc(sizeof(minmax_state_t));
|
||||
memset(*context_ptr, 0, sizeof(minmax_state_t));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void minmax_face_activate(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
minmax_state_t *state = (minmax_state_t *)context;
|
||||
state->show_min = true;
|
||||
watch_display_string("MN", 0); // Start with minimum temp
|
||||
}
|
||||
|
||||
bool minmax_face_loop(movement_event_t event, movement_settings_t *settings, void *context) {
|
||||
minmax_state_t *state = (minmax_state_t *)context;
|
||||
float temp_c;
|
||||
|
||||
switch (event.event_type) {
|
||||
case EVENT_ACTIVATE:
|
||||
temp_c = _get_displayed_temperature_c(state);
|
||||
_minmax_face_update_display(temp_c, settings->bit.use_imperial_units);
|
||||
break;
|
||||
|
||||
case EVENT_LIGHT_LONG_PRESS:
|
||||
settings->bit.use_imperial_units = !settings->bit.use_imperial_units;
|
||||
temp_c = _get_displayed_temperature_c(state);
|
||||
_minmax_face_update_display(temp_c, settings->bit.use_imperial_units);
|
||||
break;
|
||||
|
||||
case EVENT_ALARM_BUTTON_UP:
|
||||
state->show_min = !state->show_min;
|
||||
if(state->show_min){
|
||||
watch_display_string("MN", 0);
|
||||
} else {
|
||||
watch_display_string("MX", 0);
|
||||
}
|
||||
temp_c = _get_displayed_temperature_c(state);
|
||||
_minmax_face_update_display(temp_c, settings->bit.use_imperial_units);
|
||||
break;
|
||||
|
||||
case EVENT_TIMEOUT:
|
||||
movement_move_to_face(0);
|
||||
break;
|
||||
case EVENT_BACKGROUND_TASK:
|
||||
_minmax_face_log_data(state);
|
||||
break;
|
||||
default:
|
||||
return movement_default_loop_handler(event, settings);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void minmax_face_resign(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
}
|
||||
|
||||
|
||||
bool minmax_face_wants_background_task(movement_settings_t *settings, void *context) {
|
||||
(void) settings;
|
||||
(void) context;
|
||||
// this will get called at the top of each minute; always request bg task
|
||||
return true;
|
||||
}
|
69
movement/watch_faces/sensor/minmax_face.h
Normal file
69
movement/watch_faces/sensor/minmax_face.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2023 Mark Blyth
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef MINMAX_FACE_H_
|
||||
#define MINMAX_FACE_H_
|
||||
|
||||
#include "movement.h"
|
||||
#include "watch.h"
|
||||
|
||||
#define LOGGING_DATA_POINTS (24)
|
||||
|
||||
/*
|
||||
* Log for the min. and max. temperature over the last 24h.
|
||||
*
|
||||
* Temperature is logged once a minute, every minute. Results are
|
||||
* stored, noting the highest and lowest temperatures observed within
|
||||
* any given hour. The watch face then displays the minimum or maximum
|
||||
* temperature recorded over the last 24h.
|
||||
*
|
||||
* A long press of the light button changes units between Celsius and
|
||||
* Fahrenheit. Pressing the alarm button switches between displaying the
|
||||
* minimum and maximum observed temperatures. If no buttons are pressed,
|
||||
* the watch face will eventually time out and return home.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
bool show_min;
|
||||
bool have_logged;
|
||||
float hourly_mins[LOGGING_DATA_POINTS];
|
||||
float hourly_maxs[LOGGING_DATA_POINTS];
|
||||
} minmax_state_t;
|
||||
|
||||
void minmax_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr);
|
||||
void minmax_face_activate(movement_settings_t *settings, void *context);
|
||||
bool minmax_face_loop(movement_event_t event, movement_settings_t *settings, void *context);
|
||||
void minmax_face_resign(movement_settings_t *settings, void *context);
|
||||
bool minmax_face_wants_background_task(movement_settings_t *settings, void *context);
|
||||
|
||||
#define minmax_face ((const watch_face_t){ \
|
||||
minmax_face_setup, \
|
||||
minmax_face_activate, \
|
||||
minmax_face_loop, \
|
||||
minmax_face_resign, \
|
||||
minmax_face_wants_background_task, \
|
||||
})
|
||||
|
||||
#endif // MINMAX_FACE_H_
|
||||
|
@ -97,6 +97,16 @@ void watch_enable_analog_input(const uint8_t pin) {
|
||||
case A4:
|
||||
gpio_set_pin_function(pin, PINMUX_PB00B_ADC_AIN8);
|
||||
break;
|
||||
#ifdef TEMPSENSE
|
||||
case TEMPSENSE:
|
||||
gpio_set_pin_function(pin, PINMUX_PA03B_ADC_AIN1);
|
||||
break;
|
||||
#endif
|
||||
#ifdef IRSENSE
|
||||
case IRSENSE:
|
||||
gpio_set_pin_function(pin, PINMUX_PA04B_ADC_AIN4);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return;
|
||||
}
|
||||
@ -114,7 +124,15 @@ uint16_t watch_get_analog_pin_level(const uint8_t pin) {
|
||||
return _watch_get_analog_value(ADC_INPUTCTRL_MUXPOS_AIN11_Val);
|
||||
case A4:
|
||||
return _watch_get_analog_value(ADC_INPUTCTRL_MUXPOS_AIN8_Val);
|
||||
default:
|
||||
#ifdef TEMPSENSE
|
||||
case TEMPSENSE:
|
||||
return _watch_get_analog_value(ADC_INPUTCTRL_MUXPOS_AIN1_Val);
|
||||
#endif
|
||||
#ifdef IRSENSE
|
||||
case IRSENSE:
|
||||
return _watch_get_analog_value(ADC_INPUTCTRL_MUXPOS_AIN4_Val);
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user