diff --git a/.gitignore b/.gitignore index 06256b71..6b2c0902 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,11 @@ .idea/ .vs .vscode -docs/ \ No newline at end of file +docs/ +*.kicad_sch-bak +*-backups/ +*.bak +_autosave* +fp-info-cache +.~* +*.plan diff --git a/PCB/Sensor Boards/BMI270-SensorBoard.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Community/BMI270-SensorBoard.brd similarity index 100% rename from PCB/Sensor Boards/BMI270-SensorBoard.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Community/BMI270-SensorBoard.brd diff --git a/PCB/Sensor Boards/BMI270-SensorBoard.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Community/BMI270-SensorBoard.sch similarity index 100% rename from PCB/Sensor Boards/BMI270-SensorBoard.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Community/BMI270-SensorBoard.sch diff --git a/PCB/Sensor Boards/OSO-SWAB-A1-00 Temperature + Test Points.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Shipped/OSO-SWAB-A1-00 Temperature + Test Points.brd similarity index 100% rename from PCB/Sensor Boards/OSO-SWAB-A1-00 Temperature + Test Points.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Shipped/OSO-SWAB-A1-00 Temperature + Test Points.brd diff --git a/PCB/Sensor Boards/OSO-SWAB-A1-00 Temperature + Test Points.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Shipped/OSO-SWAB-A1-00 Temperature + Test Points.sch similarity index 100% rename from PCB/Sensor Boards/OSO-SWAB-A1-00 Temperature + Test Points.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Shipped/OSO-SWAB-A1-00 Temperature + Test Points.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-002 Sensor Watch Environment.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-002 Sensor Watch Environment.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-002 Sensor Watch Environment.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-002 Sensor Watch Environment.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-002 Sensor Watch Environment.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-002 Sensor Watch Environment.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-002 Sensor Watch Environment.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-002 Sensor Watch Environment.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-016 Power Test.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-016 Power Test.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-016 Power Test.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-016 Power Test.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-016 Power Test.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-016 Power Test.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-016 Power Test.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-016 Power Test.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-017 Sensor Watch Flash.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-017 Sensor Watch Flash.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-017 Sensor Watch Flash.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-017 Sensor Watch Flash.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-017 Sensor Watch Flash.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-017 Sensor Watch Flash.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-017 Sensor Watch Flash.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-017 Sensor Watch Flash.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-019 Sensor Watch Test.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-019 Sensor Watch Test.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-019 Sensor Watch Test.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-019 Sensor Watch Test.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-019 Sensor Watch Test.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-019 Sensor Watch Test.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-019 Sensor Watch Test.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-019 Sensor Watch Test.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-021 Sensor Watch Motion II.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-021 Sensor Watch Motion II.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-021 Sensor Watch Motion II.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-021 Sensor Watch Motion II.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-021 Sensor Watch Motion II.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-021 Sensor Watch Motion II.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-021 Sensor Watch Motion II.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-21-021 Sensor Watch Motion II.sch diff --git a/PCB/Sensor Boards/OSO-MISC-22-005 UART Breakout.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-22-005 UART Breakout.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-005 UART Breakout.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-22-005 UART Breakout.brd diff --git a/PCB/Sensor Boards/OSO-MISC-22-005 UART Breakout.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-22-005 UART Breakout.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-005 UART Breakout.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Tested/OSO-MISC-22-005 UART Breakout.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-001 Sensor Watch Express.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-001 Sensor Watch Express.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-001 Sensor Watch Express.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-001 Sensor Watch Express.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-001 Sensor Watch Express.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-001 Sensor Watch Express.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-001 Sensor Watch Express.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-001 Sensor Watch Express.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-003 Sensor Watch Motion.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-003 Sensor Watch Motion.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-003 Sensor Watch Motion.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-003 Sensor Watch Motion.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-003 Sensor Watch Motion.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-003 Sensor Watch Motion.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-003 Sensor Watch Motion.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-003 Sensor Watch Motion.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-004 Sensor Watch Testpoints.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-004 Sensor Watch Testpoints.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-004 Sensor Watch Testpoints.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-004 Sensor Watch Testpoints.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-004 Sensor Watch Testpoints.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-004 Sensor Watch Testpoints.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-004 Sensor Watch Testpoints.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-004 Sensor Watch Testpoints.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-008 Hiking Log.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-008 Hiking Log.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-008 Hiking Log.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-008 Hiking Log.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-008 Hiking Log.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-008 Hiking Log.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-008 Hiking Log.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-008 Hiking Log.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-009 Simple Thermistor Board.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-009 Simple Thermistor Board.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-009 Simple Thermistor Board.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-009 Simple Thermistor Board.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-009 Simple Thermistor Board.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-009 Simple Thermistor Board.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-009 Simple Thermistor Board.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-009 Simple Thermistor Board.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-010 Light Sensor.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-010 Light Sensor.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-010 Light Sensor.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-010 Light Sensor.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-010 Light Sensor.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-010 Light Sensor.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-010 Light Sensor.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-010 Light Sensor.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-011 RFID.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-011 RFID.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-011 RFID.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-011 RFID.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-011 RFID.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-011 RFID.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-011 RFID.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-011 RFID.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-012 Sensor Watch Testpoints v2.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-012 Sensor Watch Testpoints v2.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-012 Sensor Watch Testpoints v2.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-012 Sensor Watch Testpoints v2.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-012 Sensor Watch Testpoints v2.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-012 Sensor Watch Testpoints v2.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-012 Sensor Watch Testpoints v2.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-012 Sensor Watch Testpoints v2.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-015 Temperature and Light Board.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-015 Temperature and Light Board.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-015 Temperature and Light Board.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-015 Temperature and Light Board.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-015 Temperature and Light Board.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-015 Temperature and Light Board.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-015 Temperature and Light Board.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-015 Temperature and Light Board.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-018 Temperature Board.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-018 Temperature Board.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-018 Temperature Board.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-018 Temperature Board.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-018 Temperature Board.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-018 Temperature Board.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-018 Temperature Board.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-018 Temperature Board.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-020 Temperature + GPIO Board.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-020 Temperature + GPIO Board.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-020 Temperature + GPIO Board.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-020 Temperature + GPIO Board.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-020 Temperature + GPIO Board.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-020 Temperature + GPIO Board.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-020 Temperature + GPIO Board.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-020 Temperature + GPIO Board.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-022 Temperature + GPIO + I2C Board.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-022 Temperature + GPIO + I2C Board.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-022 Temperature + GPIO + I2C Board.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-022 Temperature + GPIO + I2C Board.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-022 Temperature + GPIO + I2C Board.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-022 Temperature + GPIO + I2C Board.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-022 Temperature + GPIO + I2C Board.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-022 Temperature + GPIO + I2C Board.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-023 Temperature + GPIO + I2C Alternate.sch diff --git a/PCB/Sensor Boards/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.brd diff --git a/PCB/Sensor Boards/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-21-024 Temperature + GPIO + I2C Alternate 2.sch diff --git a/PCB/Sensor Boards/OSO-MISC-22-001 Temperature + GPIO + I2C.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-001 Temperature + GPIO + I2C.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-001 Temperature + GPIO + I2C.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-001 Temperature + GPIO + I2C.brd diff --git a/PCB/Sensor Boards/OSO-MISC-22-001 Temperature + GPIO + I2C.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-001 Temperature + GPIO + I2C.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-001 Temperature + GPIO + I2C.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-001 Temperature + GPIO + I2C.sch diff --git a/PCB/Sensor Boards/OSO-MISC-22-002 Sensor Watch Motion Express.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-002 Sensor Watch Motion Express.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-002 Sensor Watch Motion Express.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-002 Sensor Watch Motion Express.brd diff --git a/PCB/Sensor Boards/OSO-MISC-22-002 Sensor Watch Motion Express.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-002 Sensor Watch Motion Express.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-002 Sensor Watch Motion Express.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-002 Sensor Watch Motion Express.sch diff --git a/PCB/Sensor Boards/OSO-MISC-22-004 WIP-NFC.brd b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-004 WIP-NFC.brd similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-004 WIP-NFC.brd rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-004 WIP-NFC.brd diff --git a/PCB/Sensor Boards/OSO-MISC-22-004 WIP-NFC.sch b/PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-004 WIP-NFC.sch similarity index 100% rename from PCB/Sensor Boards/OSO-MISC-22-004 WIP-NFC.sch rename to PCB/Sensor Boards/Eagle (Legacy Boards)/Untested - WIP - Not Recommended/OSO-MISC-22-004 WIP-NFC.sch diff --git a/PCB/Sensor Boards/OSO-SWAB-A1-00 Temperature + Test Points_2022-01-26.zip b/PCB/Sensor Boards/Gerbers/OSO-SWAB-A1-00 Temperature + Test Points_2022-01-26.zip similarity index 100% rename from PCB/Sensor Boards/OSO-SWAB-A1-00 Temperature + Test Points_2022-01-26.zip rename to PCB/Sensor Boards/Gerbers/OSO-SWAB-A1-00 Temperature + Test Points_2022-01-26.zip diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_dru b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_dru new file mode 100644 index 00000000..6ac34d2f --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_dru @@ -0,0 +1 @@ +(version 1) \ No newline at end of file diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_pcb b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_pcb new file mode 100644 index 00000000..e32ca94b --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_pcb @@ -0,0 +1,493 @@ +(kicad_pcb (version 20211014) (generator pcbnew) + + (general + (thickness 0.19) + ) + + (paper "A4") + (layers + (0 "F.Cu" signal) + (31 "B.Cu" signal) + (32 "B.Adhes" user "B.Adhesive") + (33 "F.Adhes" user "F.Adhesive") + (34 "B.Paste" user) + (35 "F.Paste" user) + (36 "B.SilkS" user "B.Silkscreen") + (37 "F.SilkS" user "F.Silkscreen") + (38 "B.Mask" user) + (39 "F.Mask" user) + (40 "Dwgs.User" user "User.Drawings") + (41 "Cmts.User" user "User.Comments") + (42 "Eco1.User" user "User.Eco1") + (43 "Eco2.User" user "User.Eco2") + (44 "Edge.Cuts" user) + (45 "Margin" user) + (46 "B.CrtYd" user "B.Courtyard") + (47 "F.CrtYd" user "F.Courtyard") + (48 "B.Fab" user) + (49 "F.Fab" user) + (50 "User.1" user) + (51 "User.2" user) + (52 "User.3" user) + (53 "User.4" user) + (54 "User.5" user) + (55 "User.6" user) + (56 "User.7" user) + (57 "User.8" user) + (58 "User.9" user) + ) + + (setup + (stackup + (layer "F.SilkS" (type "Top Silk Screen") (color "White")) + (layer "F.Paste" (type "Top Solder Paste")) + (layer "F.Mask" (type "Top Solder Mask") (color "#CC66004D") (thickness 0.01)) + (layer "F.Cu" (type "copper") (thickness 0.035)) + (layer "dielectric 1" (type "core") (thickness 0.1) (material "Polyimide") (epsilon_r 3.2) (loss_tangent 0.004)) + (layer "B.Cu" (type "copper") (thickness 0.035)) + (layer "B.Mask" (type "Bottom Solder Mask") (color "#CC66004D") (thickness 0.01)) + (layer "B.Paste" (type "Bottom Solder Paste")) + (layer "B.SilkS" (type "Bottom Silk Screen") (color "White")) + (copper_finish "None") + (dielectric_constraints no) + ) + (pad_to_mask_clearance 0) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (disableapertmacros false) + (usegerberextensions false) + (usegerberattributes true) + (usegerberadvancedattributes true) + (creategerberjobfile true) + (svguseinch false) + (svgprecision 6) + (excludeedgelayer true) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (dxfpolygonmode true) + (dxfimperialunits true) + (dxfusepcbnewfont true) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (sketchpadsonfab false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 0) + (scaleselection 1) + (outputdirectory "OSO-SWAB-B1-00") + ) + ) + + (net 0 "") + (net 1 "/A1_RX") + (net 2 "/A2_TX") + (net 3 "/A4_INT1") + (net 4 "GND") + (net 5 "/A3_INT2") + (net 6 "/SDA") + (net 7 "/SCL") + (net 8 "VCC") + (net 9 "/A0_UNUSED") + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:FH19C9S05SH10-FFC" (layer "F.Cu") + (tedit 0) (tstamp c450d786-1278-4a96-8a62-a0d27859c515) + (at 153.2255 106.7461) + (descr "FH19C-9S-0.5SH(10)-1
\n") + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/4dc3cbb6-fb37-42a6-81e4-ab57e8e35700") + (fp_text reference "U$3" (at 0 0) (layer "F.SilkS") hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + (tstamp 9040ae45-373a-45fc-adb3-fcfaa02764b2) + ) + (fp_text value "FH19C-9S-0.5SH_10-FFC" (at 0 0) (layer "F.Fab") hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + (tstamp 5af4c90c-a654-4d3a-80bb-293a78da42b9) + ) + (fp_poly (pts + (xy 2.56543 3.556) + (xy -2.56537 3.556) + (xy -2.56643 0.898) + (xy 2.56437 0.898) + ) (layer "B.Mask") (width 0) (fill solid) (tstamp 21283db5-1009-43c5-a3ef-4954974a3a30)) + (pad "1" smd rect (at 2 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 8 "VCC") (pinfunction "1") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp b2e7f160-81a2-4f3a-9cac-d6cba543336c)) + (pad "2" smd rect (at 1.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 4 "GND") (pinfunction "2") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp 4a8a2808-da08-4211-a839-b545ca46843d)) + (pad "3" smd rect (at 1 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 3 "/A4_INT1") (pinfunction "3") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp 1ad63a96-1ef2-463e-9ea7-81ba46599172)) + (pad "4" smd rect (at 0.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 5 "/A3_INT2") (pinfunction "4") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp 44970b45-f7b0-47cc-a114-209df0456d8f)) + (pad "5" smd rect (at 0 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 2 "/A2_TX") (pinfunction "5") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp 16a60cfb-4140-483f-9675-22643c201dcd)) + (pad "6" smd rect (at -0.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 1 "/A1_RX") (pinfunction "6") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp edf03a5b-8be1-48f8-8f16-4719d937182d)) + (pad "7" smd rect (at -1 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 6 "/SDA") (pinfunction "7") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp b54a21f9-d0ee-47bd-8a33-6d2ccb2f1964)) + (pad "8" smd rect (at -1.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 7 "/SCL") (pinfunction "8") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp 496964dd-0d25-423f-9576-ddcd7d92b9c0)) + (pad "9" smd rect (at -2 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (net 9 "/A0_UNUSED") (pinfunction "9") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp 6a847b13-3d48-4df7-8dd7-d515f51aacbf)) + ) + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:LGA12R50P4X4_200X200X70" (layer "B.Cu") + (tedit 0) (tstamp 38449293-6eb3-4fce-a813-980a83af30a5) + (at 145.3261 101.9201 180) + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/f61a4c5e-e4e7-40df-976e-1899d4c8a12a") + (fp_text reference "U2" (at 0.02175 2.6201) (layer "B.SilkS") + (effects (font (size 0.406899 0.406899) (thickness 0.101101)) (justify left mirror)) + (tstamp 2fb12f0c-a2cb-4979-8ff3-7261f4205a8f) + ) + (fp_text value "LIS2DW12TR" (at -1.501141 -2.001519) (layer "B.Fab") + (effects (font (size 0.406974 0.406974) (thickness 0.101026)) (justify left mirror)) + (tstamp 79ae9206-147d-40c8-b439-c5e1aa71ef7c) + ) + (fp_line (start -1.05 -0.555) (end -1.05 -1.05) (layer "B.SilkS") (width 0.127) (tstamp 02ae2e5e-0358-428d-9b47-799126b254ae)) + (fp_line (start 1.05 -1.05) (end 1.05 -0.555) (layer "B.SilkS") (width 0.127) (tstamp 29d50b3c-acc8-4899-ab05-b18d21ab3b3c)) + (fp_line (start 0.555 1.05) (end 1.05 1.05) (layer "B.SilkS") (width 0.127) (tstamp 3ccbbde2-8e04-400e-bf38-caa624eba487)) + (fp_line (start -1.05 0.555) (end -1.05 1.05) (layer "B.SilkS") (width 0.127) (tstamp 418272bc-4a1c-4292-abcc-02abb40a91b1)) + (fp_line (start 1.05 1.05) (end 1.05 0.555) (layer "B.SilkS") (width 0.127) (tstamp 6b1bdfd4-bd5f-4649-8e19-6c646bd31d41)) + (fp_line (start -1.05 1.05) (end -0.555 1.05) (layer "B.SilkS") (width 0.127) (tstamp b9246ad8-1e96-4d28-8417-be94c523f7fa)) + (fp_line (start 0.555 -1.05) (end 1.05 -1.05) (layer "B.SilkS") (width 0.127) (tstamp bfa111e0-c472-4d7f-9f9f-eb6d8452f0bc)) + (fp_line (start -1.05 -1.05) (end -0.555 -1.05) (layer "B.SilkS") (width 0.127) (tstamp ed58876d-2aff-4c39-a693-85bc921546dc)) + (fp_circle (center -1.5 0.75) (end -1.45 0.75) (layer "B.SilkS") (width 0.1) (fill none) (tstamp eed4a4a1-5971-4468-a0eb-4adabc23ee91)) + (fp_line (start -1.25 -1.25) (end -1.25 1.25) (layer "B.CrtYd") (width 0.05) (tstamp 0c936eb0-2bed-42c5-a43a-a8c2138d10f6)) + (fp_line (start 1.25 1.25) (end 1.25 -1.25) (layer "B.CrtYd") (width 0.05) (tstamp b9af5acd-a7ff-4d1f-a5af-28344932ba28)) + (fp_line (start -1.25 1.25) (end 1.25 1.25) (layer "B.CrtYd") (width 0.05) (tstamp df602652-97d0-42fe-8c45-0c9e9cdbab8a)) + (fp_line (start 1.25 -1.25) (end -1.25 -1.25) (layer "B.CrtYd") (width 0.05) (tstamp e6004e06-b498-4cbf-a2cd-4065cdd9ac30)) + (fp_line (start 1 1) (end 1 -1) (layer "B.Fab") (width 0.127) (tstamp 04b92bea-33f5-431d-87c9-1b951c5a0895)) + (fp_line (start 1 -1) (end -1 -1) (layer "B.Fab") (width 0.127) (tstamp 8c6e9c84-beb1-4bc6-b6c0-93f5915e6d31)) + (fp_line (start -1 -1) (end -1 1) (layer "B.Fab") (width 0.127) (tstamp c65c8660-c3aa-4e44-a24a-c0839e96ffe1)) + (fp_line (start -1 1) (end 1 1) (layer "B.Fab") (width 0.127) (tstamp c9623f6f-a650-4e25-8bd7-692927ca8f9d)) + (fp_circle (center -0.75 0.75) (end -0.7 0.75) (layer "B.Fab") (width 0.1) (fill none) (tstamp 06bb0748-9b94-4559-8b9c-a59aa1c8ab55)) + (pad "1" smd rect (at -0.76 0.75 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 7 "/SCL") (pinfunction "SCL/SPC") (pintype "input") (solder_mask_margin 0.0635) (tstamp 3db7e36b-889f-4f74-9156-b304ec17949b)) + (pad "2" smd rect (at -0.76 0.25 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 8 "VCC") (pinfunction "CS") (pintype "input") (solder_mask_margin 0.0635) (tstamp 358727b9-955e-4b0e-8f93-faac9b591622)) + (pad "3" smd rect (at -0.76 -0.25 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 8 "VCC") (pinfunction "SDO/SDA0") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp bf192f28-5a1f-4b77-af0f-de5ad059ed8c)) + (pad "4" smd rect (at -0.76 -0.75 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 6 "/SDA") (pinfunction "SDA/SDI/SDO") (pintype "bidirectional") (solder_mask_margin 0.0635) (tstamp ec19640d-d714-4214-b3c1-ade84ffe1184)) + (pad "5" smd rect (at -0.25 -0.76 180) (size 0.35 0.4) (layers "B.Cu" "B.Paste" "B.Mask") + (solder_mask_margin 0.0635) (tstamp 98922bc7-e895-48ee-8f8c-8718a306a6e9)) + (pad "6" smd rect (at 0.25 -0.76 180) (size 0.35 0.4) (layers "B.Cu" "B.Paste" "B.Mask") + (net 4 "GND") (pinfunction "GND") (pintype "power_in") (solder_mask_margin 0.0635) (tstamp 1ae80af8-dac6-46a2-88cc-ea6877872716)) + (pad "7" smd rect (at 0.76 -0.75 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 4 "GND") (pinfunction "RES") (pintype "passive") (solder_mask_margin 0.0635) (tstamp ed3d45a3-b988-41b3-8d80-5013f0b90226)) + (pad "8" smd rect (at 0.76 -0.25 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 4 "GND") (pinfunction "GND") (pintype "power_in") (solder_mask_margin 0.0635) (tstamp afff67d6-aa97-4848-86fb-883a57bddf5a)) + (pad "9" smd rect (at 0.76 0.25 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 8 "VCC") (pinfunction "VDD") (pintype "power_in") (solder_mask_margin 0.0635) (tstamp a4de6280-2a67-4f62-9a7b-e57bae02df74)) + (pad "10" smd rect (at 0.76 0.75 180) (size 0.4 0.35) (layers "B.Cu" "B.Paste" "B.Mask") + (net 8 "VCC") (pinfunction "VDD_IO") (pintype "power_in") (solder_mask_margin 0.0635) (tstamp 861bccff-e93d-4aab-b5fb-31ba7ca49f23)) + (pad "11" smd rect (at 0.25 0.76 180) (size 0.35 0.4) (layers "B.Cu" "B.Paste" "B.Mask") + (net 5 "/A3_INT2") (pinfunction "INT2") (pintype "output") (solder_mask_margin 0.0635) (tstamp 8581ef53-a74b-453a-a79a-1ad12a5b60be)) + (pad "12" smd rect (at -0.25 0.76 180) (size 0.35 0.4) (layers "B.Cu" "B.Paste" "B.Mask") + (net 3 "/A4_INT1") (pinfunction "INT1") (pintype "output") (solder_mask_margin 0.0635) (tstamp 651bf078-2bd8-4627-9a4d-396860ade5d0)) + ) + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:_0603MP" (layer "B.Cu") + (tedit 0) (tstamp 52f3f076-84fe-4d87-b520-c9ec8ac43cd8) + (at 142.4051 101.3359 90) + (descr "0603 MicroPitch") + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/dbf111d5-5941-4c1b-8fad-675981ce34f4") + (fp_text reference "C2" (at 2.0359 0.3949 180) (layer "B.SilkS") + (effects (font (size 0.388031 0.388031) (thickness 0.119969)) (justify left mirror)) + (tstamp 9bd4d62d-7a56-42ce-b3f5-7a6d01978996) + ) + (fp_text value "10uF" (at -0.9525 -0.9525 90) (layer "B.Fab") + (effects (font (size 0.442163 0.442163) (thickness 0.065837)) (justify left mirror)) + (tstamp dd43d085-ec5b-4b38-8a0a-a3e36d67876d) + ) + (fp_poly (pts + (xy -0.1999 -0.25) + (xy 0.1999 -0.25) + (xy 0.1999 0.25) + (xy -0.1999 0.25) + ) (layer "B.Adhes") (width 0) (fill solid) (tstamp bf433100-c31b-441a-977d-11c8dfea5e5d)) + (fp_line (start 0 0.254) (end 0 -0.254) (layer "B.SilkS") (width 0.2032) (tstamp c0b3ca6d-cbf4-4a4a-829a-bd12e3d6f696)) + (fp_line (start 0.432 0.306) (end -0.432 0.306) (layer "B.Fab") (width 0.1016) (tstamp 62361dc9-703b-4d4c-9ead-64531412f98d)) + (fp_line (start -0.432 -0.306) (end 0.432 -0.306) (layer "B.Fab") (width 0.1016) (tstamp f78d3c08-172c-4642-a357-be3cd6805e97)) + (fp_poly (pts + (xy 0.4318 -0.4) + (xy 0.8 -0.4) + (xy 0.8 0.4) + (xy 0.4318 0.4) + ) (layer "B.Fab") (width 0) (fill solid) (tstamp 430dd9e0-a77c-40c2-a434-88901e1d63f9)) + (fp_poly (pts + (xy -0.8 -0.4) + (xy -0.4318 -0.4) + (xy -0.4318 0.4) + (xy -0.8 0.4) + ) (layer "B.Fab") (width 0) (fill solid) (tstamp e99999ac-764f-42aa-af5f-f6b490544976)) + (pad "1" smd rect (at -0.762 0 90) (size 0.8 0.8) (layers "B.Cu" "B.Paste" "B.Mask") + (net 4 "GND") (pinfunction "1") (pintype "passive") (solder_mask_margin 0.0635) (tstamp 05f47ce8-fbff-4c88-a713-924ebec9cd7f)) + (pad "2" smd rect (at 0.762 0 90) (size 0.8 0.8) (layers "B.Cu" "B.Paste" "B.Mask") + (net 8 "VCC") (pinfunction "2") (pintype "passive") (solder_mask_margin 0.0635) (tstamp 3418d403-467d-4e3f-8239-51594743a971)) + ) + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (layer "B.Cu") + (tedit 0) (tstamp 53397a02-3122-469f-8a6e-5586e1d48a70) + (at 144.8435 104.4601 180) + (descr "TEST PAD") + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/1936aa8e-84b5-486e-a2d5-81ae44fd41c7") + (fp_text reference "TP3" (at -1.0668 0.3302) (layer "B.SilkS") hide + (effects (font (size 0.30226 0.30226) (thickness 0.075565)) (justify left mirror)) + (tstamp a286de89-e15e-41ca-972a-92b40dbbd887) + ) + (fp_text value "TPB1,27" (at -0.635 -0.762) (layer "B.Fab") + (effects (font (size 0.503794 0.503794) (thickness 0.004206)) (justify left mirror)) + (tstamp 0f58640a-48e4-4c58-8582-c0d0f03f67c9) + ) + (pad "TP" smd roundrect (at 0 0 180) (size 1.27 1.27) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.5) + (net 2 "/A2_TX") (pinfunction "TP") (pintype "input") (solder_mask_margin 0.0635) (tstamp 37a22dff-bef4-4a54-aa97-606b44b0539d)) + ) + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (layer "B.Cu") + (tedit 0) (tstamp 8492a13d-c2e7-4353-90d5-a0194203e30e) + (at 146.2659 105.0951 180) + (descr "TEST PAD") + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/a4b4c4fb-1c78-4a88-b6d6-c95ced14e6a1") + (fp_text reference "TP4" (at -1.0668 0) (layer "B.SilkS") hide + (effects (font (size 0.30226 0.30226) (thickness 0.075565)) (justify left mirror)) + (tstamp ec765bc0-6a42-4727-9951-7e00656f3a23) + ) + (fp_text value "TPB1,27" (at -0.635 -0.762) (layer "B.Fab") + (effects (font (size 0.503794 0.503794) (thickness 0.004206)) (justify left mirror)) + (tstamp 4d040dbd-23bd-4b9e-9905-fecd7f7a7e91) + ) + (pad "TP" smd roundrect (at 0 0 180) (size 1.27 1.27) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.5) + (net 1 "/A1_RX") (pinfunction "TP") (pintype "input") (solder_mask_margin 0.0635) (tstamp 964091ca-8bbe-4ac8-aaf6-8ee79894dac0)) + ) + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:_0603MP" (layer "B.Cu") + (tedit 0) (tstamp 92f1bd8b-af09-4166-bc64-aef654c0183a) + (at 143.6243 101.3359 -90) + (descr "0603 MicroPitch") + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/81f117f8-2e22-4d95-9843-a6438cc9b8fd") + (fp_text reference "C1" (at -2.0359 0.3243 -180) (layer "B.SilkS") + (effects (font (size 0.388031 0.388031) (thickness 0.119969)) (justify right mirror)) + (tstamp 16e2b64b-b1f1-4a7b-a067-eb93b95619a3) + ) + (fp_text value "0.1uF" (at -0.9525 -0.9525 -270) (layer "B.Fab") + (effects (font (size 0.442163 0.442163) (thickness 0.065837)) (justify right mirror)) + (tstamp e0be7d00-bf2d-45a1-865e-97f1376ca4dd) + ) + (fp_poly (pts + (xy -0.1999 -0.25) + (xy 0.1999 -0.25) + (xy 0.1999 0.25) + (xy -0.1999 0.25) + ) (layer "B.Adhes") (width 0) (fill solid) (tstamp 737141da-8a5b-4eb5-a94c-2d98ea03ea2b)) + (fp_line (start 0 0.254) (end 0 -0.254) (layer "B.SilkS") (width 0.2032) (tstamp 3cb29946-354e-4d69-8954-0cb5df5feb34)) + (fp_line (start -0.432 -0.306) (end 0.432 -0.306) (layer "B.Fab") (width 0.1016) (tstamp 58356900-2195-4f68-aa48-0fbeed8a0258)) + (fp_line (start 0.432 0.306) (end -0.432 0.306) (layer "B.Fab") (width 0.1016) (tstamp d1fc816b-12b7-4411-becf-b39225ef5a06)) + (fp_poly (pts + (xy 0.4318 -0.4) + (xy 0.8 -0.4) + (xy 0.8 0.4) + (xy 0.4318 0.4) + ) (layer "B.Fab") (width 0) (fill solid) (tstamp 372669d9-06c5-4965-b34a-bd1ca4aba83d)) + (fp_poly (pts + (xy -0.8 -0.4) + (xy -0.4318 -0.4) + (xy -0.4318 0.4) + (xy -0.8 0.4) + ) (layer "B.Fab") (width 0) (fill solid) (tstamp 3d2b07eb-66f2-4ca0-8b52-77b42ce79ea8)) + (pad "1" smd rect (at -0.762 0 270) (size 0.8 0.8) (layers "B.Cu" "B.Paste" "B.Mask") + (net 8 "VCC") (pinfunction "1") (pintype "passive") (solder_mask_margin 0.0635) (tstamp f408e8b3-d3b1-4975-afa3-6edd4111b541)) + (pad "2" smd rect (at 0.762 0 270) (size 0.8 0.8) (layers "B.Cu" "B.Paste" "B.Mask") + (net 4 "GND") (pinfunction "2") (pintype "passive") (solder_mask_margin 0.0635) (tstamp 5fefcc14-df85-4c73-a324-fe9d5f1fa478)) + ) + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (layer "B.Cu") + (tedit 0) (tstamp d47e36a3-5090-4cf4-bf91-6b011b5fab8a) + (at 142.3035 103.3044 180) + (descr "TEST PAD") + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/6ea9dd18-adcc-4aba-8efa-d45943bee5d6") + (fp_text reference "TP1" (at 0.4064 -1.2954 270) (layer "B.SilkS") hide + (effects (font (size 0.30226 0.30226) (thickness 0.075565)) (justify right mirror)) + (tstamp 8643f50e-4c54-42e3-8f4e-9e7c565345a4) + ) + (fp_text value "TPB1,27" (at -0.635 -0.762) (layer "B.Fab") + (effects (font (size 0.503794 0.503794) (thickness 0.004206)) (justify left mirror)) + (tstamp 0ca4bbc5-6d45-40ae-a4b8-b0264327e89b) + ) + (pad "TP" smd roundrect (at 0 0 180) (size 1.27 1.27) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.5) + (net 4 "GND") (pinfunction "TP") (pintype "input") (solder_mask_margin 0.0635) (tstamp b69db92a-8dc0-4427-8729-230fe7829975)) + ) + + (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (layer "B.Cu") + (tedit 0) (tstamp d5562657-0bb5-4045-b7d6-e98fd391f4a3) + (at 143.3195 104.4601 180) + (descr "TEST PAD") + (property "Sheetfile" "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch") + (property "Sheetname" "") + (path "/ec24969b-8391-44db-a79f-3fa50f7e4597") + (fp_text reference "TP2" (at -0.4064 0.8636) (layer "B.SilkS") hide + (effects (font (size 0.30226 0.30226) (thickness 0.075565)) (justify left mirror)) + (tstamp 3eb69f50-8679-4783-841b-f3e56c6658ed) + ) + (fp_text value "TPB1,27" (at -0.635 -0.762) (layer "B.Fab") + (effects (font (size 0.503794 0.503794) (thickness 0.004206)) (justify left mirror)) + (tstamp de2ea6ae-7e35-4c49-af6d-0ddbb267d18e) + ) + (pad "TP" smd roundrect (at 0 0 180) (size 1.27 1.27) (layers "B.Cu" "B.Mask") (roundrect_rratio 0.5) + (net 8 "VCC") (pinfunction "TP") (pintype "input") (solder_mask_margin 0.0635) (tstamp 1b224beb-e21a-4340-ac2c-31b7fa1f7f8e)) + ) + + (gr_line (start 155.7147 105.0951) (end 147.5105 105.0951) (layer "F.SilkS") (width 0.127) (tstamp 09b40b31-a75f-48c5-94ff-dac04c6dfaf8)) + (gr_line (start 147.0025 100.5231) (end 147.0025 104.5871) (layer "F.SilkS") (width 0.127) (tstamp 59eee44c-9efd-402f-80e1-02593f15460b)) + (gr_arc (start 146.2405 99.7611) (mid 146.779315 99.984285) (end 147.0025 100.5231) (layer "F.SilkS") (width 0.127) (tstamp a8fc3609-a41b-4706-8233-14786995acaa)) + (gr_arc (start 147.5105 105.0951) (mid 147.15129 104.94631) (end 147.0025 104.5871) (layer "F.SilkS") (width 0.127) (tstamp d204339c-8036-43d2-8aa8-268d985f6138)) + (gr_line (start 144.2 105.9) (end 144.7 105.9) (layer "F.Mask") (width 0.1) (tstamp 45263c40-98a9-4f74-a47a-9075d46d8655)) + (gr_line (start 150.7363 106.7461) (end 150.7363 110.0961) (layer "Edge.Cuts") (width 0.05) (tstamp 2af795e8-c9a1-416f-b2d3-8be4310d296e)) + (gr_arc (start 150.8863 110.2461) (mid 150.780234 110.202166) (end 150.7363 110.0961) (layer "Edge.Cuts") (width 0.05) (tstamp 58502658-0694-45f6-94e7-5aca0f57af62)) + (gr_line (start 150.1013 106.1111) (end 145.3515 106.1111) (layer "Edge.Cuts") (width 0.05) (tstamp 5e539d5b-e49f-4f77-9569-2a4261264736)) + (gr_line (start 144.7165 105.4761) (end 142.1765 105.4761) (layer "Edge.Cuts") (width 0.05) (tstamp 6ac0bb29-69f1-4b1d-b893-957a8916a1bb)) + (gr_arc (start 144.7165 105.4761) (mid 145.165513 105.662087) (end 145.3515 106.1111) (layer "Edge.Cuts") (width 0.05) (tstamp 6b9e5d6b-5222-465f-9b1e-93af00265572)) + (gr_arc (start 150.1013 106.1111) (mid 150.550313 106.297087) (end 150.7363 106.7461) (layer "Edge.Cuts") (width 0.05) (tstamp 7f938717-4068-4e5c-92a0-7210bbdd7788)) + (gr_arc (start 155.3337 99.7611) (mid 155.603108 99.872692) (end 155.7147 100.1421) (layer "Edge.Cuts") (width 0.05) (tstamp 9b7def2b-3536-42b1-8e65-4b8e423042d7)) + (gr_arc (start 142.1765 105.4761) (mid 141.547882 105.215718) (end 141.2875 104.5871) (layer "Edge.Cuts") (width 0.05) (tstamp 9b9870d6-49b4-40a8-b847-cb5468c63035)) + (gr_line (start 155.7147 100.1421) (end 155.7147 106.7461) (layer "Edge.Cuts") (width 0.05) (tstamp a6bc6301-abbd-4acf-a77d-1f4e4d107e79)) + (gr_line (start 155.5647 110.2461) (end 150.8863 110.2461) (layer "Edge.Cuts") (width 0.05) (tstamp ae418f09-9594-49fa-ba14-c5ebf3097fc7)) + (gr_line (start 142.1765 99.7611) (end 155.3337 99.7611) (layer "Edge.Cuts") (width 0.05) (tstamp b5d214ca-8d2c-4892-a145-ebcdf525979d)) + (gr_arc (start 141.2875 100.6501) (mid 141.547882 100.021482) (end 142.1765 99.7611) (layer "Edge.Cuts") (width 0.05) (tstamp c4d82428-36d7-43c8-9bfb-b2beed9359df)) + (gr_line (start 155.7147 106.7461) (end 155.7147 110.0961) (layer "Edge.Cuts") (width 0.05) (tstamp dc2cbabd-f370-406b-b50e-bb3846cd95ff)) + (gr_arc (start 155.7147 110.0961) (mid 155.670766 110.202166) (end 155.5647 110.2461) (layer "Edge.Cuts") (width 0.05) (tstamp e1f2d86b-fcc6-43fe-bbcc-417ac237e0bd)) + (gr_line (start 141.2875 104.5871) (end 141.2875 100.6501) (layer "Edge.Cuts") (width 0.05) (tstamp e960ff40-d2dc-4f31-aa56-c3592606d2b4)) + (gr_text "TX" (at 144.9 103.3) (layer "B.SilkS") (tstamp 2cd2031e-bdc6-4b09-a5d6-627ebbcee21c) + (effects (font (size 0.4 0.4) (thickness 0.075)) (justify top mirror)) + ) + (gr_text "RX" (at 146.3 103.9) (layer "B.SilkS") (tstamp 5e112429-2dc1-437d-8792-2c6553eb0f93) + (effects (font (size 0.4 0.4) (thickness 0.075)) (justify top mirror)) + ) + (gr_text "GND" (at 141.8 104.4 -90) (layer "B.SilkS") (tstamp 72b454f6-3d75-4170-9db1-78a51d4c0e67) + (effects (font (size 0.4 0.4) (thickness 0.075)) (justify top mirror)) + ) + (gr_text "3V" (at 142.4 105) (layer "B.SilkS") (tstamp f65b8e04-fbde-4466-addc-36be3d61856b) + (effects (font (size 0.4 0.4) (thickness 0.075)) (justify top mirror)) + ) + (gr_text "I²C: LIS2DW12 (0x19)\nA1/A2: UART RX/TX\nA3/A4: INT2/INT1\n" (at 151.4475 102.8853) (layer "F.SilkS") (tstamp 06718050-7404-4593-8900-5367d4556e53) + (effects (font (size 0.44704 0.44704) (thickness 0.06096)) (justify top)) + ) + (gr_text "OSO-SWAB-B2-00\nSW Accelerometer:\nDeveloper Preview" (at 151.4475 100.0913) (layer "F.SilkS") (tstamp 1a8b05a9-bccd-4ebd-8312-af5738af914c) + (effects (font (size 0.499872 0.499872) (thickness 0.109728)) (justify top)) + ) + + (segment (start 149.73135 105.23315) (end 149.5933 105.0951) (width 0.2032) (layer "F.Cu") (net 1) (tstamp 0bae9b38-d794-4972-b292-0160f8d78e32)) + (segment (start 148.0693 105.0951) (end 149.5933 105.0951) (width 0.2032) (layer "F.Cu") (net 1) (tstamp 46023c51-300f-4e42-afb4-010034d44dac)) + (segment (start 151.20785 105.23315) (end 149.73135 105.23315) (width 0.2032) (layer "F.Cu") (net 1) (tstamp 52c0f5dc-54c3-478f-9860-ccb50104bb0b)) + (via (at 148.0693 105.0951) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 1) (tstamp e39680a8-e74a-46a6-a545-ac5ad0aa7f34)) + (via (at 151.20785 105.23315) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 1) (tstamp fbd986c1-ed36-4026-b812-e3868a5e2ad8)) + (segment (start 146.2659 105.0951) (end 148.0693 105.0951) (width 0.2032) (layer "B.Cu") (net 1) (tstamp 3a4f4d1c-4c47-490a-b760-933c1c17288d)) + (segment (start 152.7255 106.7508) (end 151.20785 105.23315) (width 0.2032) (layer "B.Cu") (net 1) (tstamp 5a7537b8-356a-483f-afb1-7f541c63a2bb)) + (segment (start 152.7255 108.9961) (end 152.7255 106.7508) (width 0.2032) (layer "B.Cu") (net 1) (tstamp 8ff819c8-6284-4bec-859f-4051f056dd5d)) + (segment (start 150.77605 104.69975) (end 150.2316 104.1553) (width 0.2032) (layer "F.Cu") (net 2) (tstamp 64f42c98-92a4-4baa-b4b3-05e7803c7f63)) + (segment (start 150.2316 104.1553) (end 146.8501 104.1553) (width 0.2032) (layer "F.Cu") (net 2) (tstamp 8306564e-5a9a-4496-9d00-07c1bd5d26b9)) + (via (at 150.77605 104.69975) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 2) (tstamp 99809845-4da0-4cf1-bc62-c9244dba4647)) + (via (at 146.8501 104.1553) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 2) (tstamp e676c03d-34a8-4263-88a7-40dae634a5e2)) + (segment (start 144.8435 104.4601) (end 145.1483 104.1553) (width 0.2032) (layer "B.Cu") (net 2) (tstamp 37789217-9964-4e49-8f73-d44995c5fc7e)) + (segment (start 151.51265 104.69975) (end 150.77605 104.69975) (width 0.2032) (layer "B.Cu") (net 2) (tstamp 5857a90c-f5a9-4b24-a98c-479fad8de298)) + (segment (start 153.2255 108.9961) (end 153.2255 106.4126) (width 0.2032) (layer "B.Cu") (net 2) (tstamp cae21fe2-e35b-4a44-bcf5-92de0998264c)) + (segment (start 146.8501 104.1553) (end 145.1483 104.1553) (width 0.2032) (layer "B.Cu") (net 2) (tstamp f4f1004d-dd60-429f-8283-9f030f526130)) + (segment (start 153.2255 106.4126) (end 151.51265 104.69975) (width 0.2032) (layer "B.Cu") (net 2) (tstamp fbcc5301-bbbf-4c9f-b660-fd98838053a6)) + (segment (start 154.2255 107.3959) (end 154.0985 107.2689) (width 0.2032) (layer "B.Cu") (net 3) (tstamp 7ebf6bd5-822c-4407-8d1a-08d43c2d0678)) + (segment (start 154.0985 106.079475) (end 154.0985 107.2689) (width 0.2032) (layer "B.Cu") (net 3) (tstamp 8a4485c7-f427-446f-af34-1128a47c425d)) + (segment (start 145.780813 100.7009) (end 148.719925 100.7009) (width 0.2032) (layer "B.Cu") (net 3) (tstamp b08ebf16-1549-411d-8fab-75c6d1bd76cb)) + (segment (start 145.5761 100.905613) (end 145.780813 100.7009) (width 0.2032) (layer "B.Cu") (net 3) (tstamp b21f3bbb-f1c1-4554-ac75-e53c16d27653)) + (segment (start 154.0985 106.079475) (end 148.719925 100.7009) (width 0.2032) (layer "B.Cu") (net 3) (tstamp e5d7d599-d647-4e18-96d9-808d318d07c5)) + (segment (start 154.2255 108.9961) (end 154.2255 107.3959) (width 0.2032) (layer "B.Cu") (net 3) (tstamp e9b07d7a-e899-4ca0-9369-e0d0ebb1ab10)) + (segment (start 145.5761 101.1601) (end 145.5761 100.905613) (width 0.2032) (layer "B.Cu") (net 3) (tstamp febdebfd-50f2-4c7a-baca-c05d26479bd3)) + (segment (start 146.8534 103.1139) (end 146.7772 103.1901) (width 0.3048) (layer "F.Cu") (net 4) (tstamp 06fcdb8f-2704-46cd-b30d-dcb7b02e58da)) + (segment (start 154.61145 106.83335) (end 150.892 103.1139) (width 0.3048) (layer "F.Cu") (net 4) (tstamp 1fa3df21-bfa8-4c91-9bb0-d56e9306f2bf)) + (segment (start 150.892 103.1139) (end 146.8534 103.1139) (width 0.3048) (layer "F.Cu") (net 4) (tstamp 8f443325-1180-471c-a3e1-92e2115c8bf9)) + (via (at 154.61145 106.83335) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 4) (tstamp 1b9c6030-7343-4ac8-a6d0-411c1c118821)) + (via (at 146.7772 103.1901) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 4) (tstamp 7c1347fe-33ec-4ab3-b26c-77a73b0799f2)) + (segment (start 142.4051 102.0979) (end 143.6243 102.0979) (width 0.3048) (layer "B.Cu") (net 4) (tstamp 07ac1533-fe72-4f36-a863-388b14a75fc5)) + (segment (start 142.3035 103.3044) (end 142.4051 103.2028) (width 0.3048) (layer "B.Cu") (net 4) (tstamp 0ae5de39-695f-4104-bcec-54b83e33bae2)) + (segment (start 144.5661 102.6701) (end 145.0661 102.6701) (width 0.2032) (layer "B.Cu") (net 4) (tstamp 391f44de-b221-459d-83d3-1c670da7efe7)) + (segment (start 144.5661 102.1741) (end 144.5661 102.1701) (width 0.2032) (layer "B.Cu") (net 4) (tstamp 3d9119fb-5155-4df7-a94a-e63bdeca035d)) + (segment (start 144.5661 102.6701) (end 144.5661 102.1741) (width 0.2032) (layer "B.Cu") (net 4) (tstamp 733bf9c6-aa1d-46f9-b366-35a9f20a2249)) + (segment (start 154.7255 108.9961) (end 154.7255 106.9474) (width 0.3048) (layer "B.Cu") (net 4) (tstamp 8c334ef6-ea14-4d64-923e-8c370645175a)) + (segment (start 145.28005 103.1901) (end 145.0761 102.98615) (width 0.3048) (layer "B.Cu") (net 4) (tstamp 903215f2-2ab4-494a-8eda-17fc50d3bed0)) + (segment (start 145.0661 102.6701) (end 145.0761 102.6801) (width 0.2032) (layer "B.Cu") (net 4) (tstamp a077552a-b221-43cc-9938-5d4743e3399d)) + (segment (start 143.6243 102.0979) (end 143.7005 102.1741) (width 0.3048) (layer "B.Cu") (net 4) (tstamp a26ae543-f877-4e55-8489-6ed81f3bfbf5)) + (segment (start 145.0761 102.6801) (end 145.0761 102.98615) (width 0.3048) (layer "B.Cu") (net 4) (tstamp b424a39d-8974-4555-8ffe-a4b9f275773a)) + (segment (start 142.4051 103.2028) (end 142.4051 102.0979) (width 0.3048) (layer "B.Cu") (net 4) (tstamp c2b57f9a-4cbb-409a-89ca-80ae105c720e)) + (segment (start 154.7255 106.9474) (end 154.61145 106.83335) (width 0.3048) (layer "B.Cu") (net 4) (tstamp da906691-c7ce-473f-afa0-e74ab9381761)) + (segment (start 145.28005 103.1901) (end 146.7772 103.1901) (width 0.3048) (layer "B.Cu") (net 4) (tstamp fcfeaa1c-0530-4b57-aa65-515779c79adc)) + (segment (start 143.7005 102.1741) (end 144.5661 102.1741) (width 0.3048) (layer "B.Cu") (net 4) (tstamp fe08666b-5748-4b31-8ca5-897a10c1698b)) + (segment (start 146.3675 101.7677) (end 145.4785 101.7677) (width 0.2032) (layer "F.Cu") (net 5) (tstamp 4b68e877-273f-48ca-a632-c41e8488ccf3)) + (segment (start 146.5199 101.9201) (end 146.3675 101.7677) (width 0.2032) (layer "F.Cu") (net 5) (tstamp 918e83c5-b7c2-44c1-b47f-0ab29c1c70b5)) + (segment (start 146.5199 101.9201) (end 147.3835 101.9201) (width 0.2032) (layer "F.Cu") (net 5) (tstamp ad51b439-098c-4e18-ae1f-9d44e116b8f7)) + (via (at 147.3835 101.9201) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 5) (tstamp 434f1740-e8ea-48aa-819a-e8f0c67929c4)) + (via (at 145.4785 101.7677) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 5) (tstamp 6ba8a963-4e52-4da9-b129-37389306d641)) + (segment (start 145.4277 101.7677) (end 145.0761 101.4161) (width 0.2032) (layer "B.Cu") (net 5) (tstamp 10257638-748f-4792-830d-716a1c0db7ff)) + (segment (start 145.0761 101.1601) (end 145.0761 101.4161) (width 0.2032) (layer "B.Cu") (net 5) (tstamp 365cff8c-a479-4d79-b362-fdfac89711c6)) + (segment (start 150.2029 104.1807) (end 147.9423 101.9201) (width 0.2032) (layer "B.Cu") (net 5) (tstamp 90ce1c88-363b-45a2-919d-8827646fa909)) + (segment (start 145.4785 101.7677) (end 145.4277 101.7677) (width 0.2032) (layer "B.Cu") (net 5) (tstamp be3923fc-ad03-412b-bb5d-3fdd829c673e)) + (segment (start 147.9423 101.9201) (end 147.3835 101.9201) (width 0.2032) (layer "B.Cu") (net 5) (tstamp d182f9f8-e6a8-4202-9825-0d3dc441d54e)) + (segment (start 153.7255 106.22845) (end 151.67775 104.1807) (width 0.2032) (layer "B.Cu") (net 5) (tstamp e273d4e7-8cf7-453c-9576-254ffc1b9a69)) + (segment (start 151.67775 104.1807) (end 150.2029 104.1807) (width 0.2032) (layer "B.Cu") (net 5) (tstamp f428be95-0b2d-4a60-bceb-9e05112c3631)) + (segment (start 153.7255 108.9961) (end 153.7255 106.22845) (width 0.2032) (layer "B.Cu") (net 5) (tstamp f706a32a-34b2-481f-abbc-a90a4713812a)) + (segment (start 152.2255 106.978) (end 147.9176 102.6701) (width 0.2032) (layer "B.Cu") (net 6) (tstamp 3eea729f-d81e-4602-924f-df00dc9fa656)) + (segment (start 152.2255 108.9961) (end 152.2255 106.978) (width 0.2032) (layer "B.Cu") (net 6) (tstamp 5e249130-5691-4735-95bd-6a35e7230671)) + (segment (start 147.9176 102.6701) (end 146.0861 102.6701) (width 0.2032) (layer "B.Cu") (net 6) (tstamp 6a7b5cae-5706-4ae7-90cd-85b744bf9818)) + (segment (start 151.71585 107.21435) (end 151.71585 104.90625) (width 0.2032) (layer "F.Cu") (net 7) (tstamp 5cd87d85-df22-4c10-9e4e-723432382705)) + (segment (start 151.71585 104.90625) (end 150.4823 103.6727) (width 0.2032) (layer "F.Cu") (net 7) (tstamp 9e5e5b3d-da91-43f7-a8e1-1798b10f31c4)) + (via (at 150.4823 103.6727) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 7) (tstamp a9964fed-7444-442b-82cc-b749621619ca)) + (via (at 151.71585 107.21435) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 7) (tstamp c2434c2f-d941-4c49-8079-f193e7b68270)) + (segment (start 151.7255 108.9961) (end 151.7255 107.224) (width 0.2032) (layer "B.Cu") (net 7) (tstamp 8ae15dfd-83d6-4de0-b635-cf161fade6d8)) + (segment (start 147.9797 101.1701) (end 146.0861 101.1701) (width 0.2032) (layer "B.Cu") (net 7) (tstamp 9502ea06-b6dc-4669-9f41-6d0a72043887)) + (segment (start 151.7255 107.224) (end 151.71585 107.21435) (width 0.2032) (layer "B.Cu") (net 7) (tstamp a3a7ea90-729d-4167-a73a-5b7df6440f1d)) + (segment (start 150.4823 103.6727) (end 147.9797 101.1701) (width 0.2032) (layer "B.Cu") (net 7) (tstamp d8832711-350c-4ec6-a360-bb9e4c599453)) + (segment (start 143.0147 101.3423) (end 143.5989 101.9265) (width 0.3048) (layer "F.Cu") (net 8) (tstamp 11b50766-7a82-4010-9094-79ac57ff803a)) + (segment (start 143.5989 101.9265) (end 143.5989 103.1901) (width 0.3048) (layer "F.Cu") (net 8) (tstamp a307a9c7-a8ef-452f-a518-570df34d3971)) + (via (at 143.0147 101.3423) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 8) (tstamp 4555beef-afd0-4a07-a374-49fd7a56b2b2)) + (via (at 143.5989 103.1901) (size 0.508) (drill 0.254) (layers "F.Cu" "B.Cu") (net 8) (tstamp e4527f25-252e-4b65-948d-69c2f9252889)) + (segment (start 143.6243 100.5739) (end 144.2593 100.5739) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 0255fcc1-949a-4f3e-9303-3ea178273985)) + (segment (start 144.5661 100.86405) (end 144.557775 100.872375) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 0430d002-15bd-4a42-b0f9-df13695fcd41)) + (segment (start 146.0861 102.1701) (end 146.0861 101.6701) (width 0.1524) (layer "B.Cu") (net 8) (tstamp 311f6061-4902-4cbc-adea-c404d4acbf4f)) + (segment (start 144.2593 100.5739) (end 144.557775 100.872375) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 3cb471ac-4528-43b2-8cc2-c3ed9505edbb)) + (segment (start 142.4051 100.5739) (end 142.4051 100.7327) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 4a55c467-28b2-400a-bb25-411d525e0c41)) + (segment (start 146.0861 102.1701) (end 145.7586 102.1701) (width 0.1524) (layer "B.Cu") (net 8) (tstamp 57534e6f-4afa-4ff4-8fb8-efd13eca414d)) + (segment (start 144.5661 101.1701) (end 144.5661 100.86405) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 5db439c0-d3e7-4734-b78a-7d0e5bb5ff74)) + (segment (start 144.5661 101.6701) (end 144.5661 101.1701) (width 0.2032) (layer "B.Cu") (net 8) (tstamp 7ebfbee5-a62a-4d13-aa04-b904378145cd)) + (segment (start 142.4051 100.5739) (end 143.6243 100.5739) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 81233f61-eb56-41e1-aff7-bb28c6de0f43)) + (segment (start 145.13565 100.2945) (end 144.5661 100.86405) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 88b53bf2-a9d1-436f-9e73-361984ffadfd)) + (segment (start 145.6784 102.2503) (end 145.2278 102.2503) (width 0.1524) (layer "B.Cu") (net 8) (tstamp 90b3147c-c625-4f91-99f2-b3e2525c4b58)) + (segment (start 155.2255 108.9961) (end 155.2255 106.631737) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 99b20163-86e6-4035-8ae8-2076cd6324d5)) + (segment (start 155.2255 106.631737) (end 148.888263 100.2945) (width 0.3048) (layer "B.Cu") (net 8) (tstamp 9a895394-1736-428b-8941-d281f03cb5c1)) + (segment (start 144.5661 101.6701) (end 144.764388 101.6701) (width 0.1524) (layer "B.Cu") (net 8) (tstamp a3e3db84-e7c7-4654-839f-76d04cc0c896)) + (segment (start 144.9947 102.0172) (end 144.9947 101.900413) (width 0.1524) (layer "B.Cu") (net 8) (tstamp a4d1b77a-1e80-4648-9ae9-519383b53778)) + (segment (start 142.4051 100.7327) (end 143.0147 101.3423) (width 0.3048) (layer "B.Cu") (net 8) (tstamp a9338404-2317-4d4a-8561-2fc099b9516a)) + (segment (start 143.5989 104.1807) (end 143.5989 103.1901) (width 0.3048) (layer "B.Cu") (net 8) (tstamp bece63a7-3dcb-4c76-846e-10153f6e0bc1)) + (segment (start 144.764388 101.6701) (end 144.9947 101.900413) (width 0.1524) (layer "B.Cu") (net 8) (tstamp beeed655-48b9-475b-8276-e75e9ceba0c9)) + (segment (start 143.3195 104.4601) (end 143.5989 104.1807) (width 0.3048) (layer "B.Cu") (net 8) (tstamp e5fe01a0-2862-474d-bb27-d55a88f6ecb0)) + (segment (start 145.7586 102.1701) (end 145.6784 102.2503) (width 0.1524) (layer "B.Cu") (net 8) (tstamp e87db6bb-555e-4674-ad0d-38786a05b91b)) + (segment (start 145.2278 102.2503) (end 144.9947 102.0172) (width 0.1524) (layer "B.Cu") (net 8) (tstamp ec19ba45-9ebe-4ac5-aa32-4f3cb5d1c05c)) + (segment (start 148.888263 100.2945) (end 145.13565 100.2945) (width 0.3048) (layer "B.Cu") (net 8) (tstamp efab3462-3997-4e87-83fd-171e8d73a0ec)) + +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_prl b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_prl new file mode 100644 index 00000000..de494a3d --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_prl @@ -0,0 +1,77 @@ +{ + "board": { + "active_layer": 39, + "active_layer_preset": "All Layers", + "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": "fffffff_ffffffff", + "zone_display_mode": 0 + }, + "meta": { + "filename": "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_prl", + "version": 3 + }, + "project": { + "files": [] + } +} diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_pro b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_pro new file mode 100644 index 00000000..4bc54b58 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_pro @@ -0,0 +1,527 @@ +{ + "board": { + "3dviewports": [], + "design_settings": { + "defaults": { + "board_outline_line_width": 0.049999999999999996, + "copper_line_width": 0.19999999999999998, + "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.049999999999999996, + "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.09999999999999999, + "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.09999999999999999, + "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.762, + "height": 1.524, + "width": 1.524 + }, + "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": 0.508 + } + }, + "diff_pair_dimensions": [ + { + "gap": 0.0, + "via_gap": 0.0, + "width": 0.0 + } + ], + "drc_exclusions": [ + "copper_edge_clearance|151052000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|6a847b13-3d48-4df7-8dd7-d515f51aacbf", + "copper_edge_clearance|151552000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|496964dd-0d25-423f-9576-ddcd7d92b9c0", + "copper_edge_clearance|152052000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|b54a21f9-d0ee-47bd-8a33-6d2ccb2f1964", + "copper_edge_clearance|152552000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|edf03a5b-8be1-48f8-8f16-4719d937182d", + "copper_edge_clearance|153052000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|16a60cfb-4140-483f-9675-22643c201dcd", + "copper_edge_clearance|153552000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|44970b45-f7b0-47cc-a114-209df0456d8f", + "copper_edge_clearance|154052000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|1ad63a96-1ef2-463e-9ea7-81ba46599172", + "copper_edge_clearance|154552000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|4a8a2808-da08-4211-a839-b545ca46843d", + "copper_edge_clearance|155052000|110246100|ae418f09-9594-49fa-ba14-c5ebf3097fc7|b2e7f160-81a2-4f3a-9cac-d6cba543336c", + "silk_over_copper|146240500|100142100|b5d214ca-8d2c-4892-a145-ebcdf525979d|a8fc3609-a41b-4706-8233-14786995acaa", + "silk_over_copper|155714700|105095100|a6bc6301-abbd-4acf-a77d-1f4e4d107e79|09b40b31-a75f-48c5-94ff-dac04c6dfaf8" + ], + "meta": { + "filename": "board_design_settings.json", + "version": 2 + }, + "rule_severities": { + "annular_width": "error", + "clearance": "error", + "copper_edge_clearance": "error", + "courtyards_overlap": "error", + "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_type_mismatch": "error", + "hole_clearance": "error", + "hole_near_hole": "error", + "invalid_outline": "error", + "item_on_disabled_layer": "error", + "items_not_allowed": "error", + "length_out_of_range": "error", + "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_over_copper": "warning", + "silk_overlap": "warning", + "skew_out_of_range": "error", + "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", + "zone_has_empty_net": "error", + "zones_intersect": "error" + }, + "rules": { + "allow_blind_buried_vias": false, + "allow_microvias": false, + "max_error": 0.005, + "min_clearance": 0.127, + "min_connection": 0.0, + "min_copper_edge_clearance": 0.024999999999999998, + "min_hole_clearance": 0.25, + "min_hole_to_hole": 0.25, + "min_microvia_diameter": 0.19999999999999998, + "min_microvia_drill": 0.09999999999999999, + "min_resolved_spokes": 2, + "min_silk_clearance": 0.0, + "min_text_height": 0.7999999999999999, + "min_text_thickness": 0.08, + "min_through_hole_diameter": 0.254, + "min_track_width": 0.127, + "min_via_annular_width": 0.049999999999999996, + "min_via_diameter": 0.39999999999999997, + "solder_mask_to_copper_clearance": 0.0, + "use_height_for_length_calcs": true + }, + "teardrop_options": [ + { + "td_allow_use_two_tracks": true, + "td_curve_segcount": 5, + "td_on_pad_in_zone": false, + "td_onpadsmd": true, + "td_onroundshapesonly": false, + "td_ontrackend": false, + "td_onviapad": true + } + ], + "teardrop_parameters": [ + { + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_target_name": "td_round_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_target_name": "td_rect_shape", + "td_width_to_size_filter_ratio": 0.9 + }, + { + "td_curve_segcount": 0, + "td_height_ratio": 1.0, + "td_length_ratio": 0.5, + "td_maxheight": 2.0, + "td_maxlen": 1.0, + "td_target_name": "td_track_end", + "td_width_to_size_filter_ratio": 0.9 + } + ], + "track_widths": [ + 0.0 + ], + "via_dimensions": [ + { + "diameter": 0.0, + "drill": 0.0 + } + ], + "zones_allow_external_fillets": false, + "zones_use_no_outline": true + }, + "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_label_syntax": "error", + "bus_to_bus_conflict": "error", + "bus_to_net_conflict": "error", + "different_unit_footprint": "error", + "different_unit_net": "error", + "duplicate_reference": "error", + "duplicate_sheet_names": "error", + "extra_units": "error", + "global_label_dangling": "warning", + "hier_label_mismatch": "error", + "label_dangling": "error", + "lib_symbol_issues": "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": "warning", + "power_pin_not_driven": "error", + "similar_labels": "warning", + "unannotated": "error", + "unit_value_mismatch": "error", + "unresolved_variable": "error", + "wire_dangling": "error" + } + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_pro", + "version": 1 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12, + "clearance": 0.127, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.127, + "via_diameter": 0.8, + "via_drill": 0.4, + "wire_width": 6 + }, + { + "bus_width": 12, + "clearance": 0.127, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "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.8, + "via_drill": 0.4, + "wire_width": 6 + }, + { + "bus_width": 12, + "clearance": 0.127, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "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.8, + "via_drill": 0.4, + "wire_width": 6 + } + ], + "meta": { + "version": 3 + }, + "net_colors": null, + "netclass_assignments": null, + "netclass_patterns": [] + }, + "pcbnew": { + "last_paths": { + "gencad": "", + "idf": "", + "netlist": "", + "specctra_dsn": "", + "step": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "annotate_start_num": 0, + "drawing": { + "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, + "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_external_command": "spice \"%I\"", + "subpart_first_id": 65, + "subpart_id_separator": 0 + }, + "sheets": [ + [ + "677683ff-9f49-4367-8af2-04a801740db6", + "" + ] + ], + "text_variables": {} +} diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch new file mode 100644 index 00000000..b37bfdbf --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.kicad_sch @@ -0,0 +1,1357 @@ +(kicad_sch (version 20211123) (generator eeschema) + + (uuid 677683ff-9f49-4367-8af2-04a801740db6) + + (paper "User" 300.507 217.881) + + (lib_symbols + (symbol "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:A4L-LOC" (in_bom yes) (on_board yes) + (property "Reference" "#FRAME" (id 0) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "A4L-LOC" (id 1) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (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) + ) + (property "ki_locked" "" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27))) + ) + (symbol "A4L-LOC_0_0" + (polyline + (pts + (xy 0 44.7675) + (xy 3.81 44.7675) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 89.535) + (xy 3.81 89.535) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 134.3025) + (xy 3.81 134.3025) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 3.81 3.81) + (xy 3.81 175.26) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 43.3917 0) + (xy 43.3917 3.81) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 43.3917 175.26) + (xy 43.3917 179.07) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 86.7833 0) + (xy 86.7833 3.81) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 86.7833 175.26) + (xy 86.7833 179.07) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 130.175 0) + (xy 130.175 3.81) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 130.175 175.26) + (xy 130.175 179.07) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 173.5667 0) + (xy 173.5667 3.81) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 173.5667 175.26) + (xy 173.5667 179.07) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 216.9583 0) + (xy 216.9583 3.81) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 216.9583 175.26) + (xy 216.9583 179.07) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 3.81) + (xy 3.81 3.81) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 3.81) + (xy 256.54 175.26) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 44.7675) + (xy 260.35 44.7675) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 89.535) + (xy 260.35 89.535) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 134.3025) + (xy 260.35 134.3025) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 175.26) + (xy 3.81 175.26) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 0) + (xy 260.35 0) + (xy 260.35 179.07) + (xy 0 179.07) + (xy 0 0) + ) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (text "1" (at 21.6958 1.905 0) + (effects (font (size 2.54 2.286))) + ) + (text "1" (at 21.6958 177.165 0) + (effects (font (size 2.54 2.286))) + ) + (text "2" (at 65.0875 1.905 0) + (effects (font (size 2.54 2.286))) + ) + (text "2" (at 65.0875 177.165 0) + (effects (font (size 2.54 2.286))) + ) + (text "3" (at 108.4792 1.905 0) + (effects (font (size 2.54 2.286))) + ) + (text "3" (at 108.4792 177.165 0) + (effects (font (size 2.54 2.286))) + ) + (text "4" (at 151.8708 1.905 0) + (effects (font (size 2.54 2.286))) + ) + (text "4" (at 151.8708 177.165 0) + (effects (font (size 2.54 2.286))) + ) + (text "5" (at 195.2625 1.905 0) + (effects (font (size 2.54 2.286))) + ) + (text "5" (at 195.2625 177.165 0) + (effects (font (size 2.54 2.286))) + ) + (text "6" (at 238.6542 1.905 0) + (effects (font (size 2.54 2.286))) + ) + (text "6" (at 238.6542 177.165 0) + (effects (font (size 2.54 2.286))) + ) + (text "A" (at 1.905 156.6863 0) + (effects (font (size 2.54 2.286))) + ) + (text "A" (at 258.445 156.6863 0) + (effects (font (size 2.54 2.286))) + ) + (text "B" (at 1.905 111.9188 0) + (effects (font (size 2.54 2.286))) + ) + (text "B" (at 258.445 111.9188 0) + (effects (font (size 2.54 2.286))) + ) + (text "C" (at 1.905 67.1513 0) + (effects (font (size 2.54 2.286))) + ) + (text "C" (at 258.445 67.1513 0) + (effects (font (size 2.54 2.286))) + ) + (text "D" (at 1.905 22.3838 0) + (effects (font (size 2.54 2.286))) + ) + (text "D" (at 258.445 22.3838 0) + (effects (font (size 2.54 2.286))) + ) + ) + (symbol "A4L-LOC_1_0" + (polyline + (pts + (xy 184.15 3.81) + (xy 184.15 24.13) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 184.15 24.13) + (xy 215.265 24.13) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 215.265 8.89) + (xy 215.265 3.81) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 215.265 8.89) + (xy 215.265 13.97) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 215.265 13.97) + (xy 215.265 19.05) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 215.265 13.97) + (xy 256.54 13.97) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 215.265 19.05) + (xy 215.265 24.13) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 215.265 19.05) + (xy 256.54 19.05) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 215.265 24.13) + (xy 256.54 24.13) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 234.95 3.81) + (xy 234.95 8.89) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 234.95 8.89) + (xy 215.265 8.89) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 234.95 8.89) + (xy 256.54 8.89) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 3.81) + (xy 256.54 8.89) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 8.89) + (xy 256.54 13.97) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 13.97) + (xy 256.54 19.05) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 256.54 19.05) + (xy 256.54 24.13) + ) + (stroke (width 0.1016) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (text ">DRAWING_NAME" (at 217.17 15.24 0) + (effects (font (size 2.54 2.159)) (justify left bottom)) + ) + (text ">LAST_DATE_TIME" (at 217.17 10.16 0) + (effects (font (size 2.286 1.9431)) (justify left bottom)) + ) + (text ">SHEET" (at 228.473 5.08 0) + (effects (font (size 2.54 2.159)) (justify left bottom)) + ) + (text "by joey castillo" (at 217.17 20.32 0) + (effects (font (size 2.54 2.159)) (justify left bottom)) + ) + (text "cc-by-sa 4.0" (at 236.22 5.08 0) + (effects (font (size 2.54 2.159)) (justify left bottom)) + ) + (text "oddly_specific_objects" (at 185.42 5.08 0) + (effects (font (size 4.572 4.572)) (justify left bottom)) + ) + (text "Sheet:" (at 216.916 4.953 0) + (effects (font (size 2.54 2.159)) (justify left bottom)) + ) + ) + ) + (symbol "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:CAP_CERAMIC_0603MP" (in_bom yes) (on_board yes) + (property "Reference" "C" (id 0) (at -2.29 1.25 90) + (effects (font (size 1.27 1.27))) + ) + (property "Value" "CAP_CERAMIC_0603MP" (id 1) (at 2.3 1.25 90) + (effects (font (size 1.27 1.27))) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:_0603MP" (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) + ) + (property "ki_locked" "" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27))) + ) + (symbol "CAP_CERAMIC_0603MP_1_0" + (rectangle (start -1.27 0.508) (end 1.27 1.016) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type outline)) + ) + (rectangle (start -1.27 1.524) (end 1.27 2.032) + (stroke (width 0) (type default) (color 0 0 0 0)) + (fill (type outline)) + ) + (polyline + (pts + (xy 0 0.762) + (xy 0 0) + ) + (stroke (width 0.1524) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 2.54) + (xy 0 1.778) + ) + (stroke (width 0.1524) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (pin passive line (at 0 5.08 270) (length 2.54) + (name "1" (effects (font (size 0 0)))) + (number "1" (effects (font (size 0 0)))) + ) + (pin passive line (at 0 -2.54 90) (length 2.54) + (name "2" (effects (font (size 0 0)))) + (number "2" (effects (font (size 0 0)))) + ) + ) + ) + (symbol "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:FH19C-9S-0.5SH_10-FFC" (in_bom yes) (on_board yes) + (property "Reference" "" (id 0) (at 8.89 17.78 0) + (effects (font (size 1.778 1.5113)) (justify left)) + ) + (property "Value" "FH19C-9S-0.5SH_10-FFC" (id 1) (at 8.89 15.24 0) + (effects (font (size 1.778 1.5113)) (justify left)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:FH19C9S05SH10-FFC" (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) + ) + (property "ki_locked" "" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27))) + ) + (symbol "FH19C-9S-0.5SH_10-FFC_1_0" + (polyline + (pts + (xy -5.08 12.7) + (xy -5.08 -12.7) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy -5.08 12.7) + (xy 7.62 12.7) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 7.62 -12.7) + (xy -5.08 -12.7) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 7.62 -12.7) + (xy 7.62 12.7) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (pin bidirectional line (at 12.7 10.16 180) (length 5.08) + (name "1" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 7.62 180) (length 5.08) + (name "2" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 5.08 180) (length 5.08) + (name "3" (effects (font (size 1.27 1.27)))) + (number "3" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 2.54 180) (length 5.08) + (name "4" (effects (font (size 1.27 1.27)))) + (number "4" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 0 180) (length 5.08) + (name "5" (effects (font (size 1.27 1.27)))) + (number "5" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 -2.54 180) (length 5.08) + (name "6" (effects (font (size 1.27 1.27)))) + (number "6" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 -5.08 180) (length 5.08) + (name "7" (effects (font (size 1.27 1.27)))) + (number "7" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 -7.62 180) (length 5.08) + (name "8" (effects (font (size 1.27 1.27)))) + (number "8" (effects (font (size 1.27 1.27)))) + ) + (pin bidirectional line (at 12.7 -10.16 180) (length 5.08) + (name "9" (effects (font (size 1.27 1.27)))) + (number "9" (effects (font (size 1.27 1.27)))) + ) + ) + ) + (symbol "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:GND" (power) (in_bom yes) (on_board yes) + (property "Reference" "" (id 0) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at -1.524 -2.54 0) + (effects (font (size 1.27 1.0795)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (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) + ) + (property "ki_locked" "" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27))) + ) + (symbol "GND_1_0" + (polyline + (pts + (xy -1.27 0) + (xy 1.27 0) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (pin power_in line (at 0 2.54 270) (length 2.54) + (name "GND" (effects (font (size 0 0)))) + (number "1" (effects (font (size 0 0)))) + ) + ) + ) + (symbol "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:LIS2DW12TR" (in_bom yes) (on_board yes) + (property "Reference" "U" (id 0) (at -15.2439 12.7032 0) + (effects (font (size 1.7784 1.5116)) (justify left bottom)) + ) + (property "Value" "LIS2DW12TR" (id 1) (at -15.2494 -17.7909 0) + (effects (font (size 1.779 1.5121)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:LGA12R50P4X4_200X200X70" (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) + ) + (property "ki_locked" "" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27))) + ) + (symbol "LIS2DW12TR_1_0" + (polyline + (pts + (xy -15.24 -15.24) + (xy -15.24 12.7) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy -15.24 12.7) + (xy 15.24 12.7) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 15.24 -15.24) + (xy -15.24 -15.24) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 15.24 12.7) + (xy 15.24 -15.24) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (pin input clock (at -20.32 2.54 0) (length 5.08) + (name "SCL/SPC" (effects (font (size 1.27 1.27)))) + (number "1" (effects (font (size 0 0)))) + ) + (pin power_in line (at 20.32 7.62 180) (length 5.08) + (name "VDD_IO" (effects (font (size 1.27 1.27)))) + (number "10" (effects (font (size 0 0)))) + ) + (pin output line (at 20.32 0 180) (length 5.08) + (name "INT2" (effects (font (size 1.27 1.27)))) + (number "11" (effects (font (size 0 0)))) + ) + (pin output line (at 20.32 2.54 180) (length 5.08) + (name "INT1" (effects (font (size 1.27 1.27)))) + (number "12" (effects (font (size 0 0)))) + ) + (pin input line (at -20.32 0 0) (length 5.08) + (name "CS" (effects (font (size 1.27 1.27)))) + (number "2" (effects (font (size 0 0)))) + ) + (pin bidirectional line (at -20.32 -5.08 0) (length 5.08) + (name "SDO/SDA0" (effects (font (size 1.27 1.27)))) + (number "3" (effects (font (size 0 0)))) + ) + (pin bidirectional line (at -20.32 -7.62 0) (length 5.08) + (name "SDA/SDI/SDO" (effects (font (size 1.27 1.27)))) + (number "4" (effects (font (size 0 0)))) + ) + (pin power_in line (at 20.32 -12.7 180) (length 5.08) + (name "GND" (effects (font (size 1.27 1.27)))) + (number "6" (effects (font (size 0 0)))) + ) + (pin passive line (at 20.32 -5.08 180) (length 5.08) + (name "RES" (effects (font (size 1.27 1.27)))) + (number "7" (effects (font (size 0 0)))) + ) + (pin power_in line (at 20.32 -12.7 180) (length 5.08) + (name "GND" (effects (font (size 1.27 1.27)))) + (number "8" (effects (font (size 0 0)))) + ) + (pin power_in line (at 20.32 10.16 180) (length 5.08) + (name "VDD" (effects (font (size 1.27 1.27)))) + (number "9" (effects (font (size 0 0)))) + ) + ) + ) + (symbol "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:TPB1,27" (in_bom yes) (on_board yes) + (property "Reference" "TP" (id 0) (at -1.27 1.27 0) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Value" "TPB1,27" (id 1) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (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) + ) + (property "ki_locked" "" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27))) + ) + (symbol "TPB1,27_1_0" + (polyline + (pts + (xy -0.762 -0.762) + (xy 0 0) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 -1.524) + (xy -0.762 -0.762) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0 0) + (xy 0.762 -0.762) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 0.762 -0.762) + (xy 0 -1.524) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (text ">TP_SIGNAL_NAME" (at 1.27 -1.27 0) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (pin input line (at 0 -2.54 90) (length 2.54) + (name "TP" (effects (font (size 0 0)))) + (number "TP" (effects (font (size 0 0)))) + ) + ) + ) + (symbol "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:VCC" (power) (in_bom yes) (on_board yes) + (property "Reference" "#P+" (id 0) (at 0 0 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at -2.54 -2.54 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (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) + ) + (property "ki_locked" "" (id 4) (at 0 0 0) + (effects (font (size 1.27 1.27))) + ) + (symbol "VCC_1_0" + (polyline + (pts + (xy 0 0) + (xy -1.27 -1.905) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (polyline + (pts + (xy 1.27 -1.905) + (xy 0 0) + ) + (stroke (width 0.254) (type default) (color 0 0 0 0)) + (fill (type none)) + ) + (pin power_in line (at 0 -2.54 90) (length 2.54) + (name "VCC" (effects (font (size 0 0)))) + (number "1" (effects (font (size 0 0)))) + ) + ) + ) + ) + + (junction (at 111.76 116.84) (diameter 0) (color 0 0 0 0) + (uuid 3be9f4a3-8a02-4fd7-9f6c-da7d582dafea) + ) + (junction (at 248.92 58.42) (diameter 0) (color 0 0 0 0) + (uuid 5b5c2da6-e127-4244-a9c7-89d3dd9b9d0e) + ) + (junction (at 248.92 55.88) (diameter 0) (color 0 0 0 0) + (uuid 5e75c680-cd1f-4efb-9c88-ff8e2b2b1ff8) + ) + (junction (at 167.64 66.04) (diameter 0) (color 0 0 0 0) + (uuid 6a9d2193-0f99-472a-8866-d4e6371e2972) + ) + (junction (at 248.92 63.5) (diameter 0) (color 0 0 0 0) + (uuid 6ecd4c68-b046-4b0f-889a-5d41cd1dc2cb) + ) + (junction (at 231.14 78.74) (diameter 0) (color 0 0 0 0) + (uuid b0ff7d85-ee52-44cc-ad09-698a1094d4cf) + ) + (junction (at 111.76 114.3) (diameter 0) (color 0 0 0 0) + (uuid e8978151-5b61-49d5-b364-1825da55ca17) + ) + + (wire (pts (xy 248.92 58.42) (xy 248.92 63.5)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 00d829a1-a4cd-42f2-8807-7979f0cece5f) + ) + (wire (pts (xy 182.88 66.04) (xy 167.64 66.04)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 0851e394-3c6e-47b6-a8d7-6f34d745ac74) + ) + (wire (pts (xy 116.84 114.3) (xy 111.76 114.3)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 0f64423c-7737-49b8-8d8d-a03d155058f8) + ) + (wire (pts (xy 223.52 78.74) (xy 231.14 78.74)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 154fdca3-d781-4b9f-b75d-d963b7d0e418) + ) + (wire (pts (xy 182.88 73.66) (xy 172.72 73.66)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 156e755c-9071-45f4-b96c-f6dfdc03927b) + ) + (wire (pts (xy 111.76 111.76) (xy 111.76 114.3)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 2e34a7f8-00f1-4817-860a-c76dcb24da8b) + ) + (wire (pts (xy 182.88 71.12) (xy 167.64 71.12)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 2e815da2-028a-4df3-9e13-35757d155729) + ) + (wire (pts (xy 167.64 66.04) (xy 167.64 71.12)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 319cc7d9-d4cf-4034-a187-92e0ce0f6924) + ) + (wire (pts (xy 111.76 116.84) (xy 76.2 116.84)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 3472f09d-8a9d-4ef2-8905-1691eee48827) + ) + (wire (pts (xy 182.88 63.5) (xy 172.72 63.5)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 3747cbe9-7a9d-41ff-946c-74d900957c2d) + ) + (wire (pts (xy 99.06 129.54) (xy 76.2 129.54)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 389165f9-cc0a-4e0e-9b05-8ddd936597dc) + ) + (wire (pts (xy 99.06 132.08) (xy 76.2 132.08)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 4afa6803-f447-4dd5-9d26-7e99519a7bc4) + ) + (wire (pts (xy 248.92 63.5) (xy 248.92 71.12)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 5ef45c41-2f65-4741-9664-795626b404b6) + ) + (wire (pts (xy 248.92 55.88) (xy 223.52 55.88)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 638ddb51-d601-4887-bed6-fce116198a39) + ) + (wire (pts (xy 111.76 116.84) (xy 111.76 119.38)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 653bb1bb-8447-4e5a-87fd-d46e8613c608) + ) + (wire (pts (xy 231.14 78.74) (xy 231.14 81.28)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 724d0af0-f852-47b9-b980-850731e5f9e5) + ) + (wire (pts (xy 167.64 53.34) (xy 167.64 66.04)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 755d34bd-e50b-424e-87fa-d2c4acd2a268) + ) + (wire (pts (xy 231.14 71.12) (xy 231.14 78.74)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid 9290f265-8570-4ab7-b46f-9e86358ae1bc) + ) + (wire (pts (xy 248.92 55.88) (xy 248.92 58.42)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid a1fa7a94-7c89-4b7e-8762-b4a09f13c9ef) + ) + (wire (pts (xy 99.06 121.92) (xy 76.2 121.92)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid aa45cb4e-b839-42a1-9a53-2492f871c18d) + ) + (wire (pts (xy 241.3 78.74) (xy 241.3 81.28)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid b1159d88-bd16-4ca1-bf5a-cfff2c81d09c) + ) + (wire (pts (xy 248.92 53.34) (xy 248.92 55.88)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid b466aaf1-3c2f-4060-b31f-ddf149d17782) + ) + (wire (pts (xy 236.22 66.04) (xy 223.52 66.04)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid bb32e1ee-b162-47c5-8677-4117b6e7274d) + ) + (wire (pts (xy 248.92 58.42) (xy 223.52 58.42)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid c3420623-f638-464d-8f0f-5edb87189e8b) + ) + (wire (pts (xy 76.2 119.38) (xy 99.06 119.38)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid c6fdc16c-fe06-4b73-8abf-ac7c1a3293a2) + ) + (wire (pts (xy 111.76 116.84) (xy 114.3 116.84)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid d79d922e-c8b5-4de7-b825-0dd36d6321d2) + ) + (wire (pts (xy 111.76 114.3) (xy 76.2 114.3)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid db884c28-3707-4cc9-8c02-fb5a883e8a44) + ) + (wire (pts (xy 99.06 127) (xy 76.2 127)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid e111b61b-2d82-48b0-a212-438605d810dd) + ) + (wire (pts (xy 248.92 78.74) (xy 248.92 81.28)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid eef64e3f-263b-40e6-8ee4-f84dd60d3ea2) + ) + (wire (pts (xy 223.52 71.12) (xy 231.14 71.12)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid ef2fed58-27a4-4522-9d1d-5ddee25dbff9) + ) + (wire (pts (xy 101.6 124.46) (xy 76.2 124.46)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid f214933d-b730-4e16-8e97-075bcb21090f) + ) + (wire (pts (xy 241.3 63.5) (xy 248.92 63.5)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid f2a585fb-25cb-45c6-8051-c610bbc42abe) + ) + (wire (pts (xy 223.52 63.5) (xy 236.22 63.5)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid fdea05fe-b72a-46d3-b6da-d22f0cf2787d) + ) + (wire (pts (xy 241.3 71.12) (xy 241.3 63.5)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid fecb65be-7f95-4d3c-aeea-59ad59501f67) + ) + (wire (pts (xy 99.06 134.62) (xy 76.2 134.62)) + (stroke (width 0) (type default) (color 0 0 0 0)) + (uuid ff2311d6-deb7-4124-be16-42c951cc83c7) + ) + + (label "SDA" (at 99.06 129.54 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 1f2ddf35-dc5b-48a9-9aeb-dae96a442071) + ) + (label "SCL" (at 99.06 132.08 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 21b53084-bdf2-4616-92c3-7aa46fbe795a) + ) + (label "A1_RX" (at 99.06 127 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 38d631f8-88fd-49dd-a9a6-91c3d66cbcd2) + ) + (label "GND" (at 99.06 116.84 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 38fc0840-7c4f-4f64-9c7e-eacf084ae5f7) + ) + (label "A3_INT2" (at 236.22 66.04 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 44269636-46bc-41ec-9446-1f65d73ec9b3) + ) + (label "VCC" (at 226.06 55.88 0) + (effects (font (size 1.2446 1.2446)) (justify left bottom)) + (uuid 46da8db1-4215-4027-8094-79fcf2ad9c58) + ) + (label "A0_UNUSED" (at 99.06 134.62 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 4d41f05b-1450-4e64-859b-23cf1aa567f4) + ) + (label "VCC" (at 172.72 71.12 0) + (effects (font (size 1.2446 1.2446)) (justify left bottom)) + (uuid 500c79ad-8e89-471f-8800-130c5e0e98dc) + ) + (label "SDA" (at 172.72 73.66 0) + (effects (font (size 1.2446 1.2446)) (justify left bottom)) + (uuid 6d2032ff-ae6e-4535-8987-a36cd0d680a2) + ) + (label "A4_INT1" (at 236.22 63.5 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 76858c84-c012-460a-9f40-e1ccef0b211e) + ) + (label "A3_INT2" (at 99.06 121.92 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid 77150e1e-6cd5-4d60-9843-46ed9469effc) + ) + (label "VCC" (at 226.06 58.42 0) + (effects (font (size 1.2446 1.2446)) (justify left bottom)) + (uuid 96d46355-5a7b-4240-9b6b-58ab63ad3511) + ) + (label "VCC" (at 172.72 66.04 0) + (effects (font (size 1.2446 1.2446)) (justify left bottom)) + (uuid 9fa2f432-cd00-4f4f-ab3e-08976a805c8c) + ) + (label "A2_TX" (at 99.06 124.46 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid bb351afb-4b35-478a-a1a1-26778717767e) + ) + (label "A4_INT1" (at 99.06 119.38 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid c79ddd1b-c6b5-40f9-bc81-ad92b0f855e5) + ) + (label "VCC" (at 99.06 114.3 180) + (effects (font (size 1.2446 1.2446)) (justify right bottom)) + (uuid e0b7aef4-a3dc-4143-81f5-ca93c61a48a9) + ) + (label "SCL" (at 172.72 63.5 0) + (effects (font (size 1.2446 1.2446)) (justify left bottom)) + (uuid f5ef6b68-a5a1-41f8-9851-28fffa1a6b43) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:GND") (at 248.92 83.82 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 08832b7f-d991-4c9c-8160-957a0d857246) + (property "Reference" "#U$014" (id 0) (at 248.92 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 247.396 86.36 0) + (effects (font (size 1.27 1.0795)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 248.92 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 248.92 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 4709ba8c-472b-44ac-bfea-6c6701579d64)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:TPB1,27") (at 104.14 124.46 270) (unit 1) + (in_bom yes) (on_board yes) + (uuid 1936aa8e-84b5-486e-a2d5-81ae44fd41c7) + (property "Reference" "TP3" (id 0) (at 105.41 123.19 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Value" "TPB1,27" (id 1) (at 104.14 124.46 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (id 2) (at 104.14 124.46 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 104.14 124.46 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "TP" (uuid e469a65d-dae5-4bf9-89e0-b404b90b6762)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:GND") (at 231.14 83.82 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 1b04004e-9983-4fd4-af9a-0f3ede119d12) + (property "Reference" "#U$01" (id 0) (at 231.14 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 229.616 86.36 0) + (effects (font (size 1.27 1.0795)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 231.14 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 231.14 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 0b3d80bf-3b39-43e0-bf5d-7a74ac6a44c9)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:VCC") (at 111.76 109.22 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 27a644f0-a528-464d-a151-576c61770f20) + (property "Reference" "#P+01" (id 0) (at 111.76 109.22 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 109.22 111.76 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 111.76 109.22 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 111.76 109.22 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 1d13ddfe-b7e3-4a22-8ae4-d21ab7865026)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:A4L-LOC") (at 17.78 198.12 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 3a5d2761-9f91-41e6-ada5-9ae9f8496ca2) + (property "Reference" "#FRAME1" (id 0) (at 17.78 198.12 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "A4L-LOC" (id 1) (at 17.78 198.12 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 17.78 198.12 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 17.78 198.12 0) + (effects (font (size 1.27 1.27)) hide) + ) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:FH19C-9S-0.5SH_10-FFC") (at 63.5 124.46 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 4dc3cbb6-fb37-42a6-81e4-ab57e8e35700) + (property "Reference" "U$3" (id 0) (at 72.39 106.68 0) + (effects (font (size 1.778 1.5113)) (justify left)) + ) + (property "Value" "FH19C-9S-0.5SH_10-FFC" (id 1) (at 72.39 109.22 0) + (effects (font (size 1.778 1.5113)) (justify left)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:FH19C9S05SH10-FFC" (id 2) (at 63.5 124.46 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 63.5 124.46 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 72b7908a-a147-4c13-9bc2-0f190c00bd00)) + (pin "2" (uuid 93127296-6db8-4f2d-ab2e-70bcfbd19dc5)) + (pin "3" (uuid 1d032ee1-419f-4e2d-b2bc-24b14f50ad69)) + (pin "4" (uuid ded1e12f-6a29-45c8-aee8-823f6f972229)) + (pin "5" (uuid 4e597a75-84c2-4e3a-9f69-f7f6e5fa1bda)) + (pin "6" (uuid c1e17350-4910-4735-a63a-d0906e7c105c)) + (pin "7" (uuid 7e6c73cc-1198-4aa9-a7a6-aa505f4a1a2a)) + (pin "8" (uuid aca85423-5f80-4e94-8678-d85d20991330)) + (pin "9" (uuid 3e4a8598-b196-4243-b6e1-7411945d1d18)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:VCC") (at 167.64 50.8 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 52195f21-2ebf-4931-bb78-0509347a85b2) + (property "Reference" "#P+03" (id 0) (at 167.64 50.8 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 165.1 53.34 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 167.64 50.8 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 167.64 50.8 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 1e5074b2-0daf-46ed-8b33-13c9df71009c)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:TPB1,27") (at 116.84 116.84 270) (unit 1) + (in_bom yes) (on_board yes) + (uuid 6ea9dd18-adcc-4aba-8efa-d45943bee5d6) + (property "Reference" "TP1" (id 0) (at 118.11 118.11 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Value" "TPB1,27" (id 1) (at 116.84 116.84 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (id 2) (at 116.84 116.84 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 116.84 116.84 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "TP" (uuid 81e7a0b7-339c-44c8-a5a6-474ef8c169b7)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:CAP_CERAMIC_0603MP") (at 248.92 76.2 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid 81f117f8-2e22-4d95-9843-a6438cc9b8fd) + (property "Reference" "C1" (id 0) (at 246.63 74.95 90)) + (property "Value" "0.1uF" (id 1) (at 251.22 74.95 90)) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:_0603MP" (id 2) (at 248.92 76.2 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 248.92 76.2 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid ad164184-ecb9-4520-8bd1-3781f2bb9f35)) + (pin "2" (uuid c52bd0b0-2c8d-4af6-b874-54b820cd2478)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:TPB1,27") (at 101.6 127 270) (unit 1) + (in_bom yes) (on_board yes) + (uuid a4b4c4fb-1c78-4a88-b6d6-c95ced14e6a1) + (property "Reference" "TP4" (id 0) (at 102.87 128.27 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Value" "TPB1,27" (id 1) (at 101.6 127 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (id 2) (at 101.6 127 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 101.6 127 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "TP" (uuid 200c6f8a-c516-4d05-906f-a06de5c8f920)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:GND") (at 241.3 83.82 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid bba0ef42-0f18-42c4-9c14-469ed04b2b13) + (property "Reference" "#U$02" (id 0) (at 241.3 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 239.776 86.36 0) + (effects (font (size 1.27 1.0795)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 241.3 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 241.3 83.82 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid d6779978-9459-4c86-a16f-794c7bc57caa)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:CAP_CERAMIC_0603MP") (at 241.3 73.66 180) (unit 1) + (in_bom yes) (on_board yes) + (uuid dbf111d5-5941-4c1b-8fad-675981ce34f4) + (property "Reference" "C2" (id 0) (at 243.59 74.91 90)) + (property "Value" "10uF" (id 1) (at 239 74.91 90)) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:_0603MP" (id 2) (at 241.3 73.66 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 241.3 73.66 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 00d2080f-6c63-4b6f-8f3d-d355189a4153)) + (pin "2" (uuid 80a799d6-a88a-48f5-84e5-0598868f31f3)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:GND") (at 111.76 121.92 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid e3514b09-efc5-499f-bd79-ef5eca3c0b60) + (property "Reference" "#U$04" (id 0) (at 111.76 121.92 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "GND" (id 1) (at 110.236 124.46 0) + (effects (font (size 1.27 1.0795)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 111.76 121.92 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 111.76 121.92 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid e0dddb6b-1763-4e9f-b200-729d444448c1)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:VCC") (at 248.92 50.8 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid e9a74e60-54a5-4aa5-b8e6-4f07382f4dcb) + (property "Reference" "#P+02" (id 0) (at 248.92 50.8 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Value" "VCC" (id 1) (at 246.38 53.34 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:" (id 2) (at 248.92 50.8 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 248.92 50.8 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid e9de28fb-a205-454e-aed8-8c8fbcb7ffee)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:TPB1,27") (at 119.38 114.3 270) (unit 1) + (in_bom yes) (on_board yes) + (uuid ec24969b-8391-44db-a79f-3fa50f7e4597) + (property "Reference" "TP2" (id 0) (at 120.65 113.03 90) + (effects (font (size 1.778 1.5113)) (justify left bottom)) + ) + (property "Value" "TPB1,27" (id 1) (at 119.38 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:B1,27" (id 2) (at 119.38 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 119.38 114.3 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "TP" (uuid 0632665e-cb0e-41a5-9b86-c608fcc0bf7b)) + ) + + (symbol (lib_id "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import:LIS2DW12TR") (at 203.2 66.04 0) (unit 1) + (in_bom yes) (on_board yes) + (uuid f61a4c5e-e4e7-40df-976e-1899d4c8a12a) + (property "Reference" "U2" (id 0) (at 187.9561 53.3368 0) + (effects (font (size 1.7784 1.5116)) (justify left bottom)) + ) + (property "Value" "LIS2DW12TR" (id 1) (at 187.9506 83.8309 0) + (effects (font (size 1.779 1.5121)) (justify left bottom)) + ) + (property "Footprint" "OSO-MISC-21-021 Sensor Watch Motion II:LGA12R50P4X4_200X200X70" (id 2) (at 203.2 66.04 0) + (effects (font (size 1.27 1.27)) hide) + ) + (property "Datasheet" "" (id 3) (at 203.2 66.04 0) + (effects (font (size 1.27 1.27)) hide) + ) + (pin "1" (uuid 5437a445-76be-45a9-bb36-e8226cbb76a4)) + (pin "10" (uuid aa2f966b-27db-4c46-b37b-8938b6e96a7f)) + (pin "11" (uuid c232d3d2-179b-4c32-be66-1a8ae272c155)) + (pin "12" (uuid 8730c793-1e0a-457f-a42f-dcfafda24f0c)) + (pin "2" (uuid 2600904f-6913-4cf0-9bd0-d929f49ef6bf)) + (pin "3" (uuid b6155be8-ddbb-47d3-8286-904b3aa12873)) + (pin "4" (uuid 1791a69b-a561-4028-ac1a-19f15f51996d)) + (pin "6" (uuid 8e4926ae-605c-49b2-b92b-7a1af989fde5)) + (pin "7" (uuid 41069e2b-d371-466e-92f5-369959deaacf)) + (pin "8" (uuid 27b027fb-59ee-4adb-b292-2d2f884c594e)) + (pin "9" (uuid 4732e433-8b02-41d8-9a36-1db5b79ff2ad)) + ) + + (sheet_instances + (path "/" (page "1")) + ) + + (symbol_instances + (path "/3a5d2761-9f91-41e6-ada5-9ae9f8496ca2" + (reference "#FRAME1") (unit 1) (value "A4L-LOC") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/27a644f0-a528-464d-a151-576c61770f20" + (reference "#P+01") (unit 1) (value "VCC") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/e9a74e60-54a5-4aa5-b8e6-4f07382f4dcb" + (reference "#P+02") (unit 1) (value "VCC") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/52195f21-2ebf-4931-bb78-0509347a85b2" + (reference "#P+03") (unit 1) (value "VCC") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/1b04004e-9983-4fd4-af9a-0f3ede119d12" + (reference "#U$01") (unit 1) (value "GND") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/bba0ef42-0f18-42c4-9c14-469ed04b2b13" + (reference "#U$02") (unit 1) (value "GND") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/e3514b09-efc5-499f-bd79-ef5eca3c0b60" + (reference "#U$04") (unit 1) (value "GND") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/08832b7f-d991-4c9c-8160-957a0d857246" + (reference "#U$014") (unit 1) (value "GND") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:") + ) + (path "/81f117f8-2e22-4d95-9843-a6438cc9b8fd" + (reference "C1") (unit 1) (value "0.1uF") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:_0603MP") + ) + (path "/dbf111d5-5941-4c1b-8fad-675981ce34f4" + (reference "C2") (unit 1) (value "10uF") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:_0603MP") + ) + (path "/6ea9dd18-adcc-4aba-8efa-d45943bee5d6" + (reference "TP1") (unit 1) (value "TPB1,27") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27") + ) + (path "/ec24969b-8391-44db-a79f-3fa50f7e4597" + (reference "TP2") (unit 1) (value "TPB1,27") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27") + ) + (path "/1936aa8e-84b5-486e-a2d5-81ae44fd41c7" + (reference "TP3") (unit 1) (value "TPB1,27") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27") + ) + (path "/a4b4c4fb-1c78-4a88-b6d6-c95ced14e6a1" + (reference "TP4") (unit 1) (value "TPB1,27") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:B1,27") + ) + (path "/4dc3cbb6-fb37-42a6-81e4-ab57e8e35700" + (reference "U$3") (unit 1) (value "FH19C-9S-0.5SH_10-FFC") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:FH19C9S05SH10-FFC") + ) + (path "/f61a4c5e-e4e7-40df-976e-1899d4c8a12a" + (reference "U2") (unit 1) (value "LIS2DW12TR") (footprint "OSO-MISC-21-021 Sensor Watch Motion II:LGA12R50P4X4_200X200X70") + ) + ) +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/B1,27.kicad_mod b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/B1,27.kicad_mod new file mode 100644 index 00000000..24c34863 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/B1,27.kicad_mod @@ -0,0 +1,15 @@ +(footprint "B1,27" (version 20211014) (generator pcbnew) + (layer "F.Cu") + (tedit 0) + (descr "TEST PAD") + (fp_text reference "REF**" (at -0.635 -1.016) (layer "F.SilkS") + (effects (font (size 1.143 1.143) (thickness 0.127)) (justify left bottom)) + (tstamp 66611b0e-db6e-4021-9427-c32ecc053115) + ) + (fp_text value ">VALUE" (at -0.635 0.762) (layer "F.Fab") + (effects (font (size 0.023368 0.023368) (thickness 0.002032)) (justify left bottom)) + (tstamp 4ac60ae9-6f70-4bce-8da5-6eac3cd3a3ad) + ) + (pad "TP" smd roundrect (at 0 0) (size 1.27 1.27) (layers "F.Cu" "F.Mask") (roundrect_rratio 0.5) + (solder_mask_margin 0.0635) (tstamp b8f939e4-9cdb-4994-993d-3ae41bb30177)) +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/FH19C9S05SH10-FFC.kicad_mod b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/FH19C9S05SH10-FFC.kicad_mod new file mode 100644 index 00000000..c3af1333 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/FH19C9S05SH10-FFC.kicad_mod @@ -0,0 +1,42 @@ +(footprint "FH19C9S05SH10-FFC" (version 20211014) (generator pcbnew) + (layer "F.Cu") + (tedit 0) + (descr "FH19C-9S-0.5SH(10)-1
\n") + (fp_text reference "REF**" (at 0 0) (layer "F.SilkS") + (effects (font (size 1.27 1.27) (thickness 0.15))) + (tstamp 2891e198-646d-4022-ba59-cc504d2b7d16) + ) + (fp_text value "" (at 0 0) (layer "F.Fab") + (effects (font (size 1.27 1.27) (thickness 0.15))) + (tstamp cb35e01a-ade6-4e76-8860-9691b680c03d) + ) + (fp_poly (pts + (xy 2.56543 3.556) + (xy -2.56537 3.556) + (xy -2.56643 0.898) + (xy 2.56437 0.898) + ) (layer "B.Mask") (width 0) (fill solid) (tstamp 2b3c01e4-c750-4f56-8673-86cd61068635)) + (fp_line (start -2.4892 0) (end -2.4892 3.35) (layer "Edge.Cuts") (width 0.05) (tstamp 593436ec-2ee2-4f89-a482-ad9d710ea79d)) + (fp_line (start 2.4892 0) (end 2.4892 3.35) (layer "Edge.Cuts") (width 0.05) (tstamp 757ab00f-2565-4955-8ca5-247d2ab4a459)) + (fp_line (start -2.3392 3.5) (end 2.3392 3.5) (layer "Edge.Cuts") (width 0.05) (tstamp be6a643e-0f3d-406b-82ce-bc5dd821e563)) + (fp_arc (start -2.3392 3.5) (mid -2.445266 3.456066) (end -2.4892 3.35) (layer "Edge.Cuts") (width 0.05) (tstamp eeb7dd92-dd48-45ec-b09f-f99710ea3b88)) + (fp_arc (start 2.4892 3.35) (mid 2.445266 3.456066) (end 2.3392 3.5) (layer "Edge.Cuts") (width 0.05) (tstamp eecbbc5b-a539-4c7c-8789-2616156ab52b)) + (pad "1" smd rect (at 2 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp 2b902acc-4a08-4047-ad60-bbf1eeaab6ab)) + (pad "2" smd rect (at 1.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp d8e62cc7-7124-4f2e-889d-3746b3d86a64)) + (pad "3" smd rect (at 1 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp f999fa66-5f95-4c6d-9b5b-e8836c9dc89d)) + (pad "4" smd rect (at 0.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp ab03249d-815c-4b6a-af6f-cad8e8308166)) + (pad "5" smd rect (at 0 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp badef670-3ddf-4b49-83a7-fe6eb4b07cad)) + (pad "6" smd rect (at -0.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp 102be87f-c42b-4e09-b634-d2882c35f5ae)) + (pad "7" smd rect (at -1 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp 092cbced-a774-4b39-a3d1-c6d31915fb62)) + (pad "8" smd rect (at -1.5 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp 1b3a5bc0-e9f9-47de-b2f0-4672614e470a)) + (pad "9" smd rect (at -2 2.25 90) (size 2.5 0.347) (layers "B.Cu" "B.Mask") + (solder_mask_margin 0.0635) (tstamp b0acd8bd-47e9-4935-a884-665ee78af58f)) +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/LGA12R50P4X4_200X200X70.kicad_mod b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/LGA12R50P4X4_200X200X70.kicad_mod new file mode 100644 index 00000000..5709a710 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/LGA12R50P4X4_200X200X70.kicad_mod @@ -0,0 +1,54 @@ +(footprint "LGA12R50P4X4_200X200X70" (version 20211014) (generator pcbnew) + (layer "F.Cu") + (tedit 0) + (fp_text reference "REF**" (at -1.50225 -1.50225) (layer "F.SilkS") + (effects (font (size 0.561674 0.561674) (thickness 0.048841)) (justify left bottom)) + (tstamp a841a941-dbd4-406e-9e83-16f988577ed7) + ) + (fp_text value ">VALUE" (at -1.50114 2.001518) (layer "F.Fab") + (effects (font (size 0.561257 0.561257) (thickness 0.048805)) (justify left bottom)) + (tstamp 0a9955a0-6068-4d38-b05e-1ba1984749d1) + ) + (fp_line (start 0.555 -1.05) (end 1.05 -1.05) (layer "F.SilkS") (width 0.127) (tstamp 1ec22d83-cad4-4dee-9f07-ac20256d34bb)) + (fp_line (start 0.555 1.05) (end 1.05 1.05) (layer "F.SilkS") (width 0.127) (tstamp 2ab2f09e-0c2e-40e1-8cad-8618b2964772)) + (fp_line (start 1.05 1.05) (end 1.05 0.555) (layer "F.SilkS") (width 0.127) (tstamp 691adb00-c7cf-42cd-b3b3-3cb402f71864)) + (fp_line (start -1.05 -0.555) (end -1.05 -1.05) (layer "F.SilkS") (width 0.127) (tstamp 693e0e56-7ca2-4e3c-943f-7d93d816dd88)) + (fp_line (start -1.05 -1.05) (end -0.555 -1.05) (layer "F.SilkS") (width 0.127) (tstamp 6dd9b638-7d83-48ad-9c0b-d0a3b14ff194)) + (fp_line (start 1.05 -1.05) (end 1.05 -0.555) (layer "F.SilkS") (width 0.127) (tstamp cfdfed39-3585-4f3d-af2c-df735f17f29f)) + (fp_line (start -1.05 0.555) (end -1.05 1.05) (layer "F.SilkS") (width 0.127) (tstamp d5677caf-5ab2-407c-a936-e4226c17744c)) + (fp_line (start -1.05 1.05) (end -0.555 1.05) (layer "F.SilkS") (width 0.127) (tstamp f1e92131-893d-407c-85ed-04a3d79dc8bc)) + (fp_circle (center -1.5 -0.75) (end -1.45 -0.75) (layer "F.SilkS") (width 0.1) (fill none) (tstamp 6e7bb868-6df4-43cc-ae2f-1d2b706e4c2e)) + (fp_line (start 1.25 -1.25) (end 1.25 1.25) (layer "F.CrtYd") (width 0.05) (tstamp 47f30fc1-7ed7-4645-8836-972c17bb4fe5)) + (fp_line (start -1.25 1.25) (end -1.25 -1.25) (layer "F.CrtYd") (width 0.05) (tstamp 4c1ed0d1-05e7-40bc-b7c8-845b3478b8d5)) + (fp_line (start 1.25 1.25) (end -1.25 1.25) (layer "F.CrtYd") (width 0.05) (tstamp 593de62e-58e0-4efc-8ba1-b886cd08985c)) + (fp_line (start -1.25 -1.25) (end 1.25 -1.25) (layer "F.CrtYd") (width 0.05) (tstamp 75cee19c-8883-4eb2-bb54-93d3242790c4)) + (fp_line (start 1 -1) (end 1 1) (layer "F.Fab") (width 0.127) (tstamp 0e31b15a-0bed-4c02-a998-422f761d6f21)) + (fp_line (start 1 1) (end -1 1) (layer "F.Fab") (width 0.127) (tstamp 25e98454-7b51-4256-99ce-d71274a09ddd)) + (fp_line (start -1 1) (end -1 -1) (layer "F.Fab") (width 0.127) (tstamp 9455eb49-e46c-4cc1-931f-245a8cf4484a)) + (fp_line (start -1 -1) (end 1 -1) (layer "F.Fab") (width 0.127) (tstamp 96a4c6a7-70a8-4dc8-851d-90638be2de9c)) + (fp_circle (center -0.75 -0.75) (end -0.7 -0.75) (layer "F.Fab") (width 0.1) (fill none) (tstamp 3ca22245-934d-45a7-84cc-c2d904109998)) + (pad "1" smd rect (at -0.76 -0.75) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 9b76f23f-a839-4e38-ab2f-47fe312a5451)) + (pad "2" smd rect (at -0.76 -0.25) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 084df340-c833-4415-b5ea-ddf2da7aeab1)) + (pad "3" smd rect (at -0.76 0.25) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 56e68fb3-7611-43b1-852f-2d9d710a10d4)) + (pad "4" smd rect (at -0.76 0.75) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp e1e62aad-3a36-476f-b704-a4b4240137d2)) + (pad "5" smd rect (at -0.25 0.76) (size 0.35 0.4) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp cd41e53a-0c76-4c5f-800c-753fe980f311)) + (pad "6" smd rect (at 0.25 0.76) (size 0.35 0.4) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 8d08899e-801e-464e-a053-80ece5d40773)) + (pad "7" smd rect (at 0.76 0.75) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 124b0827-61a2-4ca5-9e46-df5984bdff25)) + (pad "8" smd rect (at 0.76 0.25) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 4a93be6c-d59b-4ab5-b017-af8dd5c58e3a)) + (pad "9" smd rect (at 0.76 -0.25) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 0baa1d51-a8bc-4483-b400-80a9ff172160)) + (pad "10" smd rect (at 0.76 -0.75) (size 0.4 0.35) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 09311f64-fad0-424e-8eae-c2a2bd2cac0a)) + (pad "11" smd rect (at 0.25 -0.76) (size 0.35 0.4) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp 41f01f34-006e-48b6-a52b-6948fb66b57f)) + (pad "12" smd rect (at -0.25 -0.76) (size 0.35 0.4) (layers "F.Cu" "F.Paste" "F.Mask") + (solder_mask_margin 0.0635) (tstamp f87a7419-f9cb-4939-a776-f1a6ae037a85)) +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/_0603MP.kicad_mod b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/_0603MP.kicad_mod new file mode 100644 index 00000000..4954bc16 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty/_0603MP.kicad_mod @@ -0,0 +1,38 @@ +(footprint "_0603MP" (version 20211014) (generator pcbnew) + (layer "F.Cu") + (tedit 0) + (descr "0603 MicroPitch") + (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 08ea7653-fcf2-4de6-bc2d-71c2559866c5) + ) + (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 c6f30152-8d59-4f78-bba8-2d4dbdc2be46) + ) + (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 e4d4e5f7-6687-4207-9525-f44fa6947d43)) + (fp_line (start 0 -0.254) (end 0 0.254) (layer "F.SilkS") (width 0.2032) (tstamp 8494f3d6-e422-4ed3-afab-572a517aba7f)) + (fp_line (start -0.432 0.306) (end 0.432 0.306) (layer "F.Fab") (width 0.1016) (tstamp 3a69b14b-04ad-4165-ab2f-4ad1c270b812)) + (fp_line (start 0.432 -0.306) (end -0.432 -0.306) (layer "F.Fab") (width 0.1016) (tstamp 590cef58-c4cf-4e7a-ac89-6a7a7801e6c8)) + (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 2630aa28-dcfc-4f76-bf4f-eac1115a0083)) + (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 6d4a5dc7-5dd7-4742-b5e4-d512d0913c9b)) + (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 5ce1ec75-6b24-4360-8dcb-9033548b2be2)) + (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 77d09e3e-6f43-44cb-8866-ea235200f8dc)) +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00.zip b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00.zip new file mode 100644 index 00000000..76f29cb1 Binary files /dev/null and b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/OSO-SWAB-B1-00.zip differ diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/empty.kicad_wks b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/empty.kicad_wks new file mode 100644 index 00000000..f728a623 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/empty.kicad_wks @@ -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)) +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/fp-lib-table b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/fp-lib-table new file mode 100644 index 00000000..30c232a7 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/fp-lib-table @@ -0,0 +1,3 @@ +(fp_lib_table + (lib (name "OSO-MISC-21-021 Sensor Watch Motion II")(type "KiCad")(uri "$(KIPRJMOD)/OSO-SWAB-B1-00 Sensor Watch Accelerometer.pretty")(options "")(descr "")) +) diff --git a/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/sym-lib-table b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/sym-lib-table new file mode 100644 index 00000000..31b072f6 --- /dev/null +++ b/PCB/Sensor Boards/Kicad/OSO-SWAB-B1-00 Sensor Watch Accelerometer/sym-lib-table @@ -0,0 +1,3 @@ +(sym_lib_table + (lib (name "OSO-MISC-21-021 Sensor Watch Motion II-eagle-import")(type "KiCad")(uri "${KIPRJMOD}/OSO-MISC-21-021 Sensor Watch Motion II-eagle-import.kicad_sym")(options "")(descr "")) +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/.gitignore b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/.gitignore new file mode 100644 index 00000000..88bb66f9 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/.gitignore @@ -0,0 +1,2 @@ +OPT3001DNPT/* + diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001-cache.lib b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001-cache.lib new file mode 100644 index 00000000..90c56805 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001-cache.lib @@ -0,0 +1,162 @@ +EESchema-LIBRARY Version 2.4 +#encoding utf-8 +# +# OPT3001DNPT_OPT3001DNPT +# +DEF OPT3001DNPT_OPT3001DNPT U 0 40 Y Y 1 L N +F0 "U" -400 550 50 H V L BNN +F1 "OPT3001DNPT_OPT3001DNPT" -400 -450 50 H V L BNN +F2 "SON65P200X200X65-7N" 0 0 50 H I L BNN +F3 "" 0 0 50 H I L BNN +F4 "0.65" 0 0 50 H I L BNN "ENOM" +F5 "1.9" 0 0 50 H I L BNN "E_MIN" +F6 "0.25" 0 0 50 H I L BNN "L_MIN" +F7 "2.0" 0 0 50 H I L BNN "E_NOM" +F8 "0.65" 0 0 50 H I L BNN "A_MAX" +F9 "0.65" 0 0 50 H I L BNN "E2_NOM" +F10 "IPC 7351B" 0 0 50 H I L BNN "STANDARD" +F11 "01/2018" 0 0 50 H I L BNN "PARTREV" +F12 "0.25" 0 0 50 H I L BNN "B_NOM" +F13 "0.3" 0 0 50 H I L BNN "B_MAX" +F14 "0.2" 0 0 50 H I L BNN "B_MIN" +F15 "6.0" 0 0 50 H I L BNN "PIN_COUNT" +F16 "2.1" 0 0 50 H I L BNN "E_MAX" +F17 "0.35" 0 0 50 H I L BNN "L_MAX" +F18 "Texas Instruments" 0 0 50 H I L BNN "MANUFACTURER" +F19 "1.35" 0 0 50 H I L BNN "D2_NOM" +F20 "0.3" 0 0 50 H I L BNN "L_NOM" +F21 "2.1" 0 0 50 H I L BNN "D_MAX" +F22 "2.0" 0 0 50 H I L BNN "D_NOM" +F23 "1.9" 0 0 50 H I L BNN "D_MIN" +DRAW +S -400 -400 400 500 0 0 10 f +X VDD 1 600 400 200 L 40 40 0 0 W +X ADDR 2 -600 200 200 R 40 40 0 0 I +X GND 3 600 -300 200 L 40 40 0 0 W +X SCL 4 -600 0 200 R 40 40 0 0 I C +X INT 5 600 200 200 L 40 40 0 0 O +X SDA 6 -600 -100 200 R 40 40 0 0 B +X EXP 7 600 -100 200 L 40 40 0 0 P +ENDDRAW +ENDDEF +# +# Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_A4L-LOC +# +DEF Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_A4L-LOC #FRAME 0 40 Y Y 1 L N +F0 "#FRAME" 0 0 50 H I C CNN +F1 "Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_A4L-LOC" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 8550 600 85 0 1 0 >DRAWING_NAME Normal 0 L B +T 0 8550 400 76 0 1 0 >LAST_DATE_TIME Normal 0 L B +T 0 8995 200 85 0 1 0 >SHEET Normal 0 L B +T 0 8550 800 85 0 1 0 "by joey castillo" Normal 0 L B +T 0 9300 200 85 0 1 0 "cc-by-sa 4.0" Normal 0 L B +T 0 7300 200 180 0 1 0 oddly_specific_objects Normal 0 L B +T 0 8540 195 85 0 1 0 Sheet: Normal 0 L B +P 2 1 0 0 7250 150 7250 950 N +P 2 1 0 0 7250 950 8475 950 N +P 2 1 0 0 8475 350 8475 150 N +P 2 1 0 0 8475 350 8475 550 N +P 2 1 0 0 8475 550 8475 750 N +P 2 1 0 0 8475 550 10100 550 N +P 2 1 0 0 8475 750 8475 950 N +P 2 1 0 0 8475 750 10100 750 N +P 2 1 0 0 8475 950 10100 950 N +P 2 1 0 0 9250 150 9250 350 N +P 2 1 0 0 9250 350 8475 350 N +P 2 1 0 0 9250 350 10100 350 N +P 2 1 0 0 10100 150 10100 350 N +P 2 1 0 0 10100 350 10100 550 N +P 2 1 0 0 10100 550 10100 750 N +P 2 1 0 0 10100 750 10100 950 N +ENDDRAW +ENDDEF +# +# Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_FH19C-9S-0.5SH_10-FFC +# +DEF Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_FH19C-9S-0.5SH_10-FFC ~ 0 40 Y Y 1 L N +F0 "" 350 700 59 H V L CNN +F1 "Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_FH19C-9S-0.5SH_10-FFC" 350 600 59 H V L CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -200 500 -200 -500 N +P 2 1 0 0 -200 500 300 500 N +P 2 1 0 0 300 -500 -200 -500 N +P 2 1 0 0 300 -500 300 500 N +X 1 1 500 400 200 L 50 50 1 0 B +X 2 2 500 300 200 L 50 50 1 0 B +X 3 3 500 200 200 L 50 50 1 0 B +X 4 4 500 100 200 L 50 50 1 0 B +X 5 5 500 0 200 L 50 50 1 0 B +X 6 6 500 -100 200 L 50 50 1 0 B +X 7 7 500 -200 200 L 50 50 1 0 B +X 8 8 500 -300 200 L 50 50 1 0 B +X 9 9 500 -400 200 L 50 50 1 0 B +ENDDRAW +ENDDEF +# +# Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_GND +# +DEF Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_GND #GND 0 40 Y Y 1 L P +F0 "#GND" 0 0 50 H I C CNN +F1 "Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_GND" -100 -100 59 H V L BNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -75 0 75 0 N +X GND 1 0 100 100 D 0 0 1 0 W +ENDDRAW +ENDDEF +# +# Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_RESISTOR_0603MP +# +DEF Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_RESISTOR_0603MP R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_RESISTOR_0603MP" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_TPB1,27 +# +DEF Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_TPB1,27 TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_TPB1,27" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_VCC +# +DEF Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_VCC #P+ 0 40 Y Y 1 L P +F0 "#P+" 0 0 50 H I C CNN +F1 "Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import_VCC" -100 -100 59 V V L BNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 0 0 -50 -75 N +P 2 1 0 0 50 -75 0 0 N +X VCC 1 0 -100 100 U 0 0 1 0 W +ENDDRAW +ENDDEF +# +#End Library diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.kicad_pcb b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.kicad_pcb new file mode 100644 index 00000000..e13c73a5 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.kicad_pcb @@ -0,0 +1,497 @@ +(kicad_pcb (version 20171130) (host pcbnew 5.1.9+dfsg1-1+deb11u1) + + (general + (thickness 1.6) + (drawings 22) + (tracks 90) + (zones 0) + (modules 10) + (nets 12) + ) + + (page A4) + (layers + (0 Top signal) + (31 Bottom signal) + (32 B.Adhes user hide) + (33 F.Adhes user hide) + (34 B.Paste user hide) + (35 F.Paste user hide) + (36 B.SilkS user hide) + (37 F.SilkS user) + (38 B.Mask user hide) + (39 F.Mask user hide) + (40 Dwgs.User user hide) + (41 Cmts.User user hide) + (42 Eco1.User user hide) + (43 Eco2.User user) + (44 Edge.Cuts user) + (45 Margin user hide) + (46 B.CrtYd user hide) + (47 F.CrtYd user hide) + (48 B.Fab user hide) + (49 F.Fab user hide) + ) + + (setup + (last_trace_width 0.25) + (trace_clearance 0.1524) + (zone_clearance 0.508) + (zone_45_only no) + (trace_min 0.2) + (via_size 0.8) + (via_drill 0.4) + (via_min_size 0.1) + (via_min_drill 0.254) + (uvia_size 0.3) + (uvia_drill 0.1) + (uvias_allowed no) + (uvia_min_size 0.2) + (uvia_min_drill 0.1) + (edge_width 0.05) + (segment_width 0.2) + (pcb_text_width 0.3) + (pcb_text_size 1.5 1.5) + (mod_edge_width 0.12) + (mod_text_size 1 1) + (mod_text_width 0.15) + (pad_size 1.5 0.27) + (pad_drill 0) + (pad_to_mask_clearance 0) + (aux_axis_origin 0 0) + (visible_elements FFFFFF7F) + (pcbplotparams + (layerselection 0x010fc_ffffffff) + (usegerberextensions false) + (usegerberattributes true) + (usegerberadvancedattributes true) + (creategerberjobfile true) + (excludeedgelayer true) + (linewidth 0.100000) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (padsonsilk false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "")) + ) + + (net 0 "") + (net 1 GND) + (net 2 VCC) + (net 3 /A0_TEMP_ENABLE) + (net 4 /SCL) + (net 5 /SDA) + (net 6 /A1_SERCOM3.3_TC3.1) + (net 7 /A2_TEMP_SENSE) + (net 8 /NC) + (net 9 /A4_SERCOM3.2_TC3.0) + (net 10 "Net-(U1-Pad7)") + (net 11 "Net-(U1-Pad5)") + + (net_class Default "This is the default net class." + (clearance 0.1524) + (trace_width 0.25) + (via_dia 0.8) + (via_drill 0.4) + (uvia_dia 0.3) + (uvia_drill 0.1) + (add_net /A0_TEMP_ENABLE) + (add_net /A1_SERCOM3.3_TC3.1) + (add_net /A2_TEMP_SENSE) + (add_net /A4_SERCOM3.2_TC3.0) + (add_net /NC) + (add_net /SCL) + (add_net /SDA) + (add_net GND) + (add_net "Net-(U1-Pad5)") + (add_net "Net-(U1-Pad7)") + (add_net VCC) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:FH19C9S05SH10-FFC" (layer Top) (tedit 0) (tstamp 63E6D203) + (at 153.2255 106.5556) + (descr "FH19C-9S-0.5SH(10)-1
\n") + (path /54307519) + (fp_text reference U$3 (at 0 0) (layer F.SilkS) hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + ) + (fp_text value FH19C-9S-0.5SH_10-FFC (at 0 0) (layer F.SilkS) hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + ) + (fp_poly (pts (xy -2.4902 0.9742) (xy 2.4882 0.9742) (xy 2.4892 3.4798) (xy -2.4892 3.4798)) (layer B.Mask) (width 0)) + (fp_line (start 2.4892 0) (end 2.4892 3.35) (layer Edge.Cuts) (width 0.05)) + (fp_line (start -2.3392 3.5) (end 2.3392 3.5) (layer Edge.Cuts) (width 0.05)) + (fp_line (start -2.4892 0) (end -2.4892 3.35) (layer Edge.Cuts) (width 0.05)) + (fp_arc (start -2.3392 3.35) (end -2.3392 3.5) (angle 90) (layer Edge.Cuts) (width 0.05)) + (fp_arc (start 2.3392 3.35) (end 2.3392 3.5) (angle -90) (layer Edge.Cuts) (width 0.05)) + (pad 1 smd rect (at 2 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 2 VCC) (solder_mask_margin 0.0635)) + (pad 2 smd rect (at 1.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 1 GND) (solder_mask_margin 0.0635)) + (pad 3 smd rect (at 1 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 9 /A4_SERCOM3.2_TC3.0) (solder_mask_margin 0.0635)) + (pad 4 smd rect (at 0.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 8 /NC) (solder_mask_margin 0.0635)) + (pad 5 smd rect (at 0 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 7 /A2_TEMP_SENSE) (solder_mask_margin 0.0635)) + (pad 6 smd rect (at -0.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 6 /A1_SERCOM3.3_TC3.1) (solder_mask_margin 0.0635)) + (pad 7 smd rect (at -1 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 5 /SDA) (solder_mask_margin 0.0635)) + (pad 8 smd rect (at -1.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 4 /SCL) (solder_mask_margin 0.0635)) + (pad 9 smd rect (at -2 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 3 /A0_TEMP_ENABLE) (solder_mask_margin 0.0635)) + ) + + (module OPT3001DNPT:SON65P200X200X65-7N (layer Top) (tedit 63E6D415) (tstamp 63E73FD8) + (at 142.748 102.87 270) + (path /63E70E51) + (attr smd) + (fp_text reference U1 (at 0.54 -2.008 90) (layer F.SilkS) hide + (effects (font (size 0.8 0.8) (thickness 0.15))) + ) + (fp_text value OPT3001DNPT (at 7.652 2.008 90) (layer F.Fab) hide + (effects (font (size 0.8 0.8) (thickness 0.15))) + ) + (fp_line (start 1.615 -1.25) (end 1.615 1.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.615 -1.25) (end -1.615 1.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.615 1.25) (end 1.615 1.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.615 -1.25) (end 1.615 -1.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1 -1) (end 1 1) (layer F.Fab) (width 0.127)) + (fp_line (start -1 -1) (end -1 1) (layer F.Fab) (width 0.127)) + (fp_line (start -1 1.099) (end 1 1.099) (layer F.SilkS) (width 0.127)) + (fp_line (start -1 -1.099) (end 1 -1.099) (layer F.SilkS) (width 0.127)) + (fp_line (start -1 1) (end 1 1) (layer F.Fab) (width 0.127)) + (fp_line (start -1 -1) (end 1 -1) (layer F.Fab) (width 0.127)) + (fp_circle (center -1.935 -0.65) (end -1.835 -0.65) (layer F.Fab) (width 0.2)) + (fp_circle (center -1.935 -0.65) (end -1.835 -0.65) (layer F.SilkS) (width 0.2)) + (fp_poly (pts (xy -0.21 -0.43) (xy 0.21 -0.43) (xy 0.21 0.43) (xy -0.21 0.43)) (layer F.Paste) (width 0.01)) + (pad 1 smd roundrect (at -1.37 -0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 2 VCC)) + (pad 2 smd roundrect (at -1.37 0 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 1 GND)) + (pad 3 smd roundrect (at -1.37 0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 1 GND)) + (pad 4 smd roundrect (at 1.37 0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 4 /SCL)) + (pad 5 smd roundrect (at 1.37 0 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 11 "Net-(U1-Pad5)")) + (pad 6 smd roundrect (at 1.37 -0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 5 /SDA)) + (pad 7 smd rect (at 0 0 270) (size 0.65 1.35) (layers Top F.Mask) + (net 10 "Net-(U1-Pad7)")) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" (layer Top) (tedit 0) (tstamp 63E759D2) + (at 146.2659 104.7522 270) + (descr "0603 MicroPitch") + (path /05CBC8DB) + (fp_text reference R1 (at -0.0635 1.7145 90) (layer F.SilkS) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_text value "1% 10K" (at -0.9525 0.9525 90) (layer F.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_line (start -0.432 0.306) (end 0.432 0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start 0.432 -0.306) (end -0.432 -0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start 0 -0.254) (end 0 0.254) (layer F.SilkS) (width 0.2032)) + (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)) + (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)) + (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)) + (pad 2 smd rect (at 0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 3 /A0_TEMP_ENABLE) (solder_mask_margin 0.0635)) + (pad 1 smd rect (at -0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 7 /A2_TEMP_SENSE) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" (layer Top) (tedit 0) (tstamp 63E759F3) + (at 146.2659 102.1868 270) + (descr "0603 MicroPitch") + (path /6C7771A6) + (fp_text reference RT1 (at -0.127 1.778 90) (layer F.SilkS) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_text value "NTC 10K" (at -1.27 1.4923 90) (layer F.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_line (start -0.432 0.306) (end 0.432 0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start 0.432 -0.306) (end -0.432 -0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start 0 -0.254) (end 0 0.254) (layer F.SilkS) (width 0.2032)) + (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)) + (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)) + (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)) + (pad 2 smd rect (at 0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 7 /A2_TEMP_SENSE) (solder_mask_margin 0.0635)) + (pad 1 smd rect (at -0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 2 VCC) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D22B) + (at 146.1135 102.8472 180) + (descr "TEST PAD") + (path /8E097FD0) + (fp_text reference GND1 (at -1.778 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 1 GND) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D232) + (at 144.0815 101.2216 180) + (descr "TEST PAD") + (path /E65641C5) + (fp_text reference A4 (at 1.524 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 9 /A4_SERCOM3.2_TC3.0) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D239) + (at 146.1135 101.2216 180) + (descr "TEST PAD") + (path /D0DD1D8E) + (fp_text reference VCC1 (at -1.778 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 2 VCC) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D240) + (at 146.1135 104.4728 180) + (descr "TEST PAD") + (path /252148C1) + (fp_text reference SCL1 (at -1.778 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 4 /SCL) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D247) + (at 144.0815 104.4728 180) + (descr "TEST PAD") + (path /943CED1C) + (fp_text reference SDA1 (at 1.778 -0.0127) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 5 /SDA) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D24E) + (at 144.0815 102.8472 180) + (descr "TEST PAD") + (path /E1B0505C) + (fp_text reference A1 (at 1.524 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 6 /A1_SERCOM3.3_TC3.1) (solder_mask_margin 0.0635)) + ) + + (gr_arc (start 150.4823 106.5556) (end 150.7363 106.5556) (angle -90) (layer Edge.Cuts) (width 0.05) (tstamp 803D32C0)) + (gr_line (start 150.4823 106.3016) (end 145.7325 106.3016) (layer Edge.Cuts) (width 0.05) (tstamp 803D3820)) + (gr_line (start 145.0975 105.6666) (end 142.1765 105.6666) (layer Edge.Cuts) (width 0.05) (tstamp 803D3C70)) + (gr_arc (start 142.1765 104.7776) (end 142.1765 105.6666) (angle 90) (layer Edge.Cuts) (width 0.05) (tstamp 63E7417A)) + (gr_line (start 141.2875 104.7776) (end 141.2875 100.8406) (layer Edge.Cuts) (width 0.05) (tstamp 63E75941)) + (gr_arc (start 142.1765 100.8406) (end 141.2875 100.8406) (angle 90) (layer Edge.Cuts) (width 0.05) (tstamp 63E74180)) + (gr_line (start 142.1765 99.9516) (end 155.3337 99.9516) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9B000)) + (gr_arc (start 155.3337 100.3326) (end 155.3337 99.9516) (angle 90) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9B410)) + (gr_line (start 155.7147 100.3326) (end 155.7147 106.5556) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9B950)) + (gr_arc (start 145.0975 106.3016) (end 145.7325 106.3016) (angle -90) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9BE00)) + (gr_text "OPT3001 I2C\nSensor Board" (at 151.4475 100.2056) (layer F.SilkS) (tstamp 7FC58850) + (effects (font (size 0.57912 0.57912) (thickness 0.109728)) (justify top)) + ) + (gr_line (start 155.7147 105.2856) (end 147.5105 105.2856) (layer F.SilkS) (width 0.127) (tstamp 7FC58F50)) + (gr_line (start 147.0025 100.7136) (end 147.0025 104.7776) (layer F.SilkS) (width 0.127) (tstamp 7FA4B140)) + (gr_arc (start 147.5105 104.7776) (end 147.0025 104.7776) (angle -90) (layer F.SilkS) (width 0.127) (tstamp 7FA4B6B0)) + (gr_arc (start 146.2405 100.7136) (end 147.0025 100.7136) (angle -90) (layer F.SilkS) (width 0.127) (tstamp 7FA4BCC0)) + (gr_text "A0: Thermistor !EN\nA2: Temp. Sense\nA1/A4/SDA/SCL:\nTest Points" (at 151.4475 102.1106) (layer F.SilkS) (tstamp 7FA08AA0) + (effects (font (size 0.4826 0.4826) (thickness 0.06096)) (justify top)) + ) + (gr_text "Digital IO\nAnalog input\nPWM on TC3\nUART RX/TX\nInterrupt 1/0\nA4 ONLY: Ext. wake 0" (at 155.5115 101.2216) (layer B.SilkS) (tstamp 7FA09230) + (effects (font (size 0.4826 0.4826) (thickness 0.06096)) (justify left top mirror)) + ) + (gr_text "A1/A4 Uses" (at 155.5115 100.2056) (layer B.SilkS) (tstamp 7F9A10A0) + (effects (font (size 0.57912 0.57912) (thickness 0.109728)) (justify left top mirror)) + ) + (gr_text "" (at 142.9385 104.1172) (layer F.SilkS) (tstamp 7F9A17A0) + (effects (font (size 0.57912 0.57912) (thickness 0.073152)) (justify left)) + ) + (gr_text "" (at 142.9385 101.5518) (layer F.SilkS) (tstamp 7F9A1E50) + (effects (font (size 0.57912 0.57912) (thickness 0.073152)) (justify left)) + ) + (dimension 3 (width 0.12) (layer F.SilkS) + (gr_text "3.000 mm" (at 160.9575 108.5016 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (feature1 (pts (xy 156.0875 107.0016) (xy 160.273921 107.0016))) + (feature2 (pts (xy 156.0875 110.0016) (xy 160.273921 110.0016))) + (crossbar (pts (xy 159.6875 110.0016) (xy 159.6875 107.0016))) + (arrow1a (pts (xy 159.6875 107.0016) (xy 160.273921 108.128104))) + (arrow1b (pts (xy 159.6875 107.0016) (xy 159.101079 108.128104))) + (arrow2a (pts (xy 159.6875 110.0016) (xy 160.273921 108.875096))) + (arrow2b (pts (xy 159.6875 110.0016) (xy 159.101079 108.875096))) + ) + (gr_text "Stiffener only\nin this area" (at 159.5755 108.5876) (layer F.SilkS) (tstamp 7F95BC90) + (effects (font (size 0.57912 0.57912) (thickness 0.109728))) + ) + + (segment (start 148.082 100.457) (end 148.137 100.457) (width 0.25) (layer Bottom) (net 0)) + (segment (start 142.098 101.5) (end 142.748 101.5) (width 0.25) (layer Top) (net 1)) + (via (at 142.494 100.529) (size 0.8) (drill 0.4) (layers Top Bottom) (net 1)) + (segment (start 142.748 100.783) (end 142.494 100.529) (width 0.25) (layer Top) (net 1)) + (segment (start 142.748 101.5) (end 142.748 100.783) (width 0.25) (layer Top) (net 1)) + (segment (start 142.494 100.529) (end 142.76899 100.25401) (width 0.25) (layer Bottom) (net 1)) + (segment (start 145.201089 100.256533) (end 145.201089 101.934789) (width 0.25) (layer Bottom) (net 1)) + (segment (start 142.76899 100.25401) (end 145.198566 100.25401) (width 0.25) (layer Bottom) (net 1)) + (segment (start 145.198566 100.25401) (end 145.201089 100.256533) (width 0.25) (layer Bottom) (net 1)) + (segment (start 145.201089 101.934789) (end 146.1135 102.8472) (width 0.25) (layer Bottom) (net 1)) + (segment (start 147.022102 101.938598) (end 146.1135 102.8472) (width 0.25) (layer Bottom) (net 1)) + (segment (start 154.7255 104.319944) (end 152.344154 101.938598) (width 0.25) (layer Bottom) (net 1)) + (segment (start 152.344154 101.938598) (end 147.022102 101.938598) (width 0.25) (layer Bottom) (net 1)) + (segment (start 154.7255 108.8056) (end 154.7255 104.319944) (width 0.25) (layer Bottom) (net 1)) + (via (at 146.939 101.219) (size 0.8) (drill 0.4) (layers Top Bottom) (net 2)) + (segment (start 152.129838 100.901187) (end 147.822498 100.901187) (width 0.25) (layer Bottom) (net 2)) + (segment (start 146.1161 101.219) (end 146.1135 101.2216) (width 0.25) (layer Bottom) (net 2)) + (segment (start 147.822498 100.901187) (end 147.504685 101.219) (width 0.25) (layer Bottom) (net 2)) + (segment (start 155.2255 103.996849) (end 152.129838 100.901187) (width 0.25) (layer Bottom) (net 2)) + (segment (start 146.939 101.219) (end 146.1161 101.219) (width 0.25) (layer Bottom) (net 2)) + (segment (start 155.2255 108.8056) (end 155.2255 103.996849) (width 0.25) (layer Bottom) (net 2)) + (segment (start 147.504685 101.219) (end 146.939 101.219) (width 0.25) (layer Bottom) (net 2)) + (segment (start 143.398 101.5) (end 143.573651 101.675651) (width 0.25) (layer Top) (net 2)) + (segment (start 143.573651 101.675651) (end 146.142049 101.675651) (width 0.25) (layer Top) (net 2)) + (segment (start 146.142049 101.675651) (end 146.3929 101.4248) (width 0.25) (layer Top) (net 2)) + (segment (start 146.3929 101.4248) (end 146.7332 101.4248) (width 0.25) (layer Top) (net 2)) + (segment (start 146.7332 101.4248) (end 146.939 101.219) (width 0.25) (layer Top) (net 2)) + (via (at 147.828 105.664) (size 0.8) (drill 0.4) (layers Top Bottom) (net 3)) + (segment (start 147.6782 105.5142) (end 147.828 105.664) (width 0.25) (layer Top) (net 3)) + (segment (start 146.3929 105.5142) (end 147.6782 105.5142) (width 0.25) (layer Top) (net 3)) + (segment (start 151.2255 106.512573) (end 151.2255 108.8056) (width 0.25) (layer Bottom) (net 3)) + (segment (start 150.712117 105.99919) (end 151.2255 106.512573) (width 0.25) (layer Bottom) (net 3)) + (segment (start 148.16319 105.99919) (end 150.712117 105.99919) (width 0.25) (layer Bottom) (net 3)) + (segment (start 147.828 105.664) (end 148.16319 105.99919) (width 0.25) (layer Bottom) (net 3)) + (segment (start 142.37541 105.26741) (end 145.075078 105.26741) (width 0.25) (layer Top) (net 4)) + (via (at 145.243931 105.098557) (size 0.8) (drill 0.4) (layers Top Bottom) (net 4)) + (segment (start 142.098 104.99) (end 142.37541 105.26741) (width 0.25) (layer Top) (net 4)) + (segment (start 142.098 104.24) (end 142.098 104.99) (width 0.25) (layer Top) (net 4)) + (segment (start 145.075078 105.26741) (end 145.243931 105.098557) (width 0.25) (layer Top) (net 4)) + (segment (start 145.487743 105.098557) (end 146.1135 104.4728) (width 0.25) (layer Bottom) (net 4)) + (segment (start 145.243931 105.098557) (end 145.487743 105.098557) (width 0.25) (layer Bottom) (net 4)) + (segment (start 150.674396 105.392376) (end 151.7255 106.44348) (width 0.25) (layer Bottom) (net 4)) + (segment (start 150.421816 105.392376) (end 150.674396 105.392376) (width 0.25) (layer Bottom) (net 4)) + (segment (start 146.1135 104.4728) (end 149.50224 104.4728) (width 0.25) (layer Bottom) (net 4)) + (segment (start 151.7255 106.44348) (end 151.7255 108.8056) (width 0.25) (layer Bottom) (net 4)) + (segment (start 149.50224 104.4728) (end 150.421816 105.392376) (width 0.25) (layer Bottom) (net 4)) + (segment (start 143.398 104.24) (end 145.007 104.24) (width 0.25) (layer Top) (net 5)) + (segment (start 145.007 104.24) (end 145.381654 104.24) (width 0.25) (layer Top) (net 5)) + (segment (start 152.2255 108.8056) (end 152.2255 106.193504) (width 0.25) (layer Bottom) (net 5)) + (segment (start 145.381654 104.24) (end 145.856628 104.714974) (width 0.25) (layer Top) (net 5)) + (segment (start 145.856628 104.714974) (end 150.74697 104.714974) (width 0.25) (layer Top) (net 5)) + (via (at 150.74697 104.714974) (size 0.8) (drill 0.4) (layers Top Bottom) (net 5)) + (segment (start 152.2255 106.193504) (end 150.74697 104.714974) (width 0.25) (layer Bottom) (net 5)) + (via (at 145.034 103.886) (size 0.8) (drill 0.4) (layers Top Bottom) (net 5)) + (segment (start 145.034 103.886) (end 145.007 103.913) (width 0.25) (layer Top) (net 5)) + (segment (start 144.4472 104.4728) (end 145.034 103.886) (width 0.25) (layer Bottom) (net 5)) + (segment (start 144.0815 104.4728) (end 144.4472 104.4728) (width 0.25) (layer Bottom) (net 5)) + (segment (start 145.007 103.913) (end 145.007 104.24) (width 0.25) (layer Top) (net 5)) + (via (at 148.336 103.52461) (size 0.8) (drill 0.4) (layers Top Bottom) (net 6)) + (segment (start 152.7255 106.045058) (end 151.490164 104.809722) (width 0.25) (layer Bottom) (net 6)) + (segment (start 151.490164 104.35972) (end 150.655054 103.52461) (width 0.25) (layer Bottom) (net 6)) + (segment (start 152.7255 108.8056) (end 152.7255 106.045058) (width 0.25) (layer Bottom) (net 6)) + (segment (start 151.490164 104.809722) (end 151.490164 104.35972) (width 0.25) (layer Bottom) (net 6)) + (segment (start 150.655054 103.52461) (end 148.336 103.52461) (width 0.25) (layer Bottom) (net 6)) + (via (at 144.899309 102.94316) (size 0.8) (drill 0.4) (layers Top Bottom) (net 6)) + (segment (start 144.803349 102.8472) (end 144.899309 102.94316) (width 0.25) (layer Bottom) (net 6)) + (segment (start 144.0815 102.8472) (end 144.803349 102.8472) (width 0.25) (layer Bottom) (net 6)) + (segment (start 144.899309 102.94316) (end 145.57107 102.271399) (width 0.25) (layer Top) (net 6)) + (segment (start 145.57107 102.271399) (end 147.082789 102.271399) (width 0.25) (layer Top) (net 6)) + (segment (start 147.082789 102.271399) (end 148.336 103.52461) (width 0.25) (layer Top) (net 6)) + (segment (start 146.2659 103.9902) (end 146.2659 102.9488) (width 0.254) (layer Top) (net 7) (tstamp 63E759C5)) + (segment (start 153.2255 105.415504) (end 152.231065 104.421069) (width 0.25) (layer Bottom) (net 7)) + (segment (start 148.842094 104.02107) (end 151.831066 104.02107) (width 0.25) (layer Top) (net 7)) + (via (at 152.231065 104.421069) (size 0.8) (drill 0.4) (layers Top Bottom) (net 7)) + (segment (start 148.661153 104.202011) (end 148.842094 104.02107) (width 0.25) (layer Top) (net 7)) + (segment (start 146.3929 103.9902) (end 146.604711 104.202011) (width 0.25) (layer Top) (net 7)) + (segment (start 146.604711 104.202011) (end 148.661153 104.202011) (width 0.25) (layer Top) (net 7)) + (segment (start 151.831066 104.02107) (end 152.231065 104.421069) (width 0.25) (layer Top) (net 7)) + (segment (start 153.2255 108.8056) (end 153.2255 105.415504) (width 0.25) (layer Bottom) (net 7)) + (via (at 152.019 102.616) (size 0.8) (drill 0.4) (layers Top Bottom) (net 9)) + (segment (start 154.2255 104.8225) (end 152.019 102.616) (width 0.25) (layer Bottom) (net 9)) + (segment (start 154.2255 108.8056) (end 154.2255 104.8225) (width 0.25) (layer Bottom) (net 9)) + (segment (start 149.733 100.33) (end 147.574 100.33) (width 0.25) (layer Top) (net 9)) + (segment (start 152.019 102.616) (end 149.733 100.33) (width 0.25) (layer Top) (net 9)) + (segment (start 147.574 100.33) (end 147.955 100.33) (width 0.25) (layer Top) (net 9)) + (via (at 144.523679 100.981868) (size 0.8) (drill 0.4) (layers Top Bottom) (net 9)) + (segment (start 144.0815 101.2216) (end 144.283947 101.2216) (width 0.25) (layer Bottom) (net 9)) + (segment (start 144.283947 101.2216) (end 144.523679 100.981868) (width 0.25) (layer Bottom) (net 9)) + (segment (start 144.523679 100.981868) (end 145.175547 100.33) (width 0.25) (layer Top) (net 9)) + (segment (start 145.175547 100.33) (end 147.574 100.33) (width 0.25) (layer Top) (net 9)) + +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.kicad_pcb-bak b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.kicad_pcb-bak new file mode 100644 index 00000000..bff4000c --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.kicad_pcb-bak @@ -0,0 +1,497 @@ +(kicad_pcb (version 20171130) (host pcbnew 5.1.9+dfsg1-1+deb11u1) + + (general + (thickness 1.6) + (drawings 22) + (tracks 90) + (zones 0) + (modules 10) + (nets 12) + ) + + (page A4) + (layers + (0 Top signal) + (31 Bottom signal) + (32 B.Adhes user hide) + (33 F.Adhes user hide) + (34 B.Paste user hide) + (35 F.Paste user hide) + (36 B.SilkS user hide) + (37 F.SilkS user) + (38 B.Mask user hide) + (39 F.Mask user hide) + (40 Dwgs.User user hide) + (41 Cmts.User user hide) + (42 Eco1.User user hide) + (43 Eco2.User user) + (44 Edge.Cuts user) + (45 Margin user hide) + (46 B.CrtYd user hide) + (47 F.CrtYd user hide) + (48 B.Fab user hide) + (49 F.Fab user hide) + ) + + (setup + (last_trace_width 0.25) + (trace_clearance 0.1524) + (zone_clearance 0.508) + (zone_45_only no) + (trace_min 0.2) + (via_size 0.8) + (via_drill 0.4) + (via_min_size 0.1) + (via_min_drill 0.254) + (uvia_size 0.3) + (uvia_drill 0.1) + (uvias_allowed no) + (uvia_min_size 0.2) + (uvia_min_drill 0.1) + (edge_width 0.05) + (segment_width 0.2) + (pcb_text_width 0.3) + (pcb_text_size 1.5 1.5) + (mod_edge_width 0.12) + (mod_text_size 1 1) + (mod_text_width 0.15) + (pad_size 1.5 0.27) + (pad_drill 0) + (pad_to_mask_clearance 0) + (aux_axis_origin 0 0) + (visible_elements FFFFFF7F) + (pcbplotparams + (layerselection 0x010fc_ffffffff) + (usegerberextensions false) + (usegerberattributes true) + (usegerberadvancedattributes true) + (creategerberjobfile true) + (excludeedgelayer true) + (linewidth 0.100000) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (padsonsilk false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "")) + ) + + (net 0 "") + (net 1 GND) + (net 2 VCC) + (net 3 /A0_TEMP_ENABLE) + (net 4 /SCL) + (net 5 /SDA) + (net 6 /A1_SERCOM3.3_TC3.1) + (net 7 /A2_TEMP_SENSE) + (net 8 /NC) + (net 9 /A4_SERCOM3.2_TC3.0) + (net 10 "Net-(U1-Pad7)") + (net 11 "Net-(U1-Pad5)") + + (net_class Default "This is the default net class." + (clearance 0.1524) + (trace_width 0.25) + (via_dia 0.8) + (via_drill 0.4) + (uvia_dia 0.3) + (uvia_drill 0.1) + (add_net /A0_TEMP_ENABLE) + (add_net /A1_SERCOM3.3_TC3.1) + (add_net /A2_TEMP_SENSE) + (add_net /A4_SERCOM3.2_TC3.0) + (add_net /NC) + (add_net /SCL) + (add_net /SDA) + (add_net GND) + (add_net "Net-(U1-Pad5)") + (add_net "Net-(U1-Pad7)") + (add_net VCC) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:FH19C9S05SH10-FFC" (layer Top) (tedit 0) (tstamp 63E6D203) + (at 153.2255 106.5556) + (descr "FH19C-9S-0.5SH(10)-1
\n") + (path /54307519) + (fp_text reference U$3 (at 0 0) (layer F.SilkS) hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + ) + (fp_text value FH19C-9S-0.5SH_10-FFC (at 0 0) (layer F.SilkS) hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + ) + (fp_arc (start -2.3392 3.35) (end -2.3392 3.5) (angle 90) (layer Edge.Cuts) (width 0.05)) + (fp_arc (start 2.3392 3.35) (end 2.3392 3.5) (angle -90) (layer Edge.Cuts) (width 0.05)) + (fp_line (start -2.4892 0) (end -2.4892 3.35) (layer Edge.Cuts) (width 0.05)) + (fp_line (start -2.3392 3.5) (end 2.3392 3.5) (layer Edge.Cuts) (width 0.05)) + (fp_line (start 2.4892 0) (end 2.4892 3.35) (layer Edge.Cuts) (width 0.05)) + (fp_poly (pts (xy -2.4902 0.9742) (xy 2.4882 0.9742) (xy 2.4892 3.4798) (xy -2.4892 3.4798)) (layer B.Mask) (width 0)) + (pad 1 smd rect (at 2 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 2 VCC) (solder_mask_margin 0.0635)) + (pad 2 smd rect (at 1.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 1 GND) (solder_mask_margin 0.0635)) + (pad 3 smd rect (at 1 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 9 /A4_SERCOM3.2_TC3.0) (solder_mask_margin 0.0635)) + (pad 4 smd rect (at 0.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 8 /NC) (solder_mask_margin 0.0635)) + (pad 5 smd rect (at 0 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 7 /A2_TEMP_SENSE) (solder_mask_margin 0.0635)) + (pad 6 smd rect (at -0.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 6 /A1_SERCOM3.3_TC3.1) (solder_mask_margin 0.0635)) + (pad 7 smd rect (at -1 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 5 /SDA) (solder_mask_margin 0.0635)) + (pad 8 smd rect (at -1.5 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 4 /SCL) (solder_mask_margin 0.0635)) + (pad 9 smd rect (at -2 2.25 90) (size 2.5 0.347) (layers Bottom B.Mask) + (net 3 /A0_TEMP_ENABLE) (solder_mask_margin 0.0635)) + ) + + (module OPT3001DNPT:SON65P200X200X65-7N (layer Top) (tedit 63E6D415) (tstamp 63E73FD8) + (at 142.748 102.87 270) + (path /63E70E51) + (attr smd) + (fp_text reference U1 (at 0.54 -2.008 90) (layer F.SilkS) hide + (effects (font (size 0.8 0.8) (thickness 0.15))) + ) + (fp_text value OPT3001DNPT (at 7.652 2.008 90) (layer F.Fab) hide + (effects (font (size 0.8 0.8) (thickness 0.15))) + ) + (fp_poly (pts (xy -0.21 -0.43) (xy 0.21 -0.43) (xy 0.21 0.43) (xy -0.21 0.43)) (layer F.Paste) (width 0.01)) + (fp_circle (center -1.935 -0.65) (end -1.835 -0.65) (layer F.SilkS) (width 0.2)) + (fp_circle (center -1.935 -0.65) (end -1.835 -0.65) (layer F.Fab) (width 0.2)) + (fp_line (start -1 -1) (end 1 -1) (layer F.Fab) (width 0.127)) + (fp_line (start -1 1) (end 1 1) (layer F.Fab) (width 0.127)) + (fp_line (start -1 -1.099) (end 1 -1.099) (layer F.SilkS) (width 0.127)) + (fp_line (start -1 1.099) (end 1 1.099) (layer F.SilkS) (width 0.127)) + (fp_line (start -1 -1) (end -1 1) (layer F.Fab) (width 0.127)) + (fp_line (start 1 -1) (end 1 1) (layer F.Fab) (width 0.127)) + (fp_line (start -1.615 -1.25) (end 1.615 -1.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.615 1.25) (end 1.615 1.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.615 -1.25) (end -1.615 1.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.615 -1.25) (end 1.615 1.25) (layer F.CrtYd) (width 0.05)) + (pad 1 smd roundrect (at -1.37 -0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 2 VCC)) + (pad 2 smd roundrect (at -1.37 0 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 1 GND)) + (pad 3 smd roundrect (at -1.37 0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 1 GND)) + (pad 4 smd roundrect (at 1.37 0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 4 /SCL)) + (pad 5 smd roundrect (at 1.37 0 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 11 "Net-(U1-Pad5)")) + (pad 6 smd roundrect (at 1.37 -0.65 270) (size 1.5 0.27) (layers Top F.Paste F.Mask) (roundrect_rratio 0.03) + (net 5 /SDA)) + (pad 7 smd rect (at 0 0 270) (size 0.65 1.35) (layers Top F.Mask) + (net 10 "Net-(U1-Pad7)")) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" (layer Top) (tedit 0) (tstamp 63E759D2) + (at 146.2659 104.7522 270) + (descr "0603 MicroPitch") + (path /05CBC8DB) + (fp_text reference R1 (at -0.0635 1.7145 90) (layer F.SilkS) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_text value "1% 10K" (at -0.9525 0.9525 90) (layer F.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (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)) + (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)) + (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)) + (fp_line (start 0 -0.254) (end 0 0.254) (layer F.SilkS) (width 0.2032)) + (fp_line (start 0.432 -0.306) (end -0.432 -0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start -0.432 0.306) (end 0.432 0.306) (layer F.Fab) (width 0.1016)) + (pad 2 smd rect (at 0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 3 /A0_TEMP_ENABLE) (solder_mask_margin 0.0635)) + (pad 1 smd rect (at -0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 7 /A2_TEMP_SENSE) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" (layer Top) (tedit 0) (tstamp 63E759F3) + (at 146.2659 102.1868 270) + (descr "0603 MicroPitch") + (path /6C7771A6) + (fp_text reference RT1 (at -0.127 1.778 90) (layer F.SilkS) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_text value "NTC 10K" (at -1.27 1.4923 90) (layer F.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (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)) + (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)) + (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)) + (fp_line (start 0 -0.254) (end 0 0.254) (layer F.SilkS) (width 0.2032)) + (fp_line (start 0.432 -0.306) (end -0.432 -0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start -0.432 0.306) (end 0.432 0.306) (layer F.Fab) (width 0.1016)) + (pad 2 smd rect (at 0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 7 /A2_TEMP_SENSE) (solder_mask_margin 0.0635)) + (pad 1 smd rect (at -0.762 0 270) (size 0.8 0.8) (layers Top F.Paste F.Mask) + (net 2 VCC) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D22B) + (at 146.1135 102.8472 180) + (descr "TEST PAD") + (path /8E097FD0) + (fp_text reference GND1 (at -1.778 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 1 GND) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D232) + (at 144.0815 101.2216 180) + (descr "TEST PAD") + (path /E65641C5) + (fp_text reference A4 (at 1.524 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 9 /A4_SERCOM3.2_TC3.0) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D239) + (at 146.1135 101.2216 180) + (descr "TEST PAD") + (path /D0DD1D8E) + (fp_text reference VCC1 (at -1.778 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 2 VCC) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D240) + (at 146.1135 104.4728 180) + (descr "TEST PAD") + (path /252148C1) + (fp_text reference SCL1 (at -1.778 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 4 /SCL) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D247) + (at 144.0815 104.4728 180) + (descr "TEST PAD") + (path /943CED1C) + (fp_text reference SDA1 (at 1.778 -0.0127) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 5 /SDA) (solder_mask_margin 0.0635)) + ) + + (module "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" (layer Bottom) (tedit 0) (tstamp 63E6D24E) + (at 144.0815 102.8472 180) + (descr "TEST PAD") + (path /E1B0505C) + (fp_text reference A1 (at 1.524 0) (layer B.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify right bottom mirror)) + ) + (fp_text value TPB1,27 (at -0.635 -0.762) (layer B.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify right bottom mirror)) + ) + (fp_line (start 0 0.635) (end 0 -0.635) (layer Dwgs.User) (width 0.0024)) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 -1.905 180) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify right bottom)) + ) + (pad TP smd roundrect (at 0 0 180) (size 1.27 1.27) (layers Bottom B.Mask) (roundrect_rratio 0.5) + (net 6 /A1_SERCOM3.3_TC3.1) (solder_mask_margin 0.0635)) + ) + + (gr_arc (start 150.4823 106.5556) (end 150.7363 106.5556) (angle -90) (layer Edge.Cuts) (width 0.05) (tstamp 803D32C0)) + (gr_line (start 150.4823 106.3016) (end 145.7325 106.3016) (layer Edge.Cuts) (width 0.05) (tstamp 803D3820)) + (gr_line (start 145.0975 105.6666) (end 142.1765 105.6666) (layer Edge.Cuts) (width 0.05) (tstamp 803D3C70)) + (gr_arc (start 142.1765 104.7776) (end 142.1765 105.6666) (angle 90) (layer Edge.Cuts) (width 0.05) (tstamp 63E7417A)) + (gr_line (start 141.2875 104.7776) (end 141.2875 100.8406) (layer Edge.Cuts) (width 0.05) (tstamp 63E75941)) + (gr_arc (start 142.1765 100.8406) (end 141.2875 100.8406) (angle 90) (layer Edge.Cuts) (width 0.05) (tstamp 63E74180)) + (gr_line (start 142.1765 99.9516) (end 155.3337 99.9516) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9B000)) + (gr_arc (start 155.3337 100.3326) (end 155.3337 99.9516) (angle 90) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9B410)) + (gr_line (start 155.7147 100.3326) (end 155.7147 106.5556) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9B950)) + (gr_arc (start 145.0975 106.3016) (end 145.7325 106.3016) (angle -90) (layer Edge.Cuts) (width 0.05) (tstamp 7FB9BE00)) + (gr_text "OPT3001 I2C\nSensor Board" (at 151.4475 100.2056) (layer F.SilkS) (tstamp 7FC58850) + (effects (font (size 0.57912 0.57912) (thickness 0.109728)) (justify top)) + ) + (gr_line (start 155.7147 105.2856) (end 147.5105 105.2856) (layer F.SilkS) (width 0.127) (tstamp 7FC58F50)) + (gr_line (start 147.0025 100.7136) (end 147.0025 104.7776) (layer F.SilkS) (width 0.127) (tstamp 7FA4B140)) + (gr_arc (start 147.5105 104.7776) (end 147.0025 104.7776) (angle -90) (layer F.SilkS) (width 0.127) (tstamp 7FA4B6B0)) + (gr_arc (start 146.2405 100.7136) (end 147.0025 100.7136) (angle -90) (layer F.SilkS) (width 0.127) (tstamp 7FA4BCC0)) + (gr_text "A0: Thermistor !EN\nA2: Temp. Sense\nA1/A4/SDA/SCL:\nTest Points" (at 151.4475 102.1106) (layer F.SilkS) (tstamp 7FA08AA0) + (effects (font (size 0.4826 0.4826) (thickness 0.06096)) (justify top)) + ) + (gr_text "Digital IO\nAnalog input\nPWM on TC3\nUART RX/TX\nInterrupt 1/0\nA4 ONLY: Ext. wake 0" (at 155.5115 101.2216) (layer B.SilkS) (tstamp 7FA09230) + (effects (font (size 0.4826 0.4826) (thickness 0.06096)) (justify left top mirror)) + ) + (gr_text "A1/A4 Uses" (at 155.5115 100.2056) (layer B.SilkS) (tstamp 7F9A10A0) + (effects (font (size 0.57912 0.57912) (thickness 0.109728)) (justify left top mirror)) + ) + (gr_text "" (at 142.9385 104.1172) (layer F.SilkS) (tstamp 7F9A17A0) + (effects (font (size 0.57912 0.57912) (thickness 0.073152)) (justify left)) + ) + (gr_text "" (at 142.9385 101.5518) (layer F.SilkS) (tstamp 7F9A1E50) + (effects (font (size 0.57912 0.57912) (thickness 0.073152)) (justify left)) + ) + (dimension 3 (width 0.12) (layer F.SilkS) + (gr_text "3.000 mm" (at 160.9575 108.5016 90) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (feature1 (pts (xy 156.0875 107.0016) (xy 160.273921 107.0016))) + (feature2 (pts (xy 156.0875 110.0016) (xy 160.273921 110.0016))) + (crossbar (pts (xy 159.6875 110.0016) (xy 159.6875 107.0016))) + (arrow1a (pts (xy 159.6875 107.0016) (xy 160.273921 108.128104))) + (arrow1b (pts (xy 159.6875 107.0016) (xy 159.101079 108.128104))) + (arrow2a (pts (xy 159.6875 110.0016) (xy 160.273921 108.875096))) + (arrow2b (pts (xy 159.6875 110.0016) (xy 159.101079 108.875096))) + ) + (gr_text "Stiffener only\nin this area" (at 159.5755 108.5876) (layer F.SilkS) (tstamp 7F95BC90) + (effects (font (size 0.57912 0.57912) (thickness 0.109728))) + ) + + (segment (start 148.082 100.457) (end 148.137 100.457) (width 0.25) (layer Bottom) (net 0)) + (segment (start 142.098 101.5) (end 142.748 101.5) (width 0.25) (layer Top) (net 1)) + (via (at 142.494 100.529) (size 0.8) (drill 0.4) (layers Top Bottom) (net 1)) + (segment (start 142.748 100.783) (end 142.494 100.529) (width 0.25) (layer Top) (net 1)) + (segment (start 142.748 101.5) (end 142.748 100.783) (width 0.25) (layer Top) (net 1)) + (segment (start 142.494 100.529) (end 142.76899 100.25401) (width 0.25) (layer Bottom) (net 1)) + (segment (start 145.201089 100.256533) (end 145.201089 101.934789) (width 0.25) (layer Bottom) (net 1)) + (segment (start 142.76899 100.25401) (end 145.198566 100.25401) (width 0.25) (layer Bottom) (net 1)) + (segment (start 145.198566 100.25401) (end 145.201089 100.256533) (width 0.25) (layer Bottom) (net 1)) + (segment (start 145.201089 101.934789) (end 146.1135 102.8472) (width 0.25) (layer Bottom) (net 1)) + (segment (start 147.022102 101.938598) (end 146.1135 102.8472) (width 0.25) (layer Bottom) (net 1)) + (segment (start 154.7255 104.319944) (end 152.344154 101.938598) (width 0.25) (layer Bottom) (net 1)) + (segment (start 152.344154 101.938598) (end 147.022102 101.938598) (width 0.25) (layer Bottom) (net 1)) + (segment (start 154.7255 108.8056) (end 154.7255 104.319944) (width 0.25) (layer Bottom) (net 1)) + (via (at 146.939 101.219) (size 0.8) (drill 0.4) (layers Top Bottom) (net 2) (status 1000000)) + (segment (start 152.129838 100.901187) (end 147.822498 100.901187) (width 0.25) (layer Bottom) (net 2)) + (segment (start 146.7332 101.4248) (end 146.939 101.219) (width 0.25) (layer Top) (net 2)) + (segment (start 146.3929 101.4248) (end 146.7332 101.4248) (width 0.25) (layer Top) (net 2)) + (segment (start 146.142049 101.675651) (end 146.3929 101.4248) (width 0.25) (layer Top) (net 2)) + (segment (start 143.573651 101.675651) (end 146.142049 101.675651) (width 0.25) (layer Top) (net 2)) + (segment (start 146.1161 101.219) (end 146.1135 101.2216) (width 0.25) (layer Bottom) (net 2)) + (segment (start 147.822498 100.901187) (end 147.504685 101.219) (width 0.25) (layer Bottom) (net 2)) + (segment (start 155.2255 103.996849) (end 152.129838 100.901187) (width 0.25) (layer Bottom) (net 2)) + (segment (start 143.398 101.5) (end 143.573651 101.675651) (width 0.25) (layer Top) (net 2)) + (segment (start 146.939 101.219) (end 146.1161 101.219) (width 0.25) (layer Bottom) (net 2)) + (segment (start 155.2255 108.8056) (end 155.2255 103.996849) (width 0.25) (layer Bottom) (net 2)) + (segment (start 147.504685 101.219) (end 146.939 101.219) (width 0.25) (layer Bottom) (net 2)) + (via (at 147.828 105.664) (size 0.8) (drill 0.4) (layers Top Bottom) (net 3)) + (segment (start 147.6782 105.5142) (end 147.828 105.664) (width 0.25) (layer Top) (net 3)) + (segment (start 146.3929 105.5142) (end 147.6782 105.5142) (width 0.25) (layer Top) (net 3)) + (segment (start 151.2255 106.512573) (end 151.2255 108.8056) (width 0.25) (layer Bottom) (net 3)) + (segment (start 150.712117 105.99919) (end 151.2255 106.512573) (width 0.25) (layer Bottom) (net 3)) + (segment (start 148.16319 105.99919) (end 150.712117 105.99919) (width 0.25) (layer Bottom) (net 3)) + (segment (start 147.828 105.664) (end 148.16319 105.99919) (width 0.25) (layer Bottom) (net 3)) + (segment (start 142.37541 105.26741) (end 145.075078 105.26741) (width 0.25) (layer Top) (net 4)) + (via (at 145.243931 105.098557) (size 0.8) (drill 0.4) (layers Top Bottom) (net 4)) + (segment (start 142.098 104.99) (end 142.37541 105.26741) (width 0.25) (layer Top) (net 4)) + (segment (start 142.098 104.24) (end 142.098 104.99) (width 0.25) (layer Top) (net 4)) + (segment (start 145.075078 105.26741) (end 145.243931 105.098557) (width 0.25) (layer Top) (net 4)) + (segment (start 145.487743 105.098557) (end 146.1135 104.4728) (width 0.25) (layer Bottom) (net 4)) + (segment (start 145.243931 105.098557) (end 145.487743 105.098557) (width 0.25) (layer Bottom) (net 4)) + (segment (start 150.674396 105.392376) (end 151.7255 106.44348) (width 0.25) (layer Bottom) (net 4)) + (segment (start 150.421816 105.392376) (end 150.674396 105.392376) (width 0.25) (layer Bottom) (net 4)) + (segment (start 146.1135 104.4728) (end 149.50224 104.4728) (width 0.25) (layer Bottom) (net 4)) + (segment (start 151.7255 106.44348) (end 151.7255 108.8056) (width 0.25) (layer Bottom) (net 4)) + (segment (start 149.50224 104.4728) (end 150.421816 105.392376) (width 0.25) (layer Bottom) (net 4)) + (segment (start 144.0815 104.4728) (end 144.4472 104.4728) (width 0.25) (layer Bottom) (net 5)) + (segment (start 144.4472 104.4728) (end 145.034 103.886) (width 0.25) (layer Bottom) (net 5)) + (via (at 145.034 103.886) (size 0.8) (drill 0.4) (layers Top Bottom) (net 5)) + (segment (start 145.034 103.886) (end 145.007 103.913) (width 0.25) (layer Top) (net 5)) + (segment (start 145.007 103.913) (end 145.007 104.24) (width 0.25) (layer Top) (net 5)) + (segment (start 143.398 104.24) (end 145.007 104.24) (width 0.25) (layer Top) (net 5)) + (segment (start 145.007 104.24) (end 145.381654 104.24) (width 0.25) (layer Top) (net 5)) + (segment (start 152.2255 108.8056) (end 152.2255 106.193504) (width 0.25) (layer Bottom) (net 5)) + (segment (start 145.381654 104.24) (end 145.856628 104.714974) (width 0.25) (layer Top) (net 5)) + (segment (start 145.856628 104.714974) (end 150.74697 104.714974) (width 0.25) (layer Top) (net 5)) + (via (at 150.74697 104.714974) (size 0.8) (drill 0.4) (layers Top Bottom) (net 5)) + (segment (start 152.2255 106.193504) (end 150.74697 104.714974) (width 0.25) (layer Bottom) (net 5)) + (segment (start 144.0815 102.8472) (end 144.803349 102.8472) (width 0.25) (layer Bottom) (net 6)) + (via (at 144.899309 102.94316) (size 0.8) (drill 0.4) (layers Top Bottom) (net 6)) + (segment (start 144.803349 102.8472) (end 144.899309 102.94316) (width 0.25) (layer Bottom) (net 6)) + (segment (start 144.899309 102.94316) (end 145.57107 102.271399) (width 0.25) (layer Top) (net 6)) + (via (at 148.336 103.52461) (size 0.8) (drill 0.4) (layers Top Bottom) (net 6)) + (segment (start 147.082789 102.271399) (end 148.336 103.52461) (width 0.25) (layer Top) (net 6)) + (segment (start 145.57107 102.271399) (end 147.082789 102.271399) (width 0.25) (layer Top) (net 6)) + (segment (start 152.7255 106.045058) (end 151.490164 104.809722) (width 0.25) (layer Bottom) (net 6)) + (segment (start 151.490164 104.35972) (end 150.655054 103.52461) (width 0.25) (layer Bottom) (net 6)) + (segment (start 152.7255 108.8056) (end 152.7255 106.045058) (width 0.25) (layer Bottom) (net 6)) + (segment (start 151.490164 104.809722) (end 151.490164 104.35972) (width 0.25) (layer Bottom) (net 6)) + (segment (start 150.655054 103.52461) (end 148.336 103.52461) (width 0.25) (layer Bottom) (net 6)) + (segment (start 146.2659 103.9902) (end 146.2659 102.9488) (width 0.254) (layer Top) (net 7) (tstamp 63E759C5)) + (segment (start 153.2255 105.415504) (end 152.231065 104.421069) (width 0.25) (layer Bottom) (net 7)) + (segment (start 148.842094 104.02107) (end 151.831066 104.02107) (width 0.25) (layer Top) (net 7)) + (via (at 152.231065 104.421069) (size 0.8) (drill 0.4) (layers Top Bottom) (net 7)) + (segment (start 148.661153 104.202011) (end 148.842094 104.02107) (width 0.25) (layer Top) (net 7)) + (segment (start 146.3929 103.9902) (end 146.604711 104.202011) (width 0.25) (layer Top) (net 7)) + (segment (start 146.604711 104.202011) (end 148.661153 104.202011) (width 0.25) (layer Top) (net 7)) + (segment (start 151.831066 104.02107) (end 152.231065 104.421069) (width 0.25) (layer Top) (net 7)) + (segment (start 153.2255 108.8056) (end 153.2255 105.415504) (width 0.25) (layer Bottom) (net 7)) + (segment (start 144.0815 101.2216) (end 144.283947 101.2216) (width 0.25) (layer Bottom) (net 9)) + (via (at 144.523679 100.981868) (size 0.8) (drill 0.4) (layers Top Bottom) (net 9)) + (segment (start 144.283947 101.2216) (end 144.523679 100.981868) (width 0.25) (layer Bottom) (net 9)) + (segment (start 144.523679 100.981868) (end 145.175547 100.33) (width 0.25) (layer Top) (net 9)) + (via (at 152.019 102.616) (size 0.8) (drill 0.4) (layers Top Bottom) (net 9)) + (segment (start 154.2255 104.8225) (end 152.019 102.616) (width 0.25) (layer Bottom) (net 9)) + (segment (start 154.2255 108.8056) (end 154.2255 104.8225) (width 0.25) (layer Bottom) (net 9)) + (segment (start 149.733 100.33) (end 147.574 100.33) (width 0.25) (layer Top) (net 9)) + (segment (start 152.019 102.616) (end 149.733 100.33) (width 0.25) (layer Top) (net 9)) + (segment (start 147.574 100.33) (end 147.955 100.33) (width 0.25) (layer Top) (net 9)) + (segment (start 145.175547 100.33) (end 147.574 100.33) (width 0.25) (layer Top) (net 9)) + +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/B1,27.kicad_mod b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/B1,27.kicad_mod new file mode 100644 index 00000000..448fc3c1 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/B1,27.kicad_mod @@ -0,0 +1,16 @@ +(module B1,27 (layer F.Cu) (tedit 0) + (descr "TEST PAD") + (fp_text reference A1 (at 1.524 0 -180) (layer F.SilkS) + (effects (font (size 0.7239 0.7239) (thickness 0.130302)) (justify left bottom)) + ) + (fp_text value TPB1,27 (at -0.635 0.762 -180) (layer F.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_line (start -0.635 0) (end 0.635 0) (layer Dwgs.User) (width 0.0024)) + (fp_line (start 0 -0.635) (end 0 0.635) (layer Dwgs.User) (width 0.0024)) + (fp_text user >TP_SIGNAL_NAME (at -0.635 1.905) (layer Dwgs.User) + (effects (font (size 0.95 0.95) (thickness 0.08)) (justify left bottom)) + ) + (pad TP smd roundrect (at 0 0) (size 1.27 1.27) (layers F.Cu F.Mask) (roundrect_rratio 0.5) + (solder_mask_margin 0.0635)) +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/FH19C9S05SH10-FFC.kicad_mod b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/FH19C9S05SH10-FFC.kicad_mod new file mode 100644 index 00000000..61ebf5f7 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/FH19C9S05SH10-FFC.kicad_mod @@ -0,0 +1,33 @@ +(module FH19C9S05SH10-FFC (layer F.Cu) (tedit 0) + (descr "FH19C-9S-0.5SH(10)-1
\n") + (fp_text reference U$3 (at 0 0) (layer F.SilkS) hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + ) + (fp_text value FH19C-9S-0.5SH_10-FFC (at 0 0) (layer F.SilkS) hide + (effects (font (size 1.27 1.27) (thickness 0.15))) + ) + (fp_line (start -2.4892 0) (end -2.4892 3.35) (layer Edge.Cuts) (width 0.05)) + (fp_line (start -2.3392 3.5) (end 2.3392 3.5) (layer Edge.Cuts) (width 0.05)) + (fp_line (start 2.4892 0) (end 2.4892 3.35) (layer Edge.Cuts) (width 0.05)) + (fp_arc (start -2.3392 3.35) (end -2.3392 3.5) (angle 90) (layer Edge.Cuts) (width 0.05)) + (fp_arc (start 2.3392 3.35) (end 2.3392 3.5) (angle -90) (layer Edge.Cuts) (width 0.05)) + (fp_poly (pts (xy -2.4902 0.9742) (xy 2.4882 0.9742) (xy 2.4892 3.4798) (xy -2.4892 3.4798)) (layer B.Mask) (width 0)) + (pad 1 smd rect (at 2 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 2 smd rect (at 1.5 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 3 smd rect (at 1 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 4 smd rect (at 0.5 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 5 smd rect (at 0 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 6 smd rect (at -0.5 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 7 smd rect (at -1 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 8 smd rect (at -1.5 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) + (pad 9 smd rect (at -2 2.25 90) (size 2.5 0.347) (layers B.Cu B.Mask) + (solder_mask_margin 0.0635)) +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/_0603MP.kicad_mod b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/_0603MP.kicad_mod new file mode 100644 index 00000000..b242ec47 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty/_0603MP.kicad_mod @@ -0,0 +1,19 @@ +(module _0603MP (layer F.Cu) (tedit 0) + (descr "0603 MicroPitch") + (fp_text reference R1 (at -0.0635 1.7145 -180) (layer F.SilkS) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_text value "1% 10K" (at -0.9525 0.9525 -180) (layer F.Fab) + (effects (font (size 0.77216 0.77216) (thickness 0.138988)) (justify left bottom)) + ) + (fp_line (start -0.432 0.306) (end 0.432 0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start 0.432 -0.306) (end -0.432 -0.306) (layer F.Fab) (width 0.1016)) + (fp_line (start 0 -0.254) (end 0 0.254) (layer F.SilkS) (width 0.2032)) + (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)) + (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)) + (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)) + (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)) + (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)) +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.sch b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.sch new file mode 100644 index 00000000..7f0a6a3d --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.sch @@ -0,0 +1,279 @@ +EESchema Schematic File Version 4 +EELAYER 30 0 +EELAYER END +$Descr User 11980 8268 +encoding utf-8 +Sheet 1 1 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +Wire Wire Line + 3300 3100 2200 3100 +Text Label 2300 3100 0 70 ~ 0 +SCL +Wire Wire Line + 3300 3000 2200 3000 +Text Label 2300 3000 0 70 ~ 0 +SDA +Wire Wire Line + 4200 2500 2200 2500 +Wire Wire Line + 4200 2500 4200 2600 +Wire Wire Line + 4300 2500 4200 2500 +Text Label 2300 2500 0 70 ~ 0 +GND +Connection ~ 4200 2500 +Wire Wire Line + 2200 3200 3300 3200 +Text Label 2300 3200 0 70 ~ 0 +A0_TEMP_ENABLE +Wire Wire Line + 4800 3200 5900 3200 +Text Label 4900 3200 0 70 ~ 0 +A0_TEMP_ENABLE +Wire Wire Line + 3300 2600 2200 2600 +Text Label 2300 2600 0 70 ~ 0 +A4_SERCOM3.2_TC3.0 +Wire Wire Line + 3300 2700 2200 2700 +Text Label 2300 2700 0 70 ~ 0 +NC +Wire Wire Line + 3300 2800 2200 2800 +Text Label 2300 2800 0 70 ~ 0 +A2_TEMP_SENSE +Wire Wire Line + 5900 2800 4800 2800 +Connection ~ 5900 2800 +Text Label 4900 2800 0 70 ~ 0 +A2_TEMP_SENSE +Wire Wire Line + 4300 2400 4200 2400 +Wire Wire Line + 4200 2400 2200 2400 +Wire Wire Line + 4200 2300 4200 2400 +Text Label 2300 2400 0 70 ~ 0 +VCC +Connection ~ 4200 2400 +Wire Wire Line + 3300 2900 2200 2900 +Text Label 2300 2900 0 70 ~ 0 +A1_SERCOM3.3_TC3.1 +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:A4L-LOC #FRAME1 +U 1 1 73DA64CA +P 900 6200 +F 0 "#FRAME1" H 900 6200 50 0001 C CNN +F 1 "A4L-LOC" H 900 6200 50 0001 C CNN +F 2 "" H 900 6200 50 0001 C CNN +F 3 "" H 900 6200 50 0001 C CNN + 1 900 6200 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:FH19C-9S-0.5SH_10-FFC U$3 +U 1 1 54307519 +P 1700 2800 +F 0 "U$3" H 2050 3500 59 0000 L CNN +F 1 "FH19C-9S-0.5SH_10-FFC" H 2050 3400 59 0000 L CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:FH19C9S05SH10-FFC" H 1700 2800 50 0001 C CNN +F 3 "" H 1700 2800 50 0001 C CNN + 1 1700 2800 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:RESISTOR_0603MP RT1 +U 1 1 6C7771A6 +P 5900 2600 +F 0 "RT1" H 5900 2700 50 0000 C CNN +F 1 "NTC 10K" H 5900 2500 40 0000 C CNB +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" H 5900 2600 50 0001 C CNN +F 3 "" H 5900 2600 50 0001 C CNN + 1 5900 2600 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:RESISTOR_0603MP R1 +U 1 1 05CBC8DB +P 5900 3000 +F 0 "R1" H 5900 3100 50 0000 C CNN +F 1 "1% 10K" H 5900 2900 40 0000 C CNB +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" H 5900 3000 50 0001 C CNN +F 3 "" H 5900 3000 50 0001 C CNN + 1 5900 3000 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:GND #GND01 +U 1 1 DB8695AC +P 4200 2700 +F 0 "#GND01" H 4200 2700 50 0001 C CNN +F 1 "GND" H 4100 2600 59 0000 L BNN +F 2 "" H 4200 2700 50 0001 C CNN +F 3 "" H 4200 2700 50 0001 C CNN + 1 4200 2700 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:VCC #P+01 +U 1 1 BCDF72C5 +P 4200 2200 +F 0 "#P+01" H 4200 2200 50 0001 C CNN +F 1 "VCC" V 4100 2200 59 0000 L BNN +F 2 "" H 4200 2200 50 0001 C CNN +F 3 "" H 4200 2200 50 0001 C CNN + 1 4200 2200 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:VCC #P+02 +U 1 1 339DE9D3 +P 5900 2300 +F 0 "#P+02" H 5900 2300 50 0001 C CNN +F 1 "VCC" V 5800 2200 59 0000 L BNN +F 2 "" H 5900 2300 50 0001 C CNN +F 3 "" H 5900 2300 50 0001 C CNN + 1 5900 2300 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 GND1 +U 1 1 8E097FD0 +P 4400 2500 +F 0 "GND1" V 4450 2550 59 0000 L BNN +F 1 "TPB1,27" H 4400 2500 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 4400 2500 50 0001 C CNN +F 3 "" H 4400 2500 50 0001 C CNN + 1 4400 2500 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 A4 +U 1 1 E65641C5 +P 3400 2600 +F 0 "A4" V 3450 2650 59 0000 L BNN +F 1 "TPB1,27" H 3400 2600 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 2600 50 0001 C CNN +F 3 "" H 3400 2600 50 0001 C CNN + 1 3400 2600 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 VCC1 +U 1 1 D0DD1D8E +P 4400 2400 +F 0 "VCC1" V 4350 2450 59 0000 L BNN +F 1 "TPB1,27" H 4400 2400 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 4400 2400 50 0001 C CNN +F 3 "" H 4400 2400 50 0001 C CNN + 1 4400 2400 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 SCL1 +U 1 1 252148C1 +P 3400 3100 +F 0 "SCL1" V 3450 3150 59 0000 L BNN +F 1 "TPB1,27" H 3400 3100 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 3100 50 0001 C CNN +F 3 "" H 3400 3100 50 0001 C CNN + 1 3400 3100 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 SDA1 +U 1 1 943CED1C +P 3400 3000 +F 0 "SDA1" V 3450 3050 59 0000 L BNN +F 1 "TPB1,27" H 3400 3000 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 3000 50 0001 C CNN +F 3 "" H 3400 3000 50 0001 C CNN + 1 3400 3000 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 A1 +U 1 1 E1B0505C +P 3400 2900 +F 0 "A1" V 3450 2950 59 0000 L BNN +F 1 "TPB1,27" H 3400 2900 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 2900 50 0001 C CNN +F 3 "" H 3400 2900 50 0001 C CNN + 1 3400 2900 + 0 1 1 0 +$EndComp +$Comp +L OPT3001DNPT:OPT3001DNPT U1 +U 1 1 63E70E51 +P 7050 3100 +F 0 "U1" H 7050 3767 50 0000 C CNN +F 1 "OPT3001DNPT" H 7050 3676 50 0000 C CNN +F 2 "SON65P200X200X65-7N" H 7050 3100 50 0001 L BNN +F 3 "" H 7050 3100 50 0001 L BNN +F 4 "" H 7050 3100 50 0001 L BNN "EMAX" +F 5 "" H 7050 3100 50 0001 L BNN "BALL_COLUMNS" +F 6 "" H 7050 3100 50 0001 L BNN "BODY_DIAMETER" +F 7 "0.65" H 7050 3100 50 0001 L BNN "ENOM" +F 8 "" H 7050 3100 50 0001 L BNN "D1_MIN" +F 9 "1.9" H 7050 3100 50 0001 L BNN "E_MIN" +F 10 "0.25" H 7050 3100 50 0001 L BNN "L_MIN" +F 11 "2.0" H 7050 3100 50 0001 L BNN "E_NOM" +F 12 "0.65" H 7050 3100 50 0001 L BNN "A_MAX" +F 13 "0.65" H 7050 3100 50 0001 L BNN "E2_NOM" +F 14 "IPC 7351B" H 7050 3100 50 0001 L BNN "STANDARD" +F 15 "01/2018" H 7050 3100 50 0001 L BNN "PARTREV" +F 16 "0.25" H 7050 3100 50 0001 L BNN "B_NOM" +F 17 "" H 7050 3100 50 0001 L BNN "THERMAL_PAD" +F 18 "0.3" H 7050 3100 50 0001 L BNN "B_MAX" +F 19 "0.2" H 7050 3100 50 0001 L BNN "B_MIN" +F 20 "" H 7050 3100 50 0001 L BNN "IPC" +F 21 "" H 7050 3100 50 0001 L BNN "DNOM" +F 22 "6.0" H 7050 3100 50 0001 L BNN "PIN_COUNT" +F 23 "2.1" H 7050 3100 50 0001 L BNN "E_MAX" +F 24 "" H 7050 3100 50 0001 L BNN "JEDEC" +F 25 "" H 7050 3100 50 0001 L BNN "BALL_ROWS" +F 26 "" H 7050 3100 50 0001 L BNN "L1_MIN" +F 27 "" H 7050 3100 50 0001 L BNN "L1_NOM" +F 28 "" H 7050 3100 50 0001 L BNN "DMAX" +F 29 "" H 7050 3100 50 0001 L BNN "PIN_COLUMNS" +F 30 "" H 7050 3100 50 0001 L BNN "VACANCIES" +F 31 "" H 7050 3100 50 0001 L BNN "SNAPEDA_PACKAGE_ID" +F 32 "" H 7050 3100 50 0001 L BNN "DMIN" +F 33 "" H 7050 3100 50 0001 L BNN "L1_MAX" +F 34 "0.35" H 7050 3100 50 0001 L BNN "L_MAX" +F 35 "" H 7050 3100 50 0001 L BNN "D1_NOM" +F 36 "Texas Instruments" H 7050 3100 50 0001 L BNN "MANUFACTURER" +F 37 "1.35" H 7050 3100 50 0001 L BNN "D2_NOM" +F 38 "" H 7050 3100 50 0001 L BNN "PACKAGE_TYPE" +F 39 "" H 7050 3100 50 0001 L BNN "D1_MAX" +F 40 "0.3" H 7050 3100 50 0001 L BNN "L_NOM" +F 41 "2.1" H 7050 3100 50 0001 L BNN "D_MAX" +F 42 "2.0" H 7050 3100 50 0001 L BNN "D_NOM" +F 43 "" H 7050 3100 50 0001 L BNN "PINS" +F 44 "1.9" H 7050 3100 50 0001 L BNN "D_MIN" +F 45 "" H 7050 3100 50 0001 L BNN "EMIN" + 1 7050 3100 + 1 0 0 -1 +$EndComp +NoConn ~ 7650 3200 +NoConn ~ 7650 2900 +Text Label 7650 2700 0 50 ~ 0 +VCC +Text Label 7650 3400 0 50 ~ 0 +GND +Text Label 6450 2900 2 50 ~ 0 +GND +Text Label 6450 3100 2 50 ~ 0 +SCL +Text Label 6450 3200 2 50 ~ 0 +SDA +$EndSCHEMATC diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.sch-bak b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.sch-bak new file mode 100644 index 00000000..7f0a6a3d --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.sch-bak @@ -0,0 +1,279 @@ +EESchema Schematic File Version 4 +EELAYER 30 0 +EELAYER END +$Descr User 11980 8268 +encoding utf-8 +Sheet 1 1 +Title "" +Date "" +Rev "" +Comp "" +Comment1 "" +Comment2 "" +Comment3 "" +Comment4 "" +$EndDescr +Wire Wire Line + 3300 3100 2200 3100 +Text Label 2300 3100 0 70 ~ 0 +SCL +Wire Wire Line + 3300 3000 2200 3000 +Text Label 2300 3000 0 70 ~ 0 +SDA +Wire Wire Line + 4200 2500 2200 2500 +Wire Wire Line + 4200 2500 4200 2600 +Wire Wire Line + 4300 2500 4200 2500 +Text Label 2300 2500 0 70 ~ 0 +GND +Connection ~ 4200 2500 +Wire Wire Line + 2200 3200 3300 3200 +Text Label 2300 3200 0 70 ~ 0 +A0_TEMP_ENABLE +Wire Wire Line + 4800 3200 5900 3200 +Text Label 4900 3200 0 70 ~ 0 +A0_TEMP_ENABLE +Wire Wire Line + 3300 2600 2200 2600 +Text Label 2300 2600 0 70 ~ 0 +A4_SERCOM3.2_TC3.0 +Wire Wire Line + 3300 2700 2200 2700 +Text Label 2300 2700 0 70 ~ 0 +NC +Wire Wire Line + 3300 2800 2200 2800 +Text Label 2300 2800 0 70 ~ 0 +A2_TEMP_SENSE +Wire Wire Line + 5900 2800 4800 2800 +Connection ~ 5900 2800 +Text Label 4900 2800 0 70 ~ 0 +A2_TEMP_SENSE +Wire Wire Line + 4300 2400 4200 2400 +Wire Wire Line + 4200 2400 2200 2400 +Wire Wire Line + 4200 2300 4200 2400 +Text Label 2300 2400 0 70 ~ 0 +VCC +Connection ~ 4200 2400 +Wire Wire Line + 3300 2900 2200 2900 +Text Label 2300 2900 0 70 ~ 0 +A1_SERCOM3.3_TC3.1 +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:A4L-LOC #FRAME1 +U 1 1 73DA64CA +P 900 6200 +F 0 "#FRAME1" H 900 6200 50 0001 C CNN +F 1 "A4L-LOC" H 900 6200 50 0001 C CNN +F 2 "" H 900 6200 50 0001 C CNN +F 3 "" H 900 6200 50 0001 C CNN + 1 900 6200 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:FH19C-9S-0.5SH_10-FFC U$3 +U 1 1 54307519 +P 1700 2800 +F 0 "U$3" H 2050 3500 59 0000 L CNN +F 1 "FH19C-9S-0.5SH_10-FFC" H 2050 3400 59 0000 L CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:FH19C9S05SH10-FFC" H 1700 2800 50 0001 C CNN +F 3 "" H 1700 2800 50 0001 C CNN + 1 1700 2800 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:RESISTOR_0603MP RT1 +U 1 1 6C7771A6 +P 5900 2600 +F 0 "RT1" H 5900 2700 50 0000 C CNN +F 1 "NTC 10K" H 5900 2500 40 0000 C CNB +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" H 5900 2600 50 0001 C CNN +F 3 "" H 5900 2600 50 0001 C CNN + 1 5900 2600 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:RESISTOR_0603MP R1 +U 1 1 05CBC8DB +P 5900 3000 +F 0 "R1" H 5900 3100 50 0000 C CNN +F 1 "1% 10K" H 5900 2900 40 0000 C CNB +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:_0603MP" H 5900 3000 50 0001 C CNN +F 3 "" H 5900 3000 50 0001 C CNN + 1 5900 3000 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:GND #GND01 +U 1 1 DB8695AC +P 4200 2700 +F 0 "#GND01" H 4200 2700 50 0001 C CNN +F 1 "GND" H 4100 2600 59 0000 L BNN +F 2 "" H 4200 2700 50 0001 C CNN +F 3 "" H 4200 2700 50 0001 C CNN + 1 4200 2700 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:VCC #P+01 +U 1 1 BCDF72C5 +P 4200 2200 +F 0 "#P+01" H 4200 2200 50 0001 C CNN +F 1 "VCC" V 4100 2200 59 0000 L BNN +F 2 "" H 4200 2200 50 0001 C CNN +F 3 "" H 4200 2200 50 0001 C CNN + 1 4200 2200 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:VCC #P+02 +U 1 1 339DE9D3 +P 5900 2300 +F 0 "#P+02" H 5900 2300 50 0001 C CNN +F 1 "VCC" V 5800 2200 59 0000 L BNN +F 2 "" H 5900 2300 50 0001 C CNN +F 3 "" H 5900 2300 50 0001 C CNN + 1 5900 2300 + 1 0 0 -1 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 GND1 +U 1 1 8E097FD0 +P 4400 2500 +F 0 "GND1" V 4450 2550 59 0000 L BNN +F 1 "TPB1,27" H 4400 2500 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 4400 2500 50 0001 C CNN +F 3 "" H 4400 2500 50 0001 C CNN + 1 4400 2500 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 A4 +U 1 1 E65641C5 +P 3400 2600 +F 0 "A4" V 3450 2650 59 0000 L BNN +F 1 "TPB1,27" H 3400 2600 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 2600 50 0001 C CNN +F 3 "" H 3400 2600 50 0001 C CNN + 1 3400 2600 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 VCC1 +U 1 1 D0DD1D8E +P 4400 2400 +F 0 "VCC1" V 4350 2450 59 0000 L BNN +F 1 "TPB1,27" H 4400 2400 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 4400 2400 50 0001 C CNN +F 3 "" H 4400 2400 50 0001 C CNN + 1 4400 2400 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 SCL1 +U 1 1 252148C1 +P 3400 3100 +F 0 "SCL1" V 3450 3150 59 0000 L BNN +F 1 "TPB1,27" H 3400 3100 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 3100 50 0001 C CNN +F 3 "" H 3400 3100 50 0001 C CNN + 1 3400 3100 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 SDA1 +U 1 1 943CED1C +P 3400 3000 +F 0 "SDA1" V 3450 3050 59 0000 L BNN +F 1 "TPB1,27" H 3400 3000 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 3000 50 0001 C CNN +F 3 "" H 3400 3000 50 0001 C CNN + 1 3400 3000 + 0 1 1 0 +$EndComp +$Comp +L Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import:TPB1,27 A1 +U 1 1 E1B0505C +P 3400 2900 +F 0 "A1" V 3450 2950 59 0000 L BNN +F 1 "TPB1,27" H 3400 2900 50 0001 C CNN +F 2 "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001:B1,27" H 3400 2900 50 0001 C CNN +F 3 "" H 3400 2900 50 0001 C CNN + 1 3400 2900 + 0 1 1 0 +$EndComp +$Comp +L OPT3001DNPT:OPT3001DNPT U1 +U 1 1 63E70E51 +P 7050 3100 +F 0 "U1" H 7050 3767 50 0000 C CNN +F 1 "OPT3001DNPT" H 7050 3676 50 0000 C CNN +F 2 "SON65P200X200X65-7N" H 7050 3100 50 0001 L BNN +F 3 "" H 7050 3100 50 0001 L BNN +F 4 "" H 7050 3100 50 0001 L BNN "EMAX" +F 5 "" H 7050 3100 50 0001 L BNN "BALL_COLUMNS" +F 6 "" H 7050 3100 50 0001 L BNN "BODY_DIAMETER" +F 7 "0.65" H 7050 3100 50 0001 L BNN "ENOM" +F 8 "" H 7050 3100 50 0001 L BNN "D1_MIN" +F 9 "1.9" H 7050 3100 50 0001 L BNN "E_MIN" +F 10 "0.25" H 7050 3100 50 0001 L BNN "L_MIN" +F 11 "2.0" H 7050 3100 50 0001 L BNN "E_NOM" +F 12 "0.65" H 7050 3100 50 0001 L BNN "A_MAX" +F 13 "0.65" H 7050 3100 50 0001 L BNN "E2_NOM" +F 14 "IPC 7351B" H 7050 3100 50 0001 L BNN "STANDARD" +F 15 "01/2018" H 7050 3100 50 0001 L BNN "PARTREV" +F 16 "0.25" H 7050 3100 50 0001 L BNN "B_NOM" +F 17 "" H 7050 3100 50 0001 L BNN "THERMAL_PAD" +F 18 "0.3" H 7050 3100 50 0001 L BNN "B_MAX" +F 19 "0.2" H 7050 3100 50 0001 L BNN "B_MIN" +F 20 "" H 7050 3100 50 0001 L BNN "IPC" +F 21 "" H 7050 3100 50 0001 L BNN "DNOM" +F 22 "6.0" H 7050 3100 50 0001 L BNN "PIN_COUNT" +F 23 "2.1" H 7050 3100 50 0001 L BNN "E_MAX" +F 24 "" H 7050 3100 50 0001 L BNN "JEDEC" +F 25 "" H 7050 3100 50 0001 L BNN "BALL_ROWS" +F 26 "" H 7050 3100 50 0001 L BNN "L1_MIN" +F 27 "" H 7050 3100 50 0001 L BNN "L1_NOM" +F 28 "" H 7050 3100 50 0001 L BNN "DMAX" +F 29 "" H 7050 3100 50 0001 L BNN "PIN_COLUMNS" +F 30 "" H 7050 3100 50 0001 L BNN "VACANCIES" +F 31 "" H 7050 3100 50 0001 L BNN "SNAPEDA_PACKAGE_ID" +F 32 "" H 7050 3100 50 0001 L BNN "DMIN" +F 33 "" H 7050 3100 50 0001 L BNN "L1_MAX" +F 34 "0.35" H 7050 3100 50 0001 L BNN "L_MAX" +F 35 "" H 7050 3100 50 0001 L BNN "D1_NOM" +F 36 "Texas Instruments" H 7050 3100 50 0001 L BNN "MANUFACTURER" +F 37 "1.35" H 7050 3100 50 0001 L BNN "D2_NOM" +F 38 "" H 7050 3100 50 0001 L BNN "PACKAGE_TYPE" +F 39 "" H 7050 3100 50 0001 L BNN "D1_MAX" +F 40 "0.3" H 7050 3100 50 0001 L BNN "L_NOM" +F 41 "2.1" H 7050 3100 50 0001 L BNN "D_MAX" +F 42 "2.0" H 7050 3100 50 0001 L BNN "D_NOM" +F 43 "" H 7050 3100 50 0001 L BNN "PINS" +F 44 "1.9" H 7050 3100 50 0001 L BNN "D_MIN" +F 45 "" H 7050 3100 50 0001 L BNN "EMIN" + 1 7050 3100 + 1 0 0 -1 +$EndComp +NoConn ~ 7650 3200 +NoConn ~ 7650 2900 +Text Label 7650 2700 0 50 ~ 0 +VCC +Text Label 7650 3400 0 50 ~ 0 +GND +Text Label 6450 2900 2 50 ~ 0 +GND +Text Label 6450 3100 2 50 ~ 0 +SCL +Text Label 6450 3200 2 50 ~ 0 +SDA +$EndSCHEMATC diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import.dcm b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import.dcm new file mode 100644 index 00000000..5f3ed79b --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import.dcm @@ -0,0 +1,3 @@ +EESchema-DOCLIB Version 2.0 +# +#End Doc Library diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import.lib b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import.lib new file mode 100644 index 00000000..b3b54896 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import.lib @@ -0,0 +1,990 @@ +EESchema-LIBRARY Version 2.4 +#encoding utf-8 +# +# A4L-LOC +# +DEF A4L-LOC #FRAME 0 40 Y Y 1 L N +F0 "#FRAME" 0 0 50 H I C CNN +F1 "A4L-LOC" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 8550 600 85 0 1 0 >DRAWING_NAME Normal 0 L B +T 0 8550 400 76 0 1 0 >LAST_DATE_TIME Normal 0 L B +T 0 8995 200 85 0 1 0 >SHEET Normal 0 L B +T 0 8550 800 85 0 1 0 "by joey castillo" Normal 0 L B +T 0 9300 200 85 0 1 0 "cc-by-sa 4.0" Normal 0 L B +T 0 7300 200 180 0 1 0 oddly_specific_objects Normal 0 L B +T 0 8540 195 85 0 1 0 Sheet: Normal 0 L B +P 2 1 0 0 7250 150 7250 950 N +P 2 1 0 0 7250 950 8475 950 N +P 2 1 0 0 8475 350 8475 150 N +P 2 1 0 0 8475 350 8475 550 N +P 2 1 0 0 8475 550 8475 750 N +P 2 1 0 0 8475 550 10100 550 N +P 2 1 0 0 8475 750 8475 950 N +P 2 1 0 0 8475 750 10100 750 N +P 2 1 0 0 8475 950 10100 950 N +P 2 1 0 0 9250 150 9250 350 N +P 2 1 0 0 9250 350 8475 350 N +P 2 1 0 0 9250 350 10100 350 N +P 2 1 0 0 10100 150 10100 350 N +P 2 1 0 0 10100 350 10100 550 N +P 2 1 0 0 10100 550 10100 750 N +P 2 1 0 0 10100 750 10100 950 N +ENDDRAW +ENDDEF +# +# FH19C-9S-0.5SH_10-FFC +# +DEF FH19C-9S-0.5SH_10-FFC ~ 0 40 Y Y 1 L N +F0 "" 350 700 59 H V L CNN +F1 "FH19C-9S-0.5SH_10-FFC" 350 600 59 H V L CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -200 500 -200 -500 N +P 2 1 0 0 -200 500 300 500 N +P 2 1 0 0 300 -500 -200 -500 N +P 2 1 0 0 300 -500 300 500 N +X 1 1 500 400 200 L 50 50 1 0 B +X 2 2 500 300 200 L 50 50 1 0 B +X 3 3 500 200 200 L 50 50 1 0 B +X 4 4 500 100 200 L 50 50 1 0 B +X 5 5 500 0 200 L 50 50 1 0 B +X 6 6 500 -100 200 L 50 50 1 0 B +X 7 7 500 -200 200 L 50 50 1 0 B +X 8 8 500 -300 200 L 50 50 1 0 B +X 9 9 500 -400 200 L 50 50 1 0 B +ENDDRAW +ENDDEF +# +# GND +# +DEF GND #GND 0 40 Y Y 1 L P +F0 "#GND" 0 0 50 H I C CNN +F1 "GND" -100 -100 59 H V L BNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -75 0 75 0 N +X GND 1 0 100 100 D 0 0 1 0 W +ENDDRAW +ENDDEF +# +# RESISTOR0603MINI +# +DEF RESISTOR0603MINI R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR0603MINI" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR0805_10MGAP +# +DEF RESISTOR0805_10MGAP R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR0805_10MGAP" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR0805_NOOUTLINE +# +DEF RESISTOR0805_NOOUTLINE R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR0805_NOOUTLINE" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR0805_NOTHERMALS +# +DEF RESISTOR0805_NOTHERMALS R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR0805_NOTHERMALS" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR2012 +# +DEF RESISTOR2012 R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR2012" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR2512 +# +DEF RESISTOR2512 R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR2512" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_0402 +# +DEF RESISTOR_0402 R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_0402" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_0402MP +# +DEF RESISTOR_0402MP R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_0402MP" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_0603 +# +DEF RESISTOR_0603 R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_0603" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_0603MP +# +DEF RESISTOR_0603MP R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_0603MP" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_0603_NOOUT +# +DEF RESISTOR_0603_NOOUT R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_0603_NOOUT" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_0805 +# +DEF RESISTOR_0805 R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_0805" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_0805MP +# +DEF RESISTOR_0805MP R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_0805MP" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_1206 +# +DEF RESISTOR_1206 R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_1206" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# RESISTOR_1206MP +# +DEF RESISTOR_1206MP R 0 40 Y Y 1 L N +F0 "R" 0 100 50 H V C CNN +F1 "RESISTOR_1206MP" 0 0 40 H V C CNB +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 -100 -50 -100 50 N +P 2 1 0 0 -100 50 100 50 N +P 2 1 0 0 100 -50 -100 -50 N +P 2 1 0 0 100 50 100 -50 N +X 1 1 -200 0 100 R 0 0 1 0 P +X 2 2 200 0 100 L 0 0 1 0 P +ENDDRAW +ENDDEF +# +# TPB1,27 +# +DEF TPB1,27 TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPB1,27" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPB2,54 +# +DEF TPB2,54 TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPB2,54" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPPAD1-13 +# +DEF TPPAD1-13 TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPPAD1-13" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPPAD1-13Y +# +DEF TPPAD1-13Y TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPPAD1-13Y" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPPAD1-17 +# +DEF TPPAD1-17 TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPPAD1-17" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPPAD1-17Y +# +DEF TPPAD1-17Y TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPPAD1-17Y" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPPAD1-20 +# +DEF TPPAD1-20 TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPPAD1-20" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPPAD1-20Y +# +DEF TPPAD1-20Y TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPPAD1-20Y" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP06R +# +DEF TPTP06R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP06R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP06SQ +# +DEF TPTP06SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP06SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP07R +# +DEF TPTP07R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP07R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP07SQ +# +DEF TPTP07SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP07SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP08R +# +DEF TPTP08R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP08R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP08SQ +# +DEF TPTP08SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP08SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP09R +# +DEF TPTP09R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP09R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP09SQ +# +DEF TPTP09SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP09SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP10R +# +DEF TPTP10R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP10R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP10SQ +# +DEF TPTP10SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP10SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP11R +# +DEF TPTP11R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP11R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP11SQ +# +DEF TPTP11SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP11SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP12R +# +DEF TPTP12R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP12R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP12SQ +# +DEF TPTP12SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP12SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP13R +# +DEF TPTP13R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP13R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP13SQ +# +DEF TPTP13SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP13SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP14R +# +DEF TPTP14R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP14R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP14SQ +# +DEF TPTP14SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP14SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP15R +# +DEF TPTP15R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP15R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP15SQ +# +DEF TPTP15SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP15SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP16R +# +DEF TPTP16R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP16R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP16SQ +# +DEF TPTP16SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP16SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP17R +# +DEF TPTP17R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP17R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP17SQ +# +DEF TPTP17SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP17SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP18R +# +DEF TPTP18R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP18R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP18SQ +# +DEF TPTP18SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP18SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP19R +# +DEF TPTP19R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP19R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP19SQ +# +DEF TPTP19SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP19SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP20R +# +DEF TPTP20R TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP20R" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# TPTP20SQ +# +DEF TPTP20SQ TP 0 40 Y Y 1 L N +F0 "TP" -50 50 59 H V L BNN +F1 "TPTP20SQ" 0 0 50 H I C CNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +T 0 50 -50 59 0 1 0 >TP_SIGNAL_NAME Normal 0 L B +P 2 1 0 0 -30 -30 0 0 N +P 2 1 0 0 0 -60 -30 -30 N +P 2 1 0 0 0 0 30 -30 N +P 2 1 0 0 30 -30 0 -60 N +X TP TP 0 -100 100 U 0 0 1 0 I +ENDDRAW +ENDDEF +# +# VCC +# +DEF VCC #P+ 0 40 Y Y 1 L P +F0 "#P+" 0 0 50 H I C CNN +F1 "VCC" -100 -100 59 V V L BNN +F2 "" 0 0 50 H I C CNN +F3 "" 0 0 50 H I C CNN +DRAW +P 2 1 0 0 0 0 -50 -75 N +P 2 1 0 0 50 -75 0 0 N +X VCC 1 0 -100 100 U 0 0 1 0 W +ENDDRAW +ENDDEF +# +#End Library diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/empty.kicad_wks b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/empty.kicad_wks new file mode 100644 index 00000000..f50032b1 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/empty.kicad_wks @@ -0,0 +1,5 @@ +(page_layout +(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)) +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/fp-info-cache b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/fp-info-cache new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/fp-info-cache @@ -0,0 +1 @@ +0 diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/fp-lib-table b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/fp-lib-table new file mode 100644 index 00000000..9ebe18e1 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/fp-lib-table @@ -0,0 +1,4 @@ +(fp_lib_table + (lib (name "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001")(type KiCad)(uri "$(KIPRJMOD)/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001.pretty")(options "")(descr "")) + (lib (name OPT3001DNPT)(type KiCad)(uri ${KIPRJMOD}/OPT3001DNPT)(options "")(descr "")) +) diff --git a/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/sym-lib-table b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/sym-lib-table new file mode 100644 index 00000000..8b9d2689 --- /dev/null +++ b/PCB/Sensor Boards/Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001/sym-lib-table @@ -0,0 +1,4 @@ +(sym_lib_table + (lib (name Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import)(type Legacy)(uri ${KIPRJMOD}/Q3Q-SWAB-A1-00_Temperature_+_Test_Points_+_OPT3001-eagle-import.lib)(options "")(descr "")) + (lib (name OPT3001DNPT)(type Legacy)(uri ${KIPRJMOD}/OPT3001DNPT/OPT3001DNPT.lib)(options "")(descr "")) +) diff --git a/make.mk b/make.mk index 737e1f51..35af3422 100644 --- a/make.mk +++ b/make.mk @@ -150,6 +150,7 @@ SRCS += \ $(TOP)/watch-library/hardware/hpl/systick/hpl_systick.c \ $(TOP)/watch-library/shared/driver/thermistor_driver.c \ $(TOP)/watch-library/shared/driver/lis2dw.c \ + $(TOP)/watch-library/shared/driver/opt3001.c \ $(TOP)/watch-library/shared/driver/spiflash.c \ $(TOP)/watch-library/shared/watch/watch_private_buzzer.c \ $(TOP)/watch-library/shared/watch/watch_private_display.c \ @@ -195,6 +196,7 @@ SRCS += \ $(TOP)/watch-library/simulator/watch/watch_private.c \ $(TOP)/watch-library/simulator/watch/watch.c \ $(TOP)/watch-library/shared/driver/thermistor_driver.c \ + $(TOP)/watch-library/shared/driver/opt3001.c \ $(TOP)/watch-library/shared/watch/watch_private_buzzer.c \ $(TOP)/watch-library/shared/watch/watch_private_display.c \ $(TOP)/watch-library/shared/watch/watch_utility.c \ diff --git a/movement/filesystem.c b/movement/filesystem.c index 2b345eda..97e35455 100644 --- a/movement/filesystem.c +++ b/movement/filesystem.c @@ -196,6 +196,7 @@ static void filesystem_cat(char *filename) { if (info.size > 0) { char *buf = malloc(info.size + 1); filesystem_read_file(filename, buf, info.size); + buf[info.size] = '\0'; printf("%s\n", buf); free(buf); } else { diff --git a/movement/lib/chirpy_tx/chirpy_tx.c b/movement/lib/chirpy_tx/chirpy_tx.c new file mode 100644 index 00000000..41a42a58 --- /dev/null +++ b/movement/lib/chirpy_tx/chirpy_tx.c @@ -0,0 +1,179 @@ +/* + * MIT License + * + * Copyright (c) 2023 Gabor L Ugray + * + * 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 +#include +#include +#include +#include "chirpy_tx.h" + +static const uint32_t chirpy_min_freq = 2500; +static const uint32_t cirpy_freq_step = 250; + +// This many bytes are followed by a CRC and block separator +// It's a multiple of 3 so no bits are wasted (a tone encodes 3 bits) +// Last block can be shorter +static const uint8_t chirpy_default_block_size = 15; + +// The dedicated control tone. This is the highest tone index. +static const uint8_t chirpy_control_tone = 8; + +// Pre-computed tone periods. This is allocated and populated on-demand. +static uint32_t *chirpy_tone_periods = NULL; + +uint8_t chirpy_crc8(const uint8_t *addr, uint16_t len) { + uint8_t crc = 0; + for (uint16_t i = 0; i < len; i++) + crc = chirpy_update_crc8(addr[i], crc); + return crc; +} + +uint8_t chirpy_update_crc8(uint8_t next_byte, uint8_t crc) { + for (uint8_t j = 0; j < 8; j++) { + uint8_t mix = (crc ^ next_byte) & 0x01; + crc >>= 1; + if (mix) + crc ^= 0x8C; + next_byte >>= 1; + } + return crc; +} + +static void _chirpy_append_tone(chirpy_encoder_state_t *ces, uint8_t tone) { + // This is BAD and should never happen. But if it does, we'd rather + // create a corrupt transmission than corrupt memory #$^@ + if (ces->tone_count == CHIRPY_TONE_BUF_SIZE) + return; + ces->tone_buf[ces->tone_count] = tone; + ++ces->tone_count; +} + +void chirpy_init_encoder(chirpy_encoder_state_t *ces, chirpy_get_next_byte_t get_next_byte) { + memset(ces, 0, sizeof(chirpy_encoder_state_t)); + ces->block_size = chirpy_default_block_size; + ces->get_next_byte = get_next_byte; + _chirpy_append_tone(ces, 8); + _chirpy_append_tone(ces, 0); + _chirpy_append_tone(ces, 8); + _chirpy_append_tone(ces, 0); +} + +static uint8_t _chirpy_retrieve_next_tone(chirpy_encoder_state_t *ces) { + if (ces->tone_pos == ces->tone_count) + return 255; + + uint8_t res = ces->tone_buf[ces->tone_pos]; + ++ces->tone_pos; + if (ces->tone_pos == ces->tone_count) { + // End of buffer: reset buffer + ces->tone_pos = 0; + ces->tone_count = 0; + } + return res; +} + +static void _chirpy_encode_bits(chirpy_encoder_state_t *ces, uint8_t force_partial) { + while (ces->bit_count > 0) { + if (ces->bit_count < 3 && !force_partial) break; + uint8_t tone = (uint8_t)(ces->bits >> 13); + _chirpy_append_tone(ces, tone); + if (ces->bit_count >= 3) { + ces->bits <<= 3; + ces->bit_count -= 3; + } else { + ces->bits = 0; + ces->bit_count = 0; + } + } +} + +static void _chirpy_finish_block(chirpy_encoder_state_t *ces) { + _chirpy_append_tone(ces, chirpy_control_tone); + ces->bits = ces->crc; + ces->bits <<= 8; + ces->bit_count = 8; + _chirpy_encode_bits(ces, 1); + ces->bit_count = 0; + ces->crc = 0; + ces->block_len = 0; + _chirpy_append_tone(ces, chirpy_control_tone); +} + +static void _chirpy_finish_transmission(chirpy_encoder_state_t *ces) { + _chirpy_append_tone(ces, chirpy_control_tone); + _chirpy_append_tone(ces, chirpy_control_tone); +} + +uint8_t chirpy_get_next_tone(chirpy_encoder_state_t *ces) { + // If there are tones left in the buffer, keep sending those + if (ces->tone_pos < ces->tone_count) + return _chirpy_retrieve_next_tone(ces); + + // We know data is over: that means we've wrapped up transmission + // Just drain tone buffer, and then keep sendig EOB + if (ces->get_next_byte == 0) + return _chirpy_retrieve_next_tone(ces); + + // Fetch next byte + uint8_t next_byte; + uint8_t got_more = ces->get_next_byte(&next_byte); + + // Data over: write CRC if we sent a partial buffer; send end signal + if (got_more == 0) { + ces->get_next_byte = 0; + if (ces->bit_count > 0) _chirpy_encode_bits(ces, 1); + if (ces->block_len > 0) _chirpy_finish_block(ces); + _chirpy_finish_transmission(ces); + return _chirpy_retrieve_next_tone(ces); + } + + // Got more data: add to bits; convert + uint16_t msk = next_byte; + msk <<= (8 - ces->bit_count); + ces->bits |= msk; + ces->bit_count += 8; + _chirpy_encode_bits(ces, 0); + ++ces->block_len; + ces->crc = chirpy_update_crc8(next_byte, ces->crc); + if (ces->block_len == ces->block_size) + _chirpy_finish_block(ces); + + return _chirpy_retrieve_next_tone(ces); +} + +uint16_t chirpy_get_tone_period(uint8_t tone) { + // Create pre-computed tone periods array on first use + if (chirpy_tone_periods == NULL) { + chirpy_tone_periods = malloc((chirpy_control_tone + 1) * sizeof(uint32_t)); + for (uint8_t i = 0; i < chirpy_control_tone + 1; ++i) { + uint32_t freq = chirpy_min_freq + i * cirpy_freq_step; + uint16_t period = 1000000 / freq; + chirpy_tone_periods[i] = period; + } + } + // Return pre-computed value, but be paranoid about indexing into array + if (tone > chirpy_control_tone) + tone = chirpy_control_tone; + return chirpy_tone_periods[tone]; +} diff --git a/movement/lib/chirpy_tx/chirpy_tx.h b/movement/lib/chirpy_tx/chirpy_tx.h new file mode 100644 index 00000000..092d05c7 --- /dev/null +++ b/movement/lib/chirpy_tx/chirpy_tx.h @@ -0,0 +1,98 @@ +/* + * MIT License + * + * Copyright (c) 2023 Gabor L Ugray + * + * 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 CHIRPY_TX_H +#define CHIRPY_TX_H + +/** @brief Calculates the CRC of a byte sequence. + */ +uint8_t chirpy_crc8(const uint8_t *addr, uint16_t len); + +/** @brief Updates a CRC value with the next byte of input. + */ +uint8_t chirpy_update_crc8(uint8_t next_byte, uint8_t crc); + +/** @brief Function to return next byte to be encoded. + * @param next_byte Pointer where implementor must write next byte (if available). + * @return 1 if there is a next byte, or 0 if no more data to encode. + */ +typedef uint8_t (*chirpy_get_next_byte_t)(uint8_t *next_byte); + +#define CHIRPY_TONE_BUF_SIZE 16 + +// Holds state used by the encoder. Do not manipulate directly. +typedef struct { + uint8_t tone_buf[CHIRPY_TONE_BUF_SIZE]; + uint8_t tone_pos; + uint8_t tone_count; + uint8_t block_len; + uint8_t block_size; + uint8_t crc; + uint16_t bits; + uint8_t bit_count; + chirpy_get_next_byte_t get_next_byte; +} chirpy_encoder_state_t; + +/** @brief Iniitializes the encoder state to be used during the transmission. + * @param ces Pointer to encoder state object to be initialized. + * @param get_next_byte Pointer to function that the encoder will call to fetch data byte by byte. + */ +void chirpy_init_encoder(chirpy_encoder_state_t *ces, chirpy_get_next_byte_t get_next_byte); + +/** @brief Returns the next tone to be transmitted. + * @details This function will call the get_next_byte function stored in the encoder state to + * retrieve the next byte to be transmitted as needed. As a single byte is encoded as several tones, + * and because the transmission also includes periodic CRC values, not every call to this function + * will result in a callback for the next data byte. + * @param ced Pointer to the encoder state object. + * @return A tone index from 0 to N (where N is the largest tone index), or 255 if the transmission is over. + */ +uint8_t chirpy_get_next_tone(chirpy_encoder_state_t *ces); + +/** @brief Returns the period value for buzzing out a tone. + * @param tone The tone index, 0 thru 8. + * @return The period for the tone's frequency, i.e., 1_000_000 / freq. + */ +uint16_t chirpy_get_tone_period(uint8_t tone); + +/** @brief Typedef for a tick handler function. + */ +typedef void (*chirpy_tick_fun_t)(void *context); + +/** @brief Creature-comfort struct for use in your chirping code. + * @details The idea is to handle a tick that happens 64 times per second at the outermost level. + * To get to the desired ~20 tones per second, increment a counter and call the actual + * transmission ticker when tick_counter reaches tick_compare, with a compare value of 3. + * seq_pos is for use by the transmission function to keep track of where it is in the data. + * The current transmission function is stored in tick_fun. You can have multiple phases + * by switching to a different function. E.g., intro countdown first, followed by data chirping. + */ +typedef struct { + uint8_t tick_count; + uint8_t tick_compare; + uint16_t seq_pos; + chirpy_tick_fun_t tick_fun; +} chirpy_tick_state_t; + +#endif diff --git a/movement/lib/chirpy_tx/test/test_main.c b/movement/lib/chirpy_tx/test/test_main.c new file mode 100644 index 00000000..c76a3f3c --- /dev/null +++ b/movement/lib/chirpy_tx/test/test_main.c @@ -0,0 +1,160 @@ +/* + * MIT License + * + * Copyright (c) 2023 Gabor L Ugray + * + * 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 +#include +#include +#include "../src/lib/chirpy_tx.h" +#include "unity.h" + + +void setUp(void) { +} + +void tearDown(void) { +} + +const char *crc_test_str0 = ""; +const char *crc_test_str1 = "h"; +const char *crc_test_str2 = "he"; +const char *crc_test_str3 = "hen"; +const char *crc_test_str4 = "henl"; +const char *crc_test_str5 = "henlO"; + +#define CRC_VAL_COUNT 5 +const uint8_t crc_vals[] = {167, 118, 95, 92, 127}; + +void test_crc8() { + TEST_ASSERT_EQUAL_UINT8(0, chirpy_crc8((const uint8_t *)crc_test_str0, 0)); + TEST_ASSERT_EQUAL_UINT8(167, chirpy_crc8((const uint8_t *)crc_test_str1, strlen(crc_test_str1))); + TEST_ASSERT_EQUAL_UINT8(118, chirpy_crc8((const uint8_t *)crc_test_str2, strlen(crc_test_str2))); + TEST_ASSERT_EQUAL_UINT8(95, chirpy_crc8((const uint8_t *)crc_test_str3, strlen(crc_test_str3))); + TEST_ASSERT_EQUAL_UINT8(92, chirpy_crc8((const uint8_t *)crc_test_str4, strlen(crc_test_str4))); + TEST_ASSERT_EQUAL_UINT8(127, chirpy_crc8((const uint8_t *)crc_test_str5, strlen(crc_test_str5))); + + uint8_t crc = 0; + for (uint16_t i = 0; i < CRC_VAL_COUNT; ++i) { + uint8_t next_byte = crc_test_str5[i]; + crc = chirpy_update_crc8(next_byte, crc); + TEST_ASSERT_EQUAL_UINT8(crc_vals[i], crc); + } + + crc = chirpy_update_crc8(0, 0); + TEST_ASSERT_EQUAL(0, crc); + + crc = chirpy_update_crc8(0x4f, 0); + TEST_ASSERT_EQUAL(7, crc); +} + +const uint16_t data_len_01 = 0; +const uint8_t data_01[] = {}; +const uint16_t tones_len_01 = 6; +const uint8_t tones_01[] = {8, 0, 8, 0, 8, 8}; + +const uint16_t data_len_02 = 1; +const uint8_t data_02[] = {0}; +const uint16_t tones_len_02 = 14; +const uint8_t tones_02[] = {8, 0, 8, 0, 0, 0, 0, 8, 0, 0, 0, 8, 8, 8}; + +const uint16_t data_len_03 = 1; +const uint8_t data_03[] = {0x68}; +const uint16_t tones_len_03 = 14; +const uint8_t tones_03[] = {8, 0, 8, 0, 3, 2, 0, 8, 5, 1, 6, 8, 8, 8}; + +const uint16_t data_len_04 = 3; +const uint8_t data_04[] = {0x68, 0x65, 0x6e}; +const uint16_t tones_len_04 = 19; +const uint8_t tones_04[] = {8, 0, 8, 0, 3, 2, 0, 6, 2, 5, 5, 6, 8, 2, 7, 6, 8, 8, 8}; + +const uint16_t data_len_05 = 4; +const uint8_t data_05[] = {0x68, 0x65, 0x6e, 0x4f}; +const uint16_t tones_len_05 = 27; +const uint8_t tones_05[] = { + 8, 0, 8, 0, 3, 2, 0, 6, 2, 5, 5, 6, 8, 2, 7, 6, 8, + 2, 3, 6, 8, 0, 1, 6, 8, 8, 8}; + +uint8_t curr_data_pos; +uint8_t curr_data_len; +const uint8_t *curr_data; + +uint8_t get_next_byte(uint8_t *next_byte) { + if (curr_data_pos < curr_data_len) { + *next_byte = curr_data[curr_data_pos]; + ++curr_data_pos; + return 1; + } + return 0; +} + +void test_encoder_one(const uint8_t *data, uint16_t data_len, const uint8_t *tones, uint16_t tones_len) { + curr_data = data; + curr_data_len = data_len; + curr_data_pos = 0; + chirpy_encoder_state_t ces; + chirpy_init_encoder(&ces, get_next_byte); + ces.block_size = 3; + + uint8_t got_tones[2048] = {0}; + uint16_t got_tone_pos = 0; + while (got_tone_pos < 2048) { + uint8_t tone = chirpy_get_next_tone(&ces); + got_tones[got_tone_pos] = tone; + if (tone == 255) break; + ++got_tone_pos; + } + char buf1[65536]; + char bufx[256]; + memset(buf1, 0, 65536); + for (uint16_t i = 0; i < got_tone_pos; ++i) { + if (i == 0) + sprintf(bufx, "%d", got_tones[i]); + else + sprintf(bufx, ", %d", got_tones[i]); + strcat(buf1, bufx); + } + TEST_MESSAGE(buf1); + TEST_ASSERT_EQUAL(tones_len, got_tone_pos); + uint16_t smaller_len = tones_len < got_tone_pos ? tones_len : got_tone_pos; + TEST_ASSERT_EQUAL_UINT8_ARRAY(tones, got_tones, smaller_len); +} + +void test_encoder() { + TEST_MESSAGE("Testing encoder with dataset 01"); + test_encoder_one(data_01, data_len_01, tones_01, tones_len_01); + TEST_MESSAGE("Testing encoder with dataset 02"); + test_encoder_one(data_02, data_len_02, tones_02, tones_len_02); + TEST_MESSAGE("Testing encoder with dataset 03"); + test_encoder_one(data_03, data_len_03, tones_03, tones_len_03); + TEST_MESSAGE("Testing encoder with dataset 04"); + test_encoder_one(data_04, data_len_04, tones_04, tones_len_04); + TEST_MESSAGE("Testing encoder with dataset 05"); + test_encoder_one(data_05, data_len_05, tones_05, tones_len_05); +} + +int main(void) { + UNITY_BEGIN(); + RUN_TEST(test_crc8); + RUN_TEST(test_encoder); + return UNITY_END(); +} diff --git a/movement/lib/chirpy_tx/test/unity.c b/movement/lib/chirpy_tx/test/unity.c new file mode 100644 index 00000000..3e4bc04d --- /dev/null +++ b/movement/lib/chirpy_tx/test/unity.c @@ -0,0 +1,2466 @@ +/* ========================================================================= + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +============================================================================ */ + +#include "unity.h" + +#ifndef UNITY_PROGMEM +#define UNITY_PROGMEM +#endif + +/* If omitted from header, declare overrideable prototypes here so they're ready for use */ +#ifdef UNITY_OMIT_OUTPUT_CHAR_HEADER_DECLARATION +void UNITY_OUTPUT_CHAR(int); +#endif + +/* Helpful macros for us to use here in Assert functions */ +#define UNITY_FAIL_AND_BAIL do { Unity.CurrentTestFailed = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define UNITY_IGNORE_AND_BAIL do { Unity.CurrentTestIgnored = 1; UNITY_OUTPUT_FLUSH(); TEST_ABORT(); } while (0) +#define RETURN_IF_FAIL_OR_IGNORE do { if (Unity.CurrentTestFailed || Unity.CurrentTestIgnored) { TEST_ABORT(); } } while (0) + +struct UNITY_STORAGE_T Unity; + +#ifdef UNITY_OUTPUT_COLOR +const char UNITY_PROGMEM UnityStrOk[] = "\033[42mOK\033[0m"; +const char UNITY_PROGMEM UnityStrPass[] = "\033[42mPASS\033[0m"; +const char UNITY_PROGMEM UnityStrFail[] = "\033[41mFAIL\033[0m"; +const char UNITY_PROGMEM UnityStrIgnore[] = "\033[43mIGNORE\033[0m"; +#else +const char UNITY_PROGMEM UnityStrOk[] = "OK"; +const char UNITY_PROGMEM UnityStrPass[] = "PASS"; +const char UNITY_PROGMEM UnityStrFail[] = "FAIL"; +const char UNITY_PROGMEM UnityStrIgnore[] = "IGNORE"; +#endif +static const char UNITY_PROGMEM UnityStrNull[] = "NULL"; +static const char UNITY_PROGMEM UnityStrSpacer[] = ". "; +static const char UNITY_PROGMEM UnityStrExpected[] = " Expected "; +static const char UNITY_PROGMEM UnityStrWas[] = " Was "; +static const char UNITY_PROGMEM UnityStrGt[] = " to be greater than "; +static const char UNITY_PROGMEM UnityStrLt[] = " to be less than "; +static const char UNITY_PROGMEM UnityStrOrEqual[] = "or equal to "; +static const char UNITY_PROGMEM UnityStrNotEqual[] = " to be not equal to "; +static const char UNITY_PROGMEM UnityStrElement[] = " Element "; +static const char UNITY_PROGMEM UnityStrByte[] = " Byte "; +static const char UNITY_PROGMEM UnityStrMemory[] = " Memory Mismatch."; +static const char UNITY_PROGMEM UnityStrDelta[] = " Values Not Within Delta "; +static const char UNITY_PROGMEM UnityStrPointless[] = " You Asked Me To Compare Nothing, Which Was Pointless."; +static const char UNITY_PROGMEM UnityStrNullPointerForExpected[] = " Expected pointer to be NULL"; +static const char UNITY_PROGMEM UnityStrNullPointerForActual[] = " Actual pointer was NULL"; +#ifndef UNITY_EXCLUDE_FLOAT +static const char UNITY_PROGMEM UnityStrNot[] = "Not "; +static const char UNITY_PROGMEM UnityStrInf[] = "Infinity"; +static const char UNITY_PROGMEM UnityStrNegInf[] = "Negative Infinity"; +static const char UNITY_PROGMEM UnityStrNaN[] = "NaN"; +static const char UNITY_PROGMEM UnityStrDet[] = "Determinate"; +static const char UNITY_PROGMEM UnityStrInvalidFloatTrait[] = "Invalid Float Trait"; +#endif +const char UNITY_PROGMEM UnityStrErrShorthand[] = "Unity Shorthand Support Disabled"; +const char UNITY_PROGMEM UnityStrErrFloat[] = "Unity Floating Point Disabled"; +const char UNITY_PROGMEM UnityStrErrDouble[] = "Unity Double Precision Disabled"; +const char UNITY_PROGMEM UnityStrErr64[] = "Unity 64-bit Support Disabled"; +static const char UNITY_PROGMEM UnityStrBreaker[] = "-----------------------"; +static const char UNITY_PROGMEM UnityStrResultsTests[] = " Tests "; +static const char UNITY_PROGMEM UnityStrResultsFailures[] = " Failures "; +static const char UNITY_PROGMEM UnityStrResultsIgnored[] = " Ignored "; +#ifndef UNITY_EXCLUDE_DETAILS +static const char UNITY_PROGMEM UnityStrDetail1Name[] = UNITY_DETAIL1_NAME " "; +static const char UNITY_PROGMEM UnityStrDetail2Name[] = " " UNITY_DETAIL2_NAME " "; +#endif +/*----------------------------------------------- + * Pretty Printers & Test Result Output Handlers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +/* Local helper function to print characters. */ +static void UnityPrintChar(const char* pch) +{ + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } +} + +/*-----------------------------------------------*/ +/* Local helper function to print ANSI escape strings e.g. "\033[42m". */ +#ifdef UNITY_OUTPUT_COLOR +static UNITY_UINT UnityPrintAnsiEscapeString(const char* string) +{ + const char* pch = string; + UNITY_UINT count = 0; + + while (*pch && (*pch != 'm')) + { + UNITY_OUTPUT_CHAR(*pch); + pch++; + count++; + } + UNITY_OUTPUT_CHAR('m'); + count++; + + return count; +} +#endif + +/*-----------------------------------------------*/ +void UnityPrint(const char* string) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch) + { +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + UnityPrintChar(pch); + pch++; + } + } +} +/*-----------------------------------------------*/ +void UnityPrintLen(const char* string, const UNITY_UINT32 length) +{ + const char* pch = string; + + if (pch != NULL) + { + while (*pch && ((UNITY_UINT32)(pch - string) < length)) + { + /* printable characters plus CR & LF are printed */ + if ((*pch <= 126) && (*pch >= 32)) + { + UNITY_OUTPUT_CHAR(*pch); + } + /* write escaped carriage returns */ + else if (*pch == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (*pch == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)*pch, 2); + } + pch++; + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style) +{ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (style == UNITY_DISPLAY_STYLE_CHAR) + { + /* printable characters plus CR & LF are printed */ + UNITY_OUTPUT_CHAR('\''); + if ((number <= 126) && (number >= 32)) + { + UNITY_OUTPUT_CHAR((int)number); + } + /* write escaped carriage returns */ + else if (number == 13) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('r'); + } + /* write escaped line feeds */ + else if (number == 10) + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('n'); + } + /* unprintable characters are shown as codes */ + else + { + UNITY_OUTPUT_CHAR('\\'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 2); + } + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrintNumber(number); + } + } + else if ((style & UNITY_DISPLAY_RANGE_UINT) == UNITY_DISPLAY_RANGE_UINT) + { + UnityPrintNumberUnsigned((UNITY_UINT)number); + } + else + { + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, (char)((style & 0xF) * 2)); + } +} + +/*-----------------------------------------------*/ +void UnityPrintNumber(const UNITY_INT number_to_print) +{ + UNITY_UINT number = (UNITY_UINT)number_to_print; + + if (number_to_print < 0) + { + /* A negative number, including MIN negative */ + UNITY_OUTPUT_CHAR('-'); + number = (~number) + 1; + } + UnityPrintNumberUnsigned(number); +} + +/*----------------------------------------------- + * basically do an itoa using as little ram as possible */ +void UnityPrintNumberUnsigned(const UNITY_UINT number) +{ + UNITY_UINT divisor = 1; + + /* figure out initial divisor */ + while (number / divisor > 9) + { + divisor *= 10; + } + + /* now mod and print, then divide divisor */ + do + { + UNITY_OUTPUT_CHAR((char)('0' + (number / divisor % 10))); + divisor /= 10; + } while (divisor > 0); +} + +/*-----------------------------------------------*/ +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print) +{ + int nibble; + char nibbles = nibbles_to_print; + + if ((unsigned)nibbles > UNITY_MAX_NIBBLES) + { + nibbles = UNITY_MAX_NIBBLES; + } + + while (nibbles > 0) + { + nibbles--; + nibble = (int)(number >> (nibbles * 4)) & 0x0F; + if (nibble <= 9) + { + UNITY_OUTPUT_CHAR((char)('0' + nibble)); + } + else + { + UNITY_OUTPUT_CHAR((char)('A' - 10 + nibble)); + } + } +} + +/*-----------------------------------------------*/ +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number) +{ + UNITY_UINT current_bit = (UNITY_UINT)1 << (UNITY_INT_WIDTH - 1); + UNITY_INT32 i; + + for (i = 0; i < UNITY_INT_WIDTH; i++) + { + if (current_bit & mask) + { + if (current_bit & number) + { + UNITY_OUTPUT_CHAR('1'); + } + else + { + UNITY_OUTPUT_CHAR('0'); + } + } + else + { + UNITY_OUTPUT_CHAR('X'); + } + current_bit = current_bit >> 1; + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +/* + * This function prints a floating-point value in a format similar to + * printf("%.7g") on a single-precision machine or printf("%.9g") on a + * double-precision machine. The 7th digit won't always be totally correct + * in single-precision operation (for that level of accuracy, a more + * complicated algorithm would be needed). + */ +void UnityPrintFloat(const UNITY_DOUBLE input_number) +{ +#ifdef UNITY_INCLUDE_DOUBLE + static const int sig_digits = 9; + static const UNITY_INT32 min_scaled = 100000000; + static const UNITY_INT32 max_scaled = 1000000000; +#else + static const int sig_digits = 7; + static const UNITY_INT32 min_scaled = 1000000; + static const UNITY_INT32 max_scaled = 10000000; +#endif + + UNITY_DOUBLE number = input_number; + + /* print minus sign (does not handle negative zero) */ + if (number < 0.0f) + { + UNITY_OUTPUT_CHAR('-'); + number = -number; + } + + /* handle zero, NaN, and +/- infinity */ + if (number == 0.0f) + { + UnityPrint("0"); + } + else if (isnan(number)) + { + UnityPrint("nan"); + } + else if (isinf(number)) + { + UnityPrint("inf"); + } + else + { + UNITY_INT32 n_int = 0; + UNITY_INT32 n; + int exponent = 0; + int decimals; + int digits; + char buf[16] = {0}; + + /* + * Scale up or down by powers of 10. To minimize rounding error, + * start with a factor/divisor of 10^10, which is the largest + * power of 10 that can be represented exactly. Finally, compute + * (exactly) the remaining power of 10 and perform one more + * multiplication or division. + */ + if (number < 1.0f) + { + UNITY_DOUBLE factor = 1.0f; + + while (number < (UNITY_DOUBLE)max_scaled / 1e10f) { number *= 1e10f; exponent -= 10; } + while (number * factor < (UNITY_DOUBLE)min_scaled) { factor *= 10.0f; exponent--; } + + number *= factor; + } + else if (number > (UNITY_DOUBLE)max_scaled) + { + UNITY_DOUBLE divisor = 1.0f; + + while (number > (UNITY_DOUBLE)min_scaled * 1e10f) { number /= 1e10f; exponent += 10; } + while (number / divisor > (UNITY_DOUBLE)max_scaled) { divisor *= 10.0f; exponent++; } + + number /= divisor; + } + else + { + /* + * In this range, we can split off the integer part before + * doing any multiplications. This reduces rounding error by + * freeing up significant bits in the fractional part. + */ + UNITY_DOUBLE factor = 1.0f; + n_int = (UNITY_INT32)number; + number -= (UNITY_DOUBLE)n_int; + + while (n_int < min_scaled) { n_int *= 10; factor *= 10.0f; exponent--; } + + number *= factor; + } + + /* round to nearest integer */ + n = ((UNITY_INT32)(number + number) + 1) / 2; + +#ifndef UNITY_ROUND_TIES_AWAY_FROM_ZERO + /* round to even if exactly between two integers */ + if ((n & 1) && (((UNITY_DOUBLE)n - number) == 0.5f)) + n--; +#endif + + n += n_int; + + if (n >= max_scaled) + { + n = min_scaled; + exponent++; + } + + /* determine where to place decimal point */ + decimals = ((exponent <= 0) && (exponent >= -(sig_digits + 3))) ? (-exponent) : (sig_digits - 1); + exponent += decimals; + + /* truncate trailing zeroes after decimal point */ + while ((decimals > 0) && ((n % 10) == 0)) + { + n /= 10; + decimals--; + } + + /* build up buffer in reverse order */ + digits = 0; + while ((n != 0) || (digits <= decimals)) + { + buf[digits++] = (char)('0' + n % 10); + n /= 10; + } + + /* print out buffer (backwards) */ + while (digits > 0) + { + if (digits == decimals) + { + UNITY_OUTPUT_CHAR('.'); + } + UNITY_OUTPUT_CHAR(buf[--digits]); + } + + /* print exponent if needed */ + if (exponent != 0) + { + UNITY_OUTPUT_CHAR('e'); + + if (exponent < 0) + { + UNITY_OUTPUT_CHAR('-'); + exponent = -exponent; + } + else + { + UNITY_OUTPUT_CHAR('+'); + } + + digits = 0; + while ((exponent != 0) || (digits < 2)) + { + buf[digits++] = (char)('0' + exponent % 10); + exponent /= 10; + } + while (digits > 0) + { + UNITY_OUTPUT_CHAR(buf[--digits]); + } + } + } +} +#endif /* ! UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static void UnityTestResultsBegin(const char* file, const UNITY_LINE_TYPE line) +{ +#ifdef UNITY_OUTPUT_FOR_ECLIPSE + UNITY_OUTPUT_CHAR('('); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(')'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else +#ifdef UNITY_OUTPUT_FOR_IAR_WORKBENCH + UnityPrint("'); + UnityPrint(Unity.CurrentTestName); + UnityPrint(" "); +#else +#ifdef UNITY_OUTPUT_FOR_QT_CREATOR + UnityPrint("file://"); + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#else + UnityPrint(file); + UNITY_OUTPUT_CHAR(':'); + UnityPrintNumber((UNITY_INT)line); + UNITY_OUTPUT_CHAR(':'); + UnityPrint(Unity.CurrentTestName); + UNITY_OUTPUT_CHAR(':'); +#endif +#endif +#endif +} + +/*-----------------------------------------------*/ +static void UnityTestResultsFailBegin(const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + UNITY_OUTPUT_CHAR(':'); +} + +/*-----------------------------------------------*/ +void UnityConcludeTest(void) +{ + if (Unity.CurrentTestIgnored) + { + Unity.TestIgnores++; + } + else if (!Unity.CurrentTestFailed) + { + UnityTestResultsBegin(Unity.TestFile, Unity.CurrentTestLineNumber); + UnityPrint(UnityStrPass); + } + else + { + Unity.TestFailures++; + } + + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + UNITY_PRINT_EXEC_TIME(); + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); +} + +/*-----------------------------------------------*/ +static void UnityAddMsgIfSpecified(const char* msg) +{ +#ifdef UNITY_PRINT_TEST_CONTEXT + UnityPrint(UnityStrSpacer); + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrSpacer); + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + } +#endif + if (msg) + { + UnityPrint(UnityStrSpacer); + UnityPrint(msg); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStrings(const char* expected, const char* actual) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(expected); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrint(actual); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*-----------------------------------------------*/ +static void UnityPrintExpectedAndActualStringsLen(const char* expected, + const char* actual, + const UNITY_UINT32 length) +{ + UnityPrint(UnityStrExpected); + if (expected != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(expected, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } + UnityPrint(UnityStrWas); + if (actual != NULL) + { + UNITY_OUTPUT_CHAR('\''); + UnityPrintLen(actual, length); + UNITY_OUTPUT_CHAR('\''); + } + else + { + UnityPrint(UnityStrNull); + } +} + +/*----------------------------------------------- + * Assertion & Control Helpers + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +static int UnityIsOneArrayNull(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_LINE_TYPE lineNumber, + const char* msg) +{ + /* Both are NULL or same pointer */ + if (expected == actual) { return 0; } + + /* print and return true if just expected is NULL */ + if (expected == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForExpected); + UnityAddMsgIfSpecified(msg); + return 1; + } + + /* print and return true if just actual is NULL */ + if (actual == NULL) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrNullPointerForActual); + UnityAddMsgIfSpecified(msg); + return 1; + } + + return 0; /* return false if neither is NULL */ +} + +/*----------------------------------------------- + * Assertion Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((mask & expected) != (mask & actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)expected); + UnityPrint(UnityStrWas); + UnityPrintMask((UNITY_UINT)mask, (UNITY_UINT)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (expected != actual) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + int failed = 0; + RETURN_IF_FAIL_OR_IGNORE; + + if ((threshold == actual) && (compare & UNITY_EQUAL_TO)) { return; } + if ((threshold == actual)) { failed = 1; } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if ((actual > threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if ((actual < threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + else /* UINT or HEX */ + { + if (((UNITY_UINT)actual > (UNITY_UINT)threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (((UNITY_UINT)actual < (UNITY_UINT)threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(actual, style); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + if (compare == UNITY_NOT_EQUAL) { UnityPrint(UnityStrNotEqual); } + UnityPrintNumberByStyle(threshold, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#define UnityPrintPointlessAndBail() \ +do { \ + UnityTestResultsFailBegin(lineNumber); \ + UnityPrint(UnityStrPointless); \ + UnityAddMsgIfSpecified(msg); \ + UNITY_FAIL_AND_BAIL; \ +} while (0) + +/*-----------------------------------------------*/ +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x000000FF; + actual_val &= 0x000000FF; + } + increment = sizeof(UNITY_INT8); + break; + + case 2: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x0000FFFF; + actual_val &= 0x0000FFFF; + } + increment = sizeof(UNITY_INT16); + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; +#ifdef UNITY_SUPPORT_64 + if (style & (UNITY_DISPLAY_RANGE_UINT | UNITY_DISPLAY_RANGE_HEX)) + { + expect_val &= 0x00000000FFFFFFFF; + actual_val &= 0x00000000FFFFFFFF; + } +#endif + increment = sizeof(UNITY_INT32); + length = 4; + break; + } + + if (expect_val != actual_val) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_FLOAT +/* Wrap this define in a function with variable types as float or double */ +#define UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff) \ + if (isinf(expected) && isinf(actual) && (((expected) < 0) == ((actual) < 0))) return 1; \ + if (UNITY_NAN_CHECK) return 1; \ + (diff) = (actual) - (expected); \ + if ((diff) < 0) (diff) = -(diff); \ + if ((delta) < 0) (delta) = -(delta); \ + return !(isnan(diff) || isinf(diff) || ((diff) > (delta))) + /* This first part of this condition will catch any NaN or Infinite values */ +#ifndef UNITY_NAN_NOT_EQUAL_NAN + #define UNITY_NAN_CHECK isnan(expected) && isnan(actual) +#else + #define UNITY_NAN_CHECK 0 +#endif + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + do { \ + UnityPrint(UnityStrExpected); \ + UnityPrintFloat(expected); \ + UnityPrint(UnityStrWas); \ + UnityPrintFloat(actual); \ + } while (0) +#else + #define UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual) \ + UnityPrint(UnityStrDelta) +#endif /* UNITY_EXCLUDE_FLOAT_PRINT */ + +/*-----------------------------------------------*/ +static int UnityFloatsWithin(UNITY_FLOAT delta, UNITY_FLOAT expected, UNITY_FLOAT actual) +{ + UNITY_FLOAT diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* ptr_actual = actual; + UNITY_FLOAT in_delta = delta; + UNITY_FLOAT current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (isinf(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (isnan(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_FLOAT_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityFloatsWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)*ptr_expected, (UNITY_DOUBLE)*ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + + if (!UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT((UNITY_DOUBLE)expected, (UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityFloatsWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityFloatsWithin(threshold * UNITY_FLOAT_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !isinf(actual) && !isnan(actual); + break; + + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat((UNITY_DOUBLE)actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_FLOAT */ + +/*-----------------------------------------------*/ +#ifndef UNITY_EXCLUDE_DOUBLE +static int UnityDoublesWithin(UNITY_DOUBLE delta, UNITY_DOUBLE expected, UNITY_DOUBLE actual) +{ + UNITY_DOUBLE diff; + UNITY_FLOAT_OR_DOUBLE_WITHIN(delta, expected, actual, diff); +} + +/*-----------------------------------------------*/ +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_expected = expected; + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* ptr_actual = actual; + UNITY_DOUBLE in_delta = delta; + UNITY_DOUBLE current_element_delta = delta; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (isinf(in_delta)) + { + return; /* Arrays will be force equal with infinite delta */ + } + + if (isnan(in_delta)) + { + /* Delta must be correct number */ + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + /* fix delta sign if need */ + if (in_delta < 0) + { + in_delta = -in_delta; + } + + while (elements--) + { + current_element_delta = *ptr_expected * UNITY_DOUBLE_PRECISION; + + if (current_element_delta < 0) + { + /* fix delta sign for correct calculations */ + current_element_delta = -current_element_delta; + } + + if (!UnityDoublesWithin(in_delta + current_element_delta, *ptr_expected, *ptr_actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(*ptr_expected, *ptr_actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + if (flags == UNITY_ARRAY_TO_ARRAY) + { + ptr_expected++; + } + ptr_actual++; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (!UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UNITY_PRINT_EXPECTED_AND_ACTUAL_FLOAT(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if (UnityDoublesWithin(delta, expected, actual)) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat((UNITY_DOUBLE)expected); + UnityPrint(UnityStrNotEqual); + UnityPrintFloat((UNITY_DOUBLE)actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + int failed; + + RETURN_IF_FAIL_OR_IGNORE; + + failed = 0; + + /* Checking for "not success" rather than failure to get the right result for NaN */ + if (!(actual < threshold) && (compare & UNITY_SMALLER_THAN)) { failed = 1; } + if (!(actual > threshold) && (compare & UNITY_GREATER_THAN)) { failed = 1; } + + if ((compare & UNITY_EQUAL_TO) && UnityDoublesWithin(threshold * UNITY_DOUBLE_PRECISION, threshold, actual)) { failed = 0; } + + if (failed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + UnityPrintFloat(actual); + if (compare & UNITY_GREATER_THAN) { UnityPrint(UnityStrGt); } + if (compare & UNITY_SMALLER_THAN) { UnityPrint(UnityStrLt); } + if (compare & UNITY_EQUAL_TO) { UnityPrint(UnityStrOrEqual); } + UnityPrintFloat(threshold); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style) +{ + const char* trait_names[] = {UnityStrInf, UnityStrNegInf, UnityStrNaN, UnityStrDet}; + UNITY_INT should_be_trait = ((UNITY_INT)style & 1); + UNITY_INT is_trait = !should_be_trait; + UNITY_INT trait_index = (UNITY_INT)(style >> 1); + + RETURN_IF_FAIL_OR_IGNORE; + + switch (style) + { + case UNITY_FLOAT_IS_INF: + case UNITY_FLOAT_IS_NOT_INF: + is_trait = isinf(actual) && (actual > 0); + break; + case UNITY_FLOAT_IS_NEG_INF: + case UNITY_FLOAT_IS_NOT_NEG_INF: + is_trait = isinf(actual) && (actual < 0); + break; + + case UNITY_FLOAT_IS_NAN: + case UNITY_FLOAT_IS_NOT_NAN: + is_trait = isnan(actual) ? 1 : 0; + break; + + case UNITY_FLOAT_IS_DET: /* A determinate number is non infinite and not NaN. */ + case UNITY_FLOAT_IS_NOT_DET: + is_trait = !isinf(actual) && !isnan(actual); + break; + + default: /* including UNITY_FLOAT_INVALID_TRAIT */ + trait_index = 0; + trait_names[0] = UnityStrInvalidFloatTrait; + break; + } + + if (is_trait != should_be_trait) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrExpected); + if (!should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); + UnityPrint(UnityStrWas); +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + UnityPrintFloat(actual); +#else + if (should_be_trait) + { + UnityPrint(UnityStrNot); + } + UnityPrint(trait_names[trait_index]); +#endif + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +#endif /* not UNITY_EXCLUDE_DOUBLE */ + +/*-----------------------------------------------*/ +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style) +{ + RETURN_IF_FAIL_OR_IGNORE; + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual > expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + else + { + if ((UNITY_UINT)actual > (UNITY_UINT)expected) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual - (UNITY_UINT)expected) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expected - (UNITY_UINT)actual) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expected, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 elements = num_elements; + unsigned int length = style & 0xF; + unsigned int increment = 0; + + RETURN_IF_FAIL_OR_IGNORE; + + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while ((elements > 0) && (elements--)) + { + UNITY_INT expect_val; + UNITY_INT actual_val; + + switch (length) + { + case 1: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT8*)actual; + increment = sizeof(UNITY_INT8); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT8*)actual; + increment = sizeof(UNITY_UINT8); + } + break; + + case 2: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT16*)actual; + increment = sizeof(UNITY_INT16); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT16*)actual; + increment = sizeof(UNITY_UINT16); + } + break; + +#ifdef UNITY_SUPPORT_64 + case 8: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT64*)actual; + increment = sizeof(UNITY_INT64); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT64*)actual; + increment = sizeof(UNITY_UINT64); + } + break; +#endif + + default: /* default is length 4 bytes */ + case 4: + /* fixing problems with signed overflow on unsigned numbers */ + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + expect_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)expected; + actual_val = *(UNITY_PTR_ATTRIBUTE const UNITY_INT32*)actual; + increment = sizeof(UNITY_INT32); + } + else + { + expect_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)expected; + actual_val = (UNITY_INT)*(UNITY_PTR_ATTRIBUTE const UNITY_UINT32*)actual; + increment = sizeof(UNITY_UINT32); + } + length = 4; + break; + } + + if ((style & UNITY_DISPLAY_RANGE_INT) == UNITY_DISPLAY_RANGE_INT) + { + if (actual_val > expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + else + { + if ((UNITY_UINT)actual_val > (UNITY_UINT)expect_val) + { + Unity.CurrentTestFailed = (((UNITY_UINT)actual_val - (UNITY_UINT)expect_val) > delta); + } + else + { + Unity.CurrentTestFailed = (((UNITY_UINT)expect_val - (UNITY_UINT)actual_val) > delta); + } + } + + if (Unity.CurrentTestFailed) + { + if ((style & UNITY_DISPLAY_RANGE_UINT) && (length < (UNITY_INT_WIDTH / 8))) + { /* For UINT, remove sign extension (padding 1's) from signed type casts above */ + UNITY_INT mask = 1; + mask = (mask << 8 * length) - 1; + expect_val &= mask; + actual_val &= mask; + } + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrDelta); + UnityPrintNumberByStyle((UNITY_INT)delta, style); + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(expect_val, style); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(actual_val, style); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + /* Walk through array by incrementing the pointers */ + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expected = (UNITY_INTERNAL_PTR)((const char*)expected + increment); + } + actual = (UNITY_INTERNAL_PTR)((const char*)actual + increment); + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; expected[i] || actual[i]; i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStrings(expected, actual); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber) +{ + UNITY_UINT32 i; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if both pointers not null compare the strings */ + if (expected && actual) + { + for (i = 0; (i < length) && (expected[i] || actual[i]); i++) + { + if (expected[i] != actual[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expected != actual) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrintExpectedAndActualStringsLen(expected, actual, length); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } +} + +/*-----------------------------------------------*/ +void UnityAssertEqualStringArray(UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_UINT32 i = 0; + UNITY_UINT32 j = 0; + const char* expd = NULL; + const char* act = NULL; + + RETURN_IF_FAIL_OR_IGNORE; + + /* if no elements, it's an error */ + if (num_elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + + if ((const void*)expected == (const void*)actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull((UNITY_INTERNAL_PTR)expected, (UNITY_INTERNAL_PTR)actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + if (flags != UNITY_ARRAY_TO_ARRAY) + { + expd = (const char*)expected; + } + + do + { + act = actual[j]; + if (flags == UNITY_ARRAY_TO_ARRAY) + { + expd = ((const char* const*)expected)[j]; + } + + /* if both pointers not null compare the strings */ + if (expd && act) + { + for (i = 0; expd[i] || act[i]; i++) + { + if (expd[i] != act[i]) + { + Unity.CurrentTestFailed = 1; + break; + } + } + } + else + { /* handle case of one pointers being null (if both null, test should pass) */ + if (expd != act) + { + Unity.CurrentTestFailed = 1; + } + } + + if (Unity.CurrentTestFailed) + { + UnityTestResultsFailBegin(lineNumber); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(j); + } + UnityPrintExpectedAndActualStrings(expd, act); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + } while (++j < num_elements); +} + +/*-----------------------------------------------*/ +void UnityAssertEqualMemory(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags) +{ + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + UNITY_PTR_ATTRIBUTE const unsigned char* ptr_act = (UNITY_PTR_ATTRIBUTE const unsigned char*)actual; + UNITY_UINT32 elements = num_elements; + UNITY_UINT32 bytes; + + RETURN_IF_FAIL_OR_IGNORE; + + if (elements == 0) + { +#ifdef UNITY_COMPARE_PTRS_ON_ZERO_ARRAY + UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, lineNumber, msg); +#else + UnityPrintPointlessAndBail(); +#endif + } + if (length == 0) + { + UnityPrintPointlessAndBail(); + } + + if (expected == actual) + { + return; /* Both are NULL or same pointer */ + } + + if (UnityIsOneArrayNull(expected, actual, lineNumber, msg)) + { + UNITY_FAIL_AND_BAIL; + } + + while (elements--) + { + bytes = length; + while (bytes--) + { + if (*ptr_exp != *ptr_act) + { + UnityTestResultsFailBegin(lineNumber); + UnityPrint(UnityStrMemory); + if (num_elements > 1) + { + UnityPrint(UnityStrElement); + UnityPrintNumberUnsigned(num_elements - elements - 1); + } + UnityPrint(UnityStrByte); + UnityPrintNumberUnsigned(length - bytes - 1); + UnityPrint(UnityStrExpected); + UnityPrintNumberByStyle(*ptr_exp, UNITY_DISPLAY_STYLE_HEX8); + UnityPrint(UnityStrWas); + UnityPrintNumberByStyle(*ptr_act, UNITY_DISPLAY_STYLE_HEX8); + UnityAddMsgIfSpecified(msg); + UNITY_FAIL_AND_BAIL; + } + ptr_exp++; + ptr_act++; + } + if (flags == UNITY_ARRAY_TO_VAL) + { + ptr_exp = (UNITY_PTR_ATTRIBUTE const unsigned char*)expected; + } + } +} + +/*-----------------------------------------------*/ + +static union +{ + UNITY_INT8 i8; + UNITY_INT16 i16; + UNITY_INT32 i32; +#ifdef UNITY_SUPPORT_64 + UNITY_INT64 i64; +#endif +#ifndef UNITY_EXCLUDE_FLOAT + float f; +#endif +#ifndef UNITY_EXCLUDE_DOUBLE + double d; +#endif +} UnityQuickCompare; + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size) +{ + switch(size) + { + case 1: + UnityQuickCompare.i8 = (UNITY_INT8)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i8); + + case 2: + UnityQuickCompare.i16 = (UNITY_INT16)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i16); + +#ifdef UNITY_SUPPORT_64 + case 8: + UnityQuickCompare.i64 = (UNITY_INT64)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i64); +#endif + + default: /* 4 bytes */ + UnityQuickCompare.i32 = (UNITY_INT32)num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.i32); + } +} + +#ifndef UNITY_EXCLUDE_FLOAT +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num) +{ + UnityQuickCompare.f = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.f); +} +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +/*-----------------------------------------------*/ +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num) +{ + UnityQuickCompare.d = num; + return (UNITY_INTERNAL_PTR)(&UnityQuickCompare.d); +} +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED + +/*----------------------------------------------- + * printf length modifier helpers + *-----------------------------------------------*/ + +enum UnityLengthModifier { + UNITY_LENGTH_MODIFIER_NONE, + UNITY_LENGTH_MODIFIER_LONG_LONG, + UNITY_LENGTH_MODIFIER_LONG, +}; + +#define UNITY_EXTRACT_ARG(NUMBER_T, NUMBER, LENGTH_MOD, VA, ARG_T) \ +do { \ + switch (LENGTH_MOD) \ + { \ + case UNITY_LENGTH_MODIFIER_LONG_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_LONG: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, long ARG_T); \ + break; \ + } \ + case UNITY_LENGTH_MODIFIER_NONE: \ + default: \ + { \ + NUMBER = (NUMBER_T)va_arg(VA, ARG_T); \ + break; \ + } \ + } \ +} while (0) + +static enum UnityLengthModifier UnityLengthModifierGet(const char *pch, int *length) +{ + enum UnityLengthModifier length_mod; + switch (pch[0]) + { + case 'l': + { + if (pch[1] == 'l') + { + *length = 2; + length_mod = UNITY_LENGTH_MODIFIER_LONG_LONG; + } + else + { + *length = 1; + length_mod = UNITY_LENGTH_MODIFIER_LONG; + } + break; + } + case 'h': + { + // short and char are converted to int + length_mod = UNITY_LENGTH_MODIFIER_NONE; + if (pch[1] == 'h') + { + *length = 2; + } + else + { + *length = 1; + } + break; + } + case 'j': + case 'z': + case 't': + case 'L': + { + // Not supported, but should gobble up the length specifier anyway + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 1; + break; + } + default: + { + length_mod = UNITY_LENGTH_MODIFIER_NONE; + *length = 0; + } + } + return length_mod; +} + +/*----------------------------------------------- + * printf helper function + *-----------------------------------------------*/ +static void UnityPrintFVA(const char* format, va_list va) +{ + const char* pch = format; + if (pch != NULL) + { + while (*pch) + { + /* format identification character */ + if (*pch == '%') + { + pch++; + + if (pch != NULL) + { + int length_mod_size; + enum UnityLengthModifier length_mod = UnityLengthModifierGet(pch, &length_mod_size); + pch += length_mod_size; + + switch (*pch) + { + case 'd': + case 'i': + { + UNITY_INT number; + UNITY_EXTRACT_ARG(UNITY_INT, number, length_mod, va, int); + UnityPrintNumber((UNITY_INT)number); + break; + } +#ifndef UNITY_EXCLUDE_FLOAT_PRINT + case 'f': + case 'g': + { + const double number = va_arg(va, double); + UnityPrintFloat((UNITY_DOUBLE)number); + break; + } +#endif + case 'u': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UnityPrintNumberUnsigned(number); + break; + } + case 'b': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + const UNITY_UINT mask = (UNITY_UINT)0 - (UNITY_UINT)1; + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('b'); + UnityPrintMask(mask, number); + break; + } + case 'x': + case 'X': + { + UNITY_UINT number; + UNITY_EXTRACT_ARG(UNITY_UINT, number, length_mod, va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex(number, 8); + break; + } + case 'p': + { + const unsigned int number = va_arg(va, unsigned int); + UNITY_OUTPUT_CHAR('0'); + UNITY_OUTPUT_CHAR('x'); + UnityPrintNumberHex((UNITY_UINT)number, 8); + break; + } + case 'c': + { + const int ch = va_arg(va, int); + UnityPrintChar((const char *)&ch); + break; + } + case 's': + { + const char * string = va_arg(va, const char *); + UnityPrint(string); + break; + } + case '%': + { + UnityPrintChar(pch); + break; + } + default: + { + /* print the unknown format character */ + UNITY_OUTPUT_CHAR('%'); + UnityPrintChar(pch); + break; + } + } + } + } +#ifdef UNITY_OUTPUT_COLOR + /* print ANSI escape code */ + else if ((*pch == 27) && (*(pch + 1) == '[')) + { + pch += UnityPrintAnsiEscapeString(pch); + continue; + } +#endif + else if (*pch == '\n') + { + UNITY_PRINT_EOL(); + } + else + { + UnityPrintChar(pch); + } + + pch++; + } + } +} + +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if(format != NULL) + { + UnityPrint(": "); + va_list va; + va_start(va, format); + UnityPrintFVA(format, va); + va_end(va); + } + UNITY_PRINT_EOL(); +} +#endif /* ! UNITY_INCLUDE_PRINT_FORMATTED */ + + +/*----------------------------------------------- + * Control Functions + *-----------------------------------------------*/ + +/*-----------------------------------------------*/ +void UnityFail(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrFail); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + +#ifdef UNITY_PRINT_TEST_CONTEXT + UNITY_PRINT_TEST_CONTEXT(); +#endif +#ifndef UNITY_EXCLUDE_DETAILS + if (Unity.CurrentDetail1) + { + UnityPrint(UnityStrDetail1Name); + UnityPrint(Unity.CurrentDetail1); + if (Unity.CurrentDetail2) + { + UnityPrint(UnityStrDetail2Name); + UnityPrint(Unity.CurrentDetail2); + } + UnityPrint(UnityStrSpacer); + } +#endif + if (msg[0] != ' ') + { + UNITY_OUTPUT_CHAR(' '); + } + UnityPrint(msg); + } + + UNITY_FAIL_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityIgnore(const char* msg, const UNITY_LINE_TYPE line) +{ + RETURN_IF_FAIL_OR_IGNORE; + + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint(UnityStrIgnore); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_IGNORE_AND_BAIL; +} + +/*-----------------------------------------------*/ +void UnityMessage(const char* msg, const UNITY_LINE_TYPE line) +{ + UnityTestResultsBegin(Unity.TestFile, line); + UnityPrint("INFO"); + if (msg != NULL) + { + UNITY_OUTPUT_CHAR(':'); + UNITY_OUTPUT_CHAR(' '); + UnityPrint(msg); + } + UNITY_PRINT_EOL(); +} + +/*-----------------------------------------------*/ +/* If we have not defined our own test runner, then include our default test runner to make life easier */ +#ifndef UNITY_SKIP_DEFAULT_RUNNER +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum) +{ + Unity.CurrentTestName = FuncName; + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)FuncLineNum; + Unity.NumberOfTests++; + UNITY_CLR_DETAILS(); + UNITY_EXEC_TIME_START(); + if (TEST_PROTECT()) + { + setUp(); + Func(); + } + if (TEST_PROTECT()) + { + tearDown(); + } + UNITY_EXEC_TIME_STOP(); + UnityConcludeTest(); +} +#endif + +/*-----------------------------------------------*/ +void UnitySetTestFile(const char* filename) +{ + Unity.TestFile = filename; +} + +/*-----------------------------------------------*/ +void UnityBegin(const char* filename) +{ + Unity.TestFile = filename; + Unity.CurrentTestName = NULL; + Unity.CurrentTestLineNumber = 0; + Unity.NumberOfTests = 0; + Unity.TestFailures = 0; + Unity.TestIgnores = 0; + Unity.CurrentTestFailed = 0; + Unity.CurrentTestIgnored = 0; + + UNITY_CLR_DETAILS(); + UNITY_OUTPUT_START(); +} + +/*-----------------------------------------------*/ +int UnityEnd(void) +{ + UNITY_PRINT_EOL(); + UnityPrint(UnityStrBreaker); + UNITY_PRINT_EOL(); + UnityPrintNumber((UNITY_INT)(Unity.NumberOfTests)); + UnityPrint(UnityStrResultsTests); + UnityPrintNumber((UNITY_INT)(Unity.TestFailures)); + UnityPrint(UnityStrResultsFailures); + UnityPrintNumber((UNITY_INT)(Unity.TestIgnores)); + UnityPrint(UnityStrResultsIgnored); + UNITY_PRINT_EOL(); + if (Unity.TestFailures == 0U) + { + UnityPrint(UnityStrOk); + } + else + { + UnityPrint(UnityStrFail); +#ifdef UNITY_DIFFERENTIATE_FINAL_FAIL + UNITY_OUTPUT_CHAR('E'); UNITY_OUTPUT_CHAR('D'); +#endif + } + UNITY_PRINT_EOL(); + UNITY_FLUSH_CALL(); + UNITY_OUTPUT_COMPLETE(); + return (int)(Unity.TestFailures); +} + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ +#ifdef UNITY_USE_COMMAND_LINE_ARGS + +char* UnityOptionIncludeNamed = NULL; +char* UnityOptionExcludeNamed = NULL; +int UnityVerbosity = 1; + +/*-----------------------------------------------*/ +int UnityParseOptions(int argc, char** argv) +{ + int i; + UnityOptionIncludeNamed = NULL; + UnityOptionExcludeNamed = NULL; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] == '-') + { + switch (argv[i][1]) + { + case 'l': /* list tests */ + return -1; + case 'n': /* include tests with name including this string */ + case 'f': /* an alias for -n */ + if (argv[i][2] == '=') + { + UnityOptionIncludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionIncludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Include Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + case 'q': /* quiet */ + UnityVerbosity = 0; + break; + case 'v': /* verbose */ + UnityVerbosity = 2; + break; + case 'x': /* exclude tests with name including this string */ + if (argv[i][2] == '=') + { + UnityOptionExcludeNamed = &argv[i][3]; + } + else if (++i < argc) + { + UnityOptionExcludeNamed = argv[i]; + } + else + { + UnityPrint("ERROR: No Test String to Exclude Matches For"); + UNITY_PRINT_EOL(); + return 1; + } + break; + default: + UnityPrint("ERROR: Unknown Option "); + UNITY_OUTPUT_CHAR(argv[i][1]); + UNITY_PRINT_EOL(); + return 1; + } + } + } + + return 0; +} + +/*-----------------------------------------------*/ +int IsStringInBiggerString(const char* longstring, const char* shortstring) +{ + const char* lptr = longstring; + const char* sptr = shortstring; + const char* lnext = lptr; + + if (*sptr == '*') + { + return 1; + } + + while (*lptr) + { + lnext = lptr + 1; + + /* If they current bytes match, go on to the next bytes */ + while (*lptr && *sptr && (*lptr == *sptr)) + { + lptr++; + sptr++; + + /* We're done if we match the entire string or up to a wildcard */ + if (*sptr == '*') + return 1; + if (*sptr == ',') + return 1; + if (*sptr == '"') + return 1; + if (*sptr == '\'') + return 1; + if (*sptr == ':') + return 2; + if (*sptr == 0) + return 1; + } + + /* Otherwise we start in the long pointer 1 character further and try again */ + lptr = lnext; + sptr = shortstring; + } + + return 0; +} + +/*-----------------------------------------------*/ +int UnityStringArgumentMatches(const char* str) +{ + int retval; + const char* ptr1; + const char* ptr2; + const char* ptrf; + + /* Go through the options and get the substrings for matching one at a time */ + ptr1 = str; + while (ptr1[0] != 0) + { + if ((ptr1[0] == '"') || (ptr1[0] == '\'')) + { + ptr1++; + } + + /* look for the start of the next partial */ + ptr2 = ptr1; + ptrf = 0; + do + { + ptr2++; + if ((ptr2[0] == ':') && (ptr2[1] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')) + { + ptrf = &ptr2[1]; + } + } while ((ptr2[0] != 0) && (ptr2[0] != '\'') && (ptr2[0] != '"') && (ptr2[0] != ',')); + + while ((ptr2[0] != 0) && ((ptr2[0] == ':') || (ptr2[0] == '\'') || (ptr2[0] == '"') || (ptr2[0] == ','))) + { + ptr2++; + } + + /* done if complete filename match */ + retval = IsStringInBiggerString(Unity.TestFile, ptr1); + if (retval == 1) + { + return retval; + } + + /* done if testname match after filename partial match */ + if ((retval == 2) && (ptrf != 0)) + { + if (IsStringInBiggerString(Unity.CurrentTestName, ptrf)) + { + return 1; + } + } + + /* done if complete testname match */ + if (IsStringInBiggerString(Unity.CurrentTestName, ptr1) == 1) + { + return 1; + } + + ptr1 = ptr2; + } + + /* we couldn't find a match for any substrings */ + return 0; +} + +/*-----------------------------------------------*/ +int UnityTestMatches(void) +{ + /* Check if this test name matches the included test pattern */ + int retval; + if (UnityOptionIncludeNamed) + { + retval = UnityStringArgumentMatches(UnityOptionIncludeNamed); + } + else + { + retval = 1; + } + + /* Check if this test name matches the excluded test pattern */ + if (UnityOptionExcludeNamed) + { + if (UnityStringArgumentMatches(UnityOptionExcludeNamed)) + { + retval = 0; + } + } + + return retval; +} + +#endif /* UNITY_USE_COMMAND_LINE_ARGS */ +/*-----------------------------------------------*/ diff --git a/movement/lib/chirpy_tx/test/unity.h b/movement/lib/chirpy_tx/test/unity.h new file mode 100644 index 00000000..e321a1da --- /dev/null +++ b/movement/lib/chirpy_tx/test/unity.h @@ -0,0 +1,687 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_FRAMEWORK_H +#define UNITY_FRAMEWORK_H +#define UNITY + +#define UNITY_VERSION_MAJOR 2 +#define UNITY_VERSION_MINOR 5 +#define UNITY_VERSION_BUILD 4 +#define UNITY_VERSION ((UNITY_VERSION_MAJOR << 16) | (UNITY_VERSION_MINOR << 8) | UNITY_VERSION_BUILD) + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "unity_internals.h" + +/*------------------------------------------------------- + * Test Setup / Teardown + *-------------------------------------------------------*/ + +/* These functions are intended to be called before and after each test. + * If using unity directly, these will need to be provided for each test + * executable built. If you are using the test runner generator and/or + * Ceedling, these are optional. */ +void setUp(void); +void tearDown(void); + +/* These functions are intended to be called at the beginning and end of an + * entire test suite. suiteTearDown() is passed the number of tests that + * failed, and its return value becomes the exit code of main(). If using + * Unity directly, you're in charge of calling these if they are desired. + * If using Ceedling or the test runner generator, these will be called + * automatically if they exist. */ +void suiteSetUp(void); +int suiteTearDown(int num_failures); + +/*------------------------------------------------------- + * Test Reset and Verify + *-------------------------------------------------------*/ + +/* These functions are intended to be called before during tests in order + * to support complex test loops, etc. Both are NOT built into Unity. Instead + * the test runner generator will create them. resetTest will run teardown and + * setup again, verifying any end-of-test needs between. verifyTest will only + * run the verification. */ +void resetTest(void); +void verifyTest(void); + +/*------------------------------------------------------- + * Configuration Options + *------------------------------------------------------- + * All options described below should be passed as a compiler flag to all files using Unity. If you must add #defines, place them BEFORE the #include above. + + * Integers/longs/pointers + * - Unity attempts to automatically discover your integer sizes + * - define UNITY_EXCLUDE_STDINT_H to stop attempting to look in + * - define UNITY_EXCLUDE_LIMITS_H to stop attempting to look in + * - If you cannot use the automatic methods above, you can force Unity by using these options: + * - define UNITY_SUPPORT_64 + * - set UNITY_INT_WIDTH + * - set UNITY_LONG_WIDTH + * - set UNITY_POINTER_WIDTH + + * Floats + * - define UNITY_EXCLUDE_FLOAT to disallow floating point comparisons + * - define UNITY_FLOAT_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_FLOAT + * - define UNITY_FLOAT_TYPE to specify doubles instead of single precision floats + * - define UNITY_INCLUDE_DOUBLE to allow double floating point comparisons + * - define UNITY_EXCLUDE_DOUBLE to disallow double floating point comparisons (default) + * - define UNITY_DOUBLE_PRECISION to specify the precision to use when doing TEST_ASSERT_EQUAL_DOUBLE + * - define UNITY_DOUBLE_TYPE to specify something other than double + * - define UNITY_EXCLUDE_FLOAT_PRINT to trim binary size, won't print floating point values in errors + + * Output + * - by default, Unity prints to standard out with putchar. define UNITY_OUTPUT_CHAR(a) with a different function if desired + * - define UNITY_DIFFERENTIATE_FINAL_FAIL to print FAILED (vs. FAIL) at test end summary - for automated search for failure + + * Optimization + * - by default, line numbers are stored in unsigned shorts. Define UNITY_LINE_TYPE with a different type if your files are huge + * - by default, test and failure counters are unsigned shorts. Define UNITY_COUNTER_TYPE with a different type if you want to save space or have more than 65535 Tests. + + * Test Cases + * - define UNITY_SUPPORT_TEST_CASES to include the TEST_CASE macro, though really it's mostly about the runner generator script + + * Parameterized Tests + * - you'll want to create a define of TEST_CASE(...) and/or TEST_RANGE(...) which basically evaluates to nothing + + * Tests with Arguments + * - you'll want to define UNITY_USE_COMMAND_LINE_ARGS if you have the test runner passing arguments to Unity + + *------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define TEST_FAIL_MESSAGE(message) UNITY_TEST_FAIL(__LINE__, (message)) +#define TEST_FAIL() UNITY_TEST_FAIL(__LINE__, NULL) +#define TEST_IGNORE_MESSAGE(message) UNITY_TEST_IGNORE(__LINE__, (message)) +#define TEST_IGNORE() UNITY_TEST_IGNORE(__LINE__, NULL) +#define TEST_MESSAGE(message) UnityMessage((message), __LINE__) +#define TEST_ONLY() +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#define TEST_PRINTF(message, ...) UnityPrintF(__LINE__, (message), __VA_ARGS__) +#endif + +/* It is not necessary for you to call PASS. A PASS condition is assumed if nothing fails. + * This method allows you to abort a test immediately with a PASS state, ignoring the remainder of the test. */ +#define TEST_PASS() TEST_ABORT() +#define TEST_PASS_MESSAGE(message) do { UnityMessage((message), __LINE__); TEST_ABORT(); } while (0) + +/* This macro does nothing, but it is useful for build tools (like Ceedling) to make use of this to figure out + * which files should be linked to in order to perform a test. Use it like TEST_FILE("sandwiches.c") */ +#define TEST_FILE(a) + +/*------------------------------------------------------- + * Test Asserts (simple) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expression Evaluated To FALSE") +#define TEST_ASSERT_TRUE(condition) UNITY_TEST_ASSERT( (condition), __LINE__, " Expected TRUE Was FALSE") +#define TEST_ASSERT_UNLESS(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expression Evaluated To TRUE") +#define TEST_ASSERT_FALSE(condition) UNITY_TEST_ASSERT( !(condition), __LINE__, " Expected FALSE Was TRUE") +#define TEST_ASSERT_NULL(pointer) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, " Expected NULL") +#define TEST_ASSERT_NOT_NULL(pointer) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, " Expected Non-NULL") +#define TEST_ASSERT_EMPTY(pointer) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, " Expected Empty") +#define TEST_ASSERT_NOT_EMPTY(pointer) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, " Expected Non-Empty") + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t(expected, actual) UNITY_TEST_ASSERT_EQUAL_UINT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64(expected, actual) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR(expected, actual) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS(mask, expected, actual) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_HIGH(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BITS_LOW(mask, actual) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT)(0), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_HIGH(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(-1), (actual), __LINE__, NULL) +#define TEST_ASSERT_BIT_LOW(bit, actual) UNITY_TEST_ASSERT_BITS(((UNITY_UINT)1 << (bit)), (UNITY_UINT)(0), (actual), __LINE__, NULL) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_THAN(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_GREATER_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +#define TEST_ASSERT_LESS_OR_EQUAL(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR(threshold, actual) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, NULL) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_INT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_UINT64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_size_t_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX8_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX16_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX32_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_HEX64_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_CHAR_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, NULL) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_size_t_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, NULL) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR(expected, actual) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING(expected, actual) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY(expected, actual, len) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, NULL) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_size_t_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) + +/* Arrays Compared To Single Value */ +#define TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_size_t(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, NULL) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((delta), (expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, NULL) +#define TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, NULL) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, NULL) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, NULL) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, " Expected Equal") +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, " Expected Not-Equal") +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL(expected, actual) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/*------------------------------------------------------- + * Test Asserts (with additional messages) + *-------------------------------------------------------*/ + +/* Boolean */ +#define TEST_ASSERT_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_TRUE_MESSAGE(condition, message) UNITY_TEST_ASSERT( (condition), __LINE__, (message)) +#define TEST_ASSERT_UNLESS_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_FALSE_MESSAGE(condition, message) UNITY_TEST_ASSERT( !(condition), __LINE__, (message)) +#define TEST_ASSERT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NULL( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_NULL_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_NULL((pointer), __LINE__, (message)) +#define TEST_ASSERT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_EMPTY( (pointer), __LINE__, (message)) +#define TEST_ASSERT_NOT_EMPTY_MESSAGE(pointer, message) UNITY_TEST_ASSERT_NOT_EMPTY((pointer), __LINE__, (message)) + +/* Integers (of all sizes) */ +#define TEST_ASSERT_EQUAL_INT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT8((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT16( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT32( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT64( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_UINT( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX8( (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX16((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX32((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_HEX64((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_MESSAGE(mask, expected, actual, message) UNITY_TEST_ASSERT_BITS((mask), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_HIGH_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BITS_LOW_MESSAGE(mask, actual, message) UNITY_TEST_ASSERT_BITS((mask), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_HIGH_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(-1), (actual), __LINE__, (message)) +#define TEST_ASSERT_BIT_LOW_MESSAGE(bit, actual, message) UNITY_TEST_ASSERT_BITS(((UNITY_UINT32)1 << (bit)), (UNITY_UINT32)(0), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_CHAR((expected), (actual), __LINE__, (message)) + +/* Integer Not Equal To (of all sizes) */ +#define TEST_ASSERT_NOT_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + + +/* Integer Greater Than/ Less Than (of all sizes) */ +#define TEST_ASSERT_GREATER_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_THAN_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_THAN_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_GREATER_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +#define TEST_ASSERT_LESS_OR_EQUAL_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_INT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_UINT64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_size_t_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX8_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX16_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX32_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_HEX64_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_CHAR_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR((threshold), (actual), __LINE__, (message)) + +/* Integer Ranges (of all sizes) */ +#define TEST_ASSERT_INT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_INT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_INT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_UINT64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_size_t_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_UINT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX8_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX8_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX16_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX16_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX32_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX32_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_HEX64_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_HEX64_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_CHAR_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_CHAR_WITHIN((delta), (expected), (actual), __LINE__, (message)) + +/* Integer Array Ranges (of all sizes) */ +#define TEST_ASSERT_INT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_INT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_UINT64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_size_t_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX8_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX16_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX32_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_HEX64_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) +#define TEST_ASSERT_CHAR_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN((delta), (expected), (actual), num_elements, __LINE__, (message)) + + +/* Structs and Strings */ +#define TEST_ASSERT_EQUAL_PTR_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_PTR((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_STRING((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_LEN_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_STRING_LEN((expected), (actual), (len), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_MESSAGE(expected, actual, len, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((expected), (actual), (len), __LINE__, (message)) + +/* Arrays */ +#define TEST_ASSERT_EQUAL_INT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_INT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_UINT64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_size_t_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX8_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX16_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX32_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_HEX64_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_PTR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_STRING_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_MEMORY_ARRAY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_CHAR_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) + +/* Arrays Compared To Single Value*/ +#define TEST_ASSERT_EACH_EQUAL_INT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_INT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_INT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_UINT64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_size_t_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_UINT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX8_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX8((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX16_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX16((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX32_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX32((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_HEX64_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_HEX64((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_PTR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_PTR((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_STRING_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_STRING((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_MEMORY_MESSAGE(expected, actual, len, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY((expected), (actual), (len), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_CHAR_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_CHAR((expected), (actual), (num_elements), __LINE__, (message)) + +/* Floating Point (If Enabled) */ +#define TEST_ASSERT_FLOAT_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_FLOAT_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_FLOAT_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_FLOAT_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_FLOAT_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Double (If Enabled) */ +#define TEST_ASSERT_DOUBLE_WITHIN_MESSAGE(delta, expected, actual, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((delta), (expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_DOUBLE_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_ARRAY_WITHIN_MESSAGE(delta, expected, actual, num_elements, message) UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN((delta), (expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EQUAL_DOUBLE_ARRAY_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_EACH_EQUAL_DOUBLE_MESSAGE(expected, actual, num_elements, message) UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE((expected), (actual), (num_elements), __LINE__, (message)) +#define TEST_ASSERT_GREATER_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_THAN_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_THAN_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_LESS_OR_EQUAL_DOUBLE_MESSAGE(threshold, actual, message) UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE((threshold), (actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_NAN_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN((actual), __LINE__, (message)) +#define TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE_MESSAGE(actual, message) UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE((actual), __LINE__, (message)) + +/* Shorthand */ +#ifdef UNITY_SHORTHAND_AS_OLD +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, (message)) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, (message)) +#endif +#ifdef UNITY_SHORTHAND_AS_INT +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_INT((expected), (actual), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_MEM +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT_EQUAL_MEMORY((&expected), (&actual), sizeof(expected), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif +#ifdef UNITY_SHORTHAND_AS_RAW +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) == (actual)), __LINE__, message) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_ASSERT(((expected) != (actual)), __LINE__, message) +#endif +#ifdef UNITY_SHORTHAND_AS_NONE +#define TEST_ASSERT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#define TEST_ASSERT_NOT_EQUAL_MESSAGE(expected, actual, message) UNITY_TEST_FAIL(__LINE__, UnityStrErrShorthand) +#endif + +/* end of UNITY_FRAMEWORK_H */ +#ifdef __cplusplus +} +#endif +#endif diff --git a/movement/lib/chirpy_tx/test/unity_internals.h b/movement/lib/chirpy_tx/test/unity_internals.h new file mode 100644 index 00000000..47bd370d --- /dev/null +++ b/movement/lib/chirpy_tx/test/unity_internals.h @@ -0,0 +1,1145 @@ +/* ========================================== + Unity Project - A Test Framework for C + Copyright (c) 2007-21 Mike Karlesky, Mark VanderVoord, Greg Williams + [Released under MIT License. Please refer to license.txt for details] +========================================== */ + +#ifndef UNITY_INTERNALS_H +#define UNITY_INTERNALS_H + +#ifdef UNITY_INCLUDE_CONFIG_H +#include "unity_config.h" +#endif + +#ifndef UNITY_EXCLUDE_SETJMP_H +#include +#endif + +#ifndef UNITY_EXCLUDE_MATH_H +#include +#endif + +#ifndef UNITY_EXCLUDE_STDDEF_H +#include +#endif + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +#include +#endif + +/* Unity Attempts to Auto-Detect Integer Types + * Attempt 1: UINT_MAX, ULONG_MAX in , or default to 32 bits + * Attempt 2: UINTPTR_MAX in , or default to same size as long + * The user may override any of these derived constants: + * UNITY_INT_WIDTH, UNITY_LONG_WIDTH, UNITY_POINTER_WIDTH */ +#ifndef UNITY_EXCLUDE_STDINT_H +#include +#endif + +#ifndef UNITY_EXCLUDE_LIMITS_H +#include +#endif + +#if defined(__GNUC__) || defined(__clang__) + #define UNITY_FUNCTION_ATTR(a) __attribute__((a)) +#else + #define UNITY_FUNCTION_ATTR(a) /* ignore */ +#endif + +#ifndef UNITY_NORETURN + #if defined(__cplusplus) + #if __cplusplus >= 201103L + #define UNITY_NORETURN [[ noreturn ]] + #endif + #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L + #if defined(_WIN32) && defined(_MSC_VER) + /* We are using MSVC compiler on Windows platform. */ + /* Not all Windows SDKs supports , but compiler can support C11: */ + /* https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ */ + /* Not sure, that Mingw compilers has Windows SDK headers at all. */ + #include + #endif + + /* Using Windows SDK predefined macro for detecting supported SDK with MSVC compiler. */ + /* Mingw GCC should work without that fixes. */ + /* Based on: */ + /* https://docs.microsoft.com/en-us/cpp/porting/modifying-winver-and-win32-winnt?view=msvc-170 */ + /* NTDDI_WIN10_FE is equal to Windows 10 SDK 2104 */ + #if defined(_MSC_VER) && ((!defined(NTDDI_WIN10_FE)) || WDK_NTDDI_VERSION < NTDDI_WIN10_FE) + /* Based on tests and: */ + /* https://docs.microsoft.com/en-us/cpp/c-language/noreturn?view=msvc-170 */ + /* https://en.cppreference.com/w/c/language/_Noreturn */ + #define UNITY_NORETURN _Noreturn + #else /* Using newer Windows SDK or not MSVC compiler */ + #include + #define UNITY_NORETURN noreturn + #endif + #endif +#endif +#ifndef UNITY_NORETURN + #define UNITY_NORETURN UNITY_FUNCTION_ATTR(noreturn) +#endif + +/*------------------------------------------------------- + * Guess Widths If Not Specified + *-------------------------------------------------------*/ + +/* Determine the size of an int, if not already specified. + * We cannot use sizeof(int), because it is not yet defined + * at this stage in the translation of the C program. + * Also sizeof(int) does return the size in addressable units on all platforms, + * which may not necessarily be the size in bytes. + * Therefore, infer it from UINT_MAX if possible. */ +#ifndef UNITY_INT_WIDTH + #ifdef UINT_MAX + #if (UINT_MAX == 0xFFFF) + #define UNITY_INT_WIDTH (16) + #elif (UINT_MAX == 0xFFFFFFFF) + #define UNITY_INT_WIDTH (32) + #elif (UINT_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_INT_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_INT_WIDTH (32) + #endif /* UINT_MAX */ +#endif + +/* Determine the size of a long, if not already specified. */ +#ifndef UNITY_LONG_WIDTH + #ifdef ULONG_MAX + #if (ULONG_MAX == 0xFFFF) + #define UNITY_LONG_WIDTH (16) + #elif (ULONG_MAX == 0xFFFFFFFF) + #define UNITY_LONG_WIDTH (32) + #elif (ULONG_MAX == 0xFFFFFFFFFFFFFFFF) + #define UNITY_LONG_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_LONG_WIDTH (32) + #endif /* ULONG_MAX */ +#endif + +/* Determine the size of a pointer, if not already specified. */ +#ifndef UNITY_POINTER_WIDTH + #ifdef UINTPTR_MAX + #if (UINTPTR_MAX <= 0xFFFF) + #define UNITY_POINTER_WIDTH (16) + #elif (UINTPTR_MAX <= 0xFFFFFFFF) + #define UNITY_POINTER_WIDTH (32) + #elif (UINTPTR_MAX <= 0xFFFFFFFFFFFFFFFF) + #define UNITY_POINTER_WIDTH (64) + #endif + #else /* Set to default */ + #define UNITY_POINTER_WIDTH UNITY_LONG_WIDTH + #endif /* UINTPTR_MAX */ +#endif + +/*------------------------------------------------------- + * Int Support (Define types based on detected sizes) + *-------------------------------------------------------*/ + +#if (UNITY_INT_WIDTH == 32) + typedef unsigned char UNITY_UINT8; + typedef unsigned short UNITY_UINT16; + typedef unsigned int UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed short UNITY_INT16; + typedef signed int UNITY_INT32; +#elif (UNITY_INT_WIDTH == 16) + typedef unsigned char UNITY_UINT8; + typedef unsigned int UNITY_UINT16; + typedef unsigned long UNITY_UINT32; + typedef signed char UNITY_INT8; + typedef signed int UNITY_INT16; + typedef signed long UNITY_INT32; +#else + #error Invalid UNITY_INT_WIDTH specified! (16 or 32 are supported) +#endif + +/*------------------------------------------------------- + * 64-bit Support + *-------------------------------------------------------*/ + +/* Auto-detect 64 Bit Support */ +#ifndef UNITY_SUPPORT_64 + #if UNITY_LONG_WIDTH == 64 || UNITY_POINTER_WIDTH == 64 + #define UNITY_SUPPORT_64 + #endif +#endif + +/* 64-Bit Support Dependent Configuration */ +#ifndef UNITY_SUPPORT_64 + /* No 64-bit Support */ + typedef UNITY_UINT32 UNITY_UINT; + typedef UNITY_INT32 UNITY_INT; + #define UNITY_MAX_NIBBLES (8) /* Maximum number of nibbles in a UNITY_(U)INT */ +#else + /* 64-bit Support */ + #if (UNITY_LONG_WIDTH == 32) + typedef unsigned long long UNITY_UINT64; + typedef signed long long UNITY_INT64; + #elif (UNITY_LONG_WIDTH == 64) + typedef unsigned long UNITY_UINT64; + typedef signed long UNITY_INT64; + #else + #error Invalid UNITY_LONG_WIDTH specified! (32 or 64 are supported) + #endif + typedef UNITY_UINT64 UNITY_UINT; + typedef UNITY_INT64 UNITY_INT; + #define UNITY_MAX_NIBBLES (16) /* Maximum number of nibbles in a UNITY_(U)INT */ +#endif + +/*------------------------------------------------------- + * Pointer Support + *-------------------------------------------------------*/ + +#if (UNITY_POINTER_WIDTH == 32) + #define UNITY_PTR_TO_INT UNITY_INT32 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX32 +#elif (UNITY_POINTER_WIDTH == 64) + #define UNITY_PTR_TO_INT UNITY_INT64 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX64 +#elif (UNITY_POINTER_WIDTH == 16) + #define UNITY_PTR_TO_INT UNITY_INT16 + #define UNITY_DISPLAY_STYLE_POINTER UNITY_DISPLAY_STYLE_HEX16 +#else + #error Invalid UNITY_POINTER_WIDTH specified! (16, 32 or 64 are supported) +#endif + +#ifndef UNITY_PTR_ATTRIBUTE + #define UNITY_PTR_ATTRIBUTE +#endif + +#ifndef UNITY_INTERNAL_PTR + #define UNITY_INTERNAL_PTR UNITY_PTR_ATTRIBUTE const void* +#endif + +/* optionally define UNITY_COMPARE_PTRS_ON_ZERO_ARRAY */ + +/*------------------------------------------------------- + * Float Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_FLOAT + +/* No Floating Point Support */ +#ifndef UNITY_EXCLUDE_DOUBLE +#define UNITY_EXCLUDE_DOUBLE /* Remove double when excluding float support */ +#endif +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +#define UNITY_EXCLUDE_FLOAT_PRINT +#endif + +#else + +/* Floating Point Support */ +#ifndef UNITY_FLOAT_PRECISION +#define UNITY_FLOAT_PRECISION (0.00001f) +#endif +#ifndef UNITY_FLOAT_TYPE +#define UNITY_FLOAT_TYPE float +#endif +typedef UNITY_FLOAT_TYPE UNITY_FLOAT; + +/* isinf & isnan macros should be provided by math.h */ +#ifndef isinf +/* The value of Inf - Inf is NaN */ +#define isinf(n) (isnan((n) - (n)) && !isnan(n)) +#endif + +#ifndef isnan +/* NaN is the only floating point value that does NOT equal itself. + * Therefore if n != n, then it is NaN. */ +#define isnan(n) ((n != n) ? 1 : 0) +#endif + +#endif + +/*------------------------------------------------------- + * Double Float Support + *-------------------------------------------------------*/ + +/* unlike float, we DON'T include by default */ +#if defined(UNITY_EXCLUDE_DOUBLE) || !defined(UNITY_INCLUDE_DOUBLE) + + /* No Floating Point Support */ + #ifndef UNITY_EXCLUDE_DOUBLE + #define UNITY_EXCLUDE_DOUBLE + #else + #undef UNITY_INCLUDE_DOUBLE + #endif + + #ifndef UNITY_EXCLUDE_FLOAT + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_FLOAT UNITY_DOUBLE; + /* For parameter in UnityPrintFloat(UNITY_DOUBLE), which aliases to double or float */ + #endif + +#else + + /* Double Floating Point Support */ + #ifndef UNITY_DOUBLE_PRECISION + #define UNITY_DOUBLE_PRECISION (1e-12) + #endif + + #ifndef UNITY_DOUBLE_TYPE + #define UNITY_DOUBLE_TYPE double + #endif + typedef UNITY_DOUBLE_TYPE UNITY_DOUBLE; + +#endif + +/*------------------------------------------------------- + * Output Method: stdout (DEFAULT) + *-------------------------------------------------------*/ +#ifndef UNITY_OUTPUT_CHAR + /* Default to using putchar, which is defined in stdio.h */ + #include + #define UNITY_OUTPUT_CHAR(a) (void)putchar(a) +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_CHAR_HEADER_DECLARATION + extern void UNITY_OUTPUT_CHAR_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH + #ifdef UNITY_USE_FLUSH_STDOUT + /* We want to use the stdout flush utility */ + #include + #define UNITY_OUTPUT_FLUSH() (void)fflush(stdout) + #else + /* We've specified nothing, therefore flush should just be ignored */ + #define UNITY_OUTPUT_FLUSH() (void)0 + #endif +#else + /* If defined as something else, make sure we declare it here so it's ready for use */ + #ifdef UNITY_OUTPUT_FLUSH_HEADER_DECLARATION + extern void UNITY_OUTPUT_FLUSH_HEADER_DECLARATION; + #endif +#endif + +#ifndef UNITY_OUTPUT_FLUSH +#define UNITY_FLUSH_CALL() +#else +#define UNITY_FLUSH_CALL() UNITY_OUTPUT_FLUSH() +#endif + +#ifndef UNITY_PRINT_EOL +#define UNITY_PRINT_EOL() UNITY_OUTPUT_CHAR('\n') +#endif + +#ifndef UNITY_OUTPUT_START +#define UNITY_OUTPUT_START() +#endif + +#ifndef UNITY_OUTPUT_COMPLETE +#define UNITY_OUTPUT_COMPLETE() +#endif + +#ifdef UNITY_INCLUDE_EXEC_TIME + #if !defined(UNITY_EXEC_TIME_START) && \ + !defined(UNITY_EXEC_TIME_STOP) && \ + !defined(UNITY_PRINT_EXEC_TIME) && \ + !defined(UNITY_TIME_TYPE) + /* If none any of these macros are defined then try to provide a default implementation */ + + #if defined(UNITY_CLOCK_MS) + /* This is a simple way to get a default implementation on platforms that support getting a millisecond counter */ + #define UNITY_TIME_TYPE UNITY_UINT + #define UNITY_EXEC_TIME_START() Unity.CurrentTestStartTime = UNITY_CLOCK_MS() + #define UNITY_EXEC_TIME_STOP() Unity.CurrentTestStopTime = UNITY_CLOCK_MS() + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(_WIN32) + #include + #define UNITY_TIME_TYPE clock_t + #define UNITY_GET_TIME(t) t = (clock_t)((clock() * 1000) / CLOCKS_PER_SEC) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = (Unity.CurrentTestStopTime - Unity.CurrentTestStartTime); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #elif defined(__unix__) || defined(__APPLE__) + #include + #define UNITY_TIME_TYPE struct timespec + #define UNITY_GET_TIME(t) clock_gettime(CLOCK_MONOTONIC, &t) + #define UNITY_EXEC_TIME_START() UNITY_GET_TIME(Unity.CurrentTestStartTime) + #define UNITY_EXEC_TIME_STOP() UNITY_GET_TIME(Unity.CurrentTestStopTime) + #define UNITY_PRINT_EXEC_TIME() { \ + UNITY_UINT execTimeMs = ((Unity.CurrentTestStopTime.tv_sec - Unity.CurrentTestStartTime.tv_sec) * 1000L); \ + execTimeMs += ((Unity.CurrentTestStopTime.tv_nsec - Unity.CurrentTestStartTime.tv_nsec) / 1000000L); \ + UnityPrint(" ("); \ + UnityPrintNumberUnsigned(execTimeMs); \ + UnityPrint(" ms)"); \ + } + #endif + #endif +#endif + +#ifndef UNITY_EXEC_TIME_START +#define UNITY_EXEC_TIME_START() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_EXEC_TIME_STOP +#define UNITY_EXEC_TIME_STOP() do { /* nothing*/ } while (0) +#endif + +#ifndef UNITY_TIME_TYPE +#define UNITY_TIME_TYPE UNITY_UINT +#endif + +#ifndef UNITY_PRINT_EXEC_TIME +#define UNITY_PRINT_EXEC_TIME() do { /* nothing*/ } while (0) +#endif + +/*------------------------------------------------------- + * Footprint + *-------------------------------------------------------*/ + +#ifndef UNITY_LINE_TYPE +#define UNITY_LINE_TYPE UNITY_UINT +#endif + +#ifndef UNITY_COUNTER_TYPE +#define UNITY_COUNTER_TYPE UNITY_UINT +#endif + +/*------------------------------------------------------- + * Internal Structs Needed + *-------------------------------------------------------*/ + +typedef void (*UnityTestFunction)(void); + +#define UNITY_DISPLAY_RANGE_INT (0x10) +#define UNITY_DISPLAY_RANGE_UINT (0x20) +#define UNITY_DISPLAY_RANGE_HEX (0x40) +#define UNITY_DISPLAY_RANGE_CHAR (0x80) + +typedef enum +{ + UNITY_DISPLAY_STYLE_INT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT8 = 1 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT16 = 2 + UNITY_DISPLAY_RANGE_INT, + UNITY_DISPLAY_STYLE_INT32 = 4 + UNITY_DISPLAY_RANGE_INT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_INT64 = 8 + UNITY_DISPLAY_RANGE_INT, +#endif + + UNITY_DISPLAY_STYLE_UINT = (UNITY_INT_WIDTH / 8) + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT8 = 1 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT16 = 2 + UNITY_DISPLAY_RANGE_UINT, + UNITY_DISPLAY_STYLE_UINT32 = 4 + UNITY_DISPLAY_RANGE_UINT, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_UINT64 = 8 + UNITY_DISPLAY_RANGE_UINT, +#endif + + UNITY_DISPLAY_STYLE_HEX8 = 1 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX16 = 2 + UNITY_DISPLAY_RANGE_HEX, + UNITY_DISPLAY_STYLE_HEX32 = 4 + UNITY_DISPLAY_RANGE_HEX, +#ifdef UNITY_SUPPORT_64 + UNITY_DISPLAY_STYLE_HEX64 = 8 + UNITY_DISPLAY_RANGE_HEX, +#endif + + UNITY_DISPLAY_STYLE_CHAR = 1 + UNITY_DISPLAY_RANGE_CHAR + UNITY_DISPLAY_RANGE_INT, + + UNITY_DISPLAY_STYLE_UNKNOWN +} UNITY_DISPLAY_STYLE_T; + +typedef enum +{ + UNITY_WITHIN = 0x0, + UNITY_EQUAL_TO = 0x1, + UNITY_GREATER_THAN = 0x2, + UNITY_GREATER_OR_EQUAL = 0x2 + UNITY_EQUAL_TO, + UNITY_SMALLER_THAN = 0x4, + UNITY_SMALLER_OR_EQUAL = 0x4 + UNITY_EQUAL_TO, + UNITY_NOT_EQUAL = 0x0, + UNITY_UNKNOWN +} UNITY_COMPARISON_T; + +#ifndef UNITY_EXCLUDE_FLOAT +typedef enum UNITY_FLOAT_TRAIT +{ + UNITY_FLOAT_IS_NOT_INF = 0, + UNITY_FLOAT_IS_INF, + UNITY_FLOAT_IS_NOT_NEG_INF, + UNITY_FLOAT_IS_NEG_INF, + UNITY_FLOAT_IS_NOT_NAN, + UNITY_FLOAT_IS_NAN, + UNITY_FLOAT_IS_NOT_DET, + UNITY_FLOAT_IS_DET, + UNITY_FLOAT_INVALID_TRAIT +} UNITY_FLOAT_TRAIT_T; +#endif + +typedef enum +{ + UNITY_ARRAY_TO_VAL = 0, + UNITY_ARRAY_TO_ARRAY, + UNITY_ARRAY_UNKNOWN +} UNITY_FLAGS_T; + +struct UNITY_STORAGE_T +{ + const char* TestFile; + const char* CurrentTestName; +#ifndef UNITY_EXCLUDE_DETAILS + const char* CurrentDetail1; + const char* CurrentDetail2; +#endif + UNITY_LINE_TYPE CurrentTestLineNumber; + UNITY_COUNTER_TYPE NumberOfTests; + UNITY_COUNTER_TYPE TestFailures; + UNITY_COUNTER_TYPE TestIgnores; + UNITY_COUNTER_TYPE CurrentTestFailed; + UNITY_COUNTER_TYPE CurrentTestIgnored; +#ifdef UNITY_INCLUDE_EXEC_TIME + UNITY_TIME_TYPE CurrentTestStartTime; + UNITY_TIME_TYPE CurrentTestStopTime; +#endif +#ifndef UNITY_EXCLUDE_SETJMP_H + jmp_buf AbortFrame; +#endif +}; + +extern struct UNITY_STORAGE_T Unity; + +/*------------------------------------------------------- + * Test Suite Management + *-------------------------------------------------------*/ + +void UnityBegin(const char* filename); +int UnityEnd(void); +void UnitySetTestFile(const char* filename); +void UnityConcludeTest(void); + +#ifndef RUN_TEST +void UnityDefaultTestRun(UnityTestFunction Func, const char* FuncName, const int FuncLineNum); +#else +#define UNITY_SKIP_DEFAULT_RUNNER +#endif + +/*------------------------------------------------------- + * Details Support + *-------------------------------------------------------*/ + +#ifdef UNITY_EXCLUDE_DETAILS +#define UNITY_CLR_DETAILS() +#define UNITY_SET_DETAIL(d1) +#define UNITY_SET_DETAILS(d1,d2) +#else +#define UNITY_CLR_DETAILS() do { Unity.CurrentDetail1 = 0; Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAIL(d1) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = 0; } while (0) +#define UNITY_SET_DETAILS(d1,d2) do { Unity.CurrentDetail1 = (d1); Unity.CurrentDetail2 = (d2); } while (0) + +#ifndef UNITY_DETAIL1_NAME +#define UNITY_DETAIL1_NAME "Function" +#endif + +#ifndef UNITY_DETAIL2_NAME +#define UNITY_DETAIL2_NAME "Argument" +#endif +#endif + +#ifdef UNITY_PRINT_TEST_CONTEXT +void UNITY_PRINT_TEST_CONTEXT(void); +#endif + +/*------------------------------------------------------- + * Test Output + *-------------------------------------------------------*/ + +void UnityPrint(const char* string); + +#ifdef UNITY_INCLUDE_PRINT_FORMATTED +void UnityPrintF(const UNITY_LINE_TYPE line, const char* format, ...); +#endif + +void UnityPrintLen(const char* string, const UNITY_UINT32 length); +void UnityPrintMask(const UNITY_UINT mask, const UNITY_UINT number); +void UnityPrintNumberByStyle(const UNITY_INT number, const UNITY_DISPLAY_STYLE_T style); +void UnityPrintNumber(const UNITY_INT number_to_print); +void UnityPrintNumberUnsigned(const UNITY_UINT number); +void UnityPrintNumberHex(const UNITY_UINT number, const char nibbles_to_print); + +#ifndef UNITY_EXCLUDE_FLOAT_PRINT +void UnityPrintFloat(const UNITY_DOUBLE input_number); +#endif + +/*------------------------------------------------------- + * Test Assertion Functions + *------------------------------------------------------- + * Use the macros below this section instead of calling + * these directly. The macros have a consistent naming + * convention and will pull in file and line information + * for you. */ + +void UnityAssertEqualNumber(const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertGreaterOrLessOrEqualNumber(const UNITY_INT threshold, + const UNITY_INT actual, + const UNITY_COMPARISON_T compare, + const char *msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertEqualIntArray(UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +void UnityAssertBits(const UNITY_INT mask, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualString(const char* expected, + const char* actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringLen(const char* expected, + const char* actual, + const UNITY_UINT32 length, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertEqualStringArray( UNITY_INTERNAL_PTR expected, + const char** actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertEqualMemory( UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 length, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertNumbersWithin(const UNITY_UINT delta, + const UNITY_INT expected, + const UNITY_INT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style); + +void UnityAssertNumbersArrayWithin(const UNITY_UINT delta, + UNITY_INTERNAL_PTR expected, + UNITY_INTERNAL_PTR actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_DISPLAY_STYLE_T style, + const UNITY_FLAGS_T flags); + +#ifndef UNITY_EXCLUDE_SETJMP_H +UNITY_NORETURN void UnityFail(const char* message, const UNITY_LINE_TYPE line); +UNITY_NORETURN void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#else +void UnityFail(const char* message, const UNITY_LINE_TYPE line); +void UnityIgnore(const char* message, const UNITY_LINE_TYPE line); +#endif + +void UnityMessage(const char* message, const UNITY_LINE_TYPE line); + +#ifndef UNITY_EXCLUDE_FLOAT +void UnityAssertFloatsWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertFloatsNotWithin(const UNITY_FLOAT delta, + const UNITY_FLOAT expected, + const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessFloat(const UNITY_FLOAT threshold, + const UNITY_FLOAT actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinFloatArray(const UNITY_FLOAT delta, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* expected, + UNITY_PTR_ATTRIBUTE const UNITY_FLOAT* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertFloatSpecial(const UNITY_FLOAT actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +#ifndef UNITY_EXCLUDE_DOUBLE +void UnityAssertDoublesWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertDoublesNotWithin(const UNITY_DOUBLE delta, + const UNITY_DOUBLE expected, + const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber); + +void UnityAssertGreaterOrLessDouble(const UNITY_DOUBLE threshold, + const UNITY_DOUBLE actual, + const UNITY_COMPARISON_T compare, + const char* msg, + const UNITY_LINE_TYPE linenumber); + +void UnityAssertWithinDoubleArray(const UNITY_DOUBLE delta, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* expected, + UNITY_PTR_ATTRIBUTE const UNITY_DOUBLE* actual, + const UNITY_UINT32 num_elements, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLAGS_T flags); + +void UnityAssertDoubleSpecial(const UNITY_DOUBLE actual, + const char* msg, + const UNITY_LINE_TYPE lineNumber, + const UNITY_FLOAT_TRAIT_T style); +#endif + +/*------------------------------------------------------- + * Helpers + *-------------------------------------------------------*/ + +UNITY_INTERNAL_PTR UnityNumToPtr(const UNITY_INT num, const UNITY_UINT8 size); +#ifndef UNITY_EXCLUDE_FLOAT +UNITY_INTERNAL_PTR UnityFloatToPtr(const float num); +#endif +#ifndef UNITY_EXCLUDE_DOUBLE +UNITY_INTERNAL_PTR UnityDoubleToPtr(const double num); +#endif + +/*------------------------------------------------------- + * Error Strings We Might Need + *-------------------------------------------------------*/ + +extern const char UnityStrOk[]; +extern const char UnityStrPass[]; +extern const char UnityStrFail[]; +extern const char UnityStrIgnore[]; + +extern const char UnityStrErrFloat[]; +extern const char UnityStrErrDouble[]; +extern const char UnityStrErr64[]; +extern const char UnityStrErrShorthand[]; + +/*------------------------------------------------------- + * Test Running Macros + *-------------------------------------------------------*/ + +#ifndef UNITY_EXCLUDE_SETJMP_H +#define TEST_PROTECT() (setjmp(Unity.AbortFrame) == 0) +#define TEST_ABORT() longjmp(Unity.AbortFrame, 1) +#else +#define TEST_PROTECT() 1 +#define TEST_ABORT() return +#endif + +/* Automatically enable variadic macros support, if it not enabled before */ +#ifndef UNITY_SUPPORT_VARIADIC_MACROS + #ifdef __STDC_VERSION__ + #if __STDC_VERSION__ >= 199901L + #define UNITY_SUPPORT_VARIADIC_MACROS + #endif + #endif +#endif + +/* This tricky series of macros gives us an optional line argument to treat it as RUN_TEST(func, num=__LINE__) */ +#ifndef RUN_TEST +#ifdef UNITY_SUPPORT_VARIADIC_MACROS +#define RUN_TEST(...) RUN_TEST_AT_LINE(__VA_ARGS__, __LINE__, throwaway) +#define RUN_TEST_AT_LINE(func, line, ...) UnityDefaultTestRun(func, #func, line) +#endif +#endif + +/* Enable default macros for masking param tests test cases */ +#ifdef UNITY_SUPPORT_TEST_CASES + #ifdef UNITY_SUPPORT_VARIADIC_MACROS + #if !defined(TEST_CASE) && !defined(UNITY_EXCLUDE_TEST_CASE) + #define TEST_CASE(...) + #endif + #if !defined(TEST_RANGE) && !defined(UNITY_EXCLUDE_TEST_RANGE) + #define TEST_RANGE(...) + #endif + #endif +#endif + +/* If we can't do the tricky version, we'll just have to require them to always include the line number */ +#ifndef RUN_TEST +#ifdef CMOCK +#define RUN_TEST(func, num) UnityDefaultTestRun(func, #func, num) +#else +#define RUN_TEST(func) UnityDefaultTestRun(func, #func, __LINE__) +#endif +#endif + +#define TEST_LINE_NUM (Unity.CurrentTestLineNumber) +#define TEST_IS_IGNORED (Unity.CurrentTestIgnored) +#define UNITY_NEW_TEST(a) \ + Unity.CurrentTestName = (a); \ + Unity.CurrentTestLineNumber = (UNITY_LINE_TYPE)(__LINE__); \ + Unity.NumberOfTests++; + +#ifndef UNITY_BEGIN +#define UNITY_BEGIN() UnityBegin(__FILE__) +#endif + +#ifndef UNITY_END +#define UNITY_END() UnityEnd() +#endif + +#ifndef UNITY_SHORTHAND_AS_INT +#ifndef UNITY_SHORTHAND_AS_MEM +#ifndef UNITY_SHORTHAND_AS_NONE +#ifndef UNITY_SHORTHAND_AS_RAW +#define UNITY_SHORTHAND_AS_OLD +#endif +#endif +#endif +#endif + +/*----------------------------------------------- + * Command Line Argument Support + *-----------------------------------------------*/ + +#ifdef UNITY_USE_COMMAND_LINE_ARGS +int UnityParseOptions(int argc, char** argv); +int UnityTestMatches(void); +#endif + +/*------------------------------------------------------- + * Basic Fail and Ignore + *-------------------------------------------------------*/ + +#define UNITY_TEST_FAIL(line, message) UnityFail( (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_IGNORE(line, message) UnityIgnore( (message), (UNITY_LINE_TYPE)(line)) + +/*------------------------------------------------------- + * Test Asserts + *-------------------------------------------------------*/ + +#define UNITY_TEST_ASSERT(condition, line, message) do { if (condition) { /* nothing*/ } else { UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), (message)); } } while (0) +#define UNITY_TEST_ASSERT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) == NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_NULL(pointer, line, message) UNITY_TEST_ASSERT(((pointer) != NULL), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) == 0), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EMPTY(pointer, line, message) UNITY_TEST_ASSERT(((pointer[0]) != 0), (UNITY_LINE_TYPE)(line), (message)) + +#define UNITY_TEST_ASSERT_EQUAL_INT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_EQUAL_INT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_EQUAL_INT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_EQUAL_INT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_EQUAL_UINT(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_EQUAL_UINT8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_EQUAL_UINT16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_EQUAL_UINT32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_EQUAL_HEX8(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_EQUAL_HEX16(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT16)(expected), (UNITY_INT)(UNITY_INT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_EQUAL_HEX32(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT32)(expected), (UNITY_INT)(UNITY_INT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_EQUAL_CHAR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(UNITY_INT8 )(expected), (UNITY_INT)(UNITY_INT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) +#define UNITY_TEST_ASSERT_BITS(mask, expected, actual, line, message) UnityAssertBits((UNITY_INT)(mask), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line)) + +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_NOT_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_THAN_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 )(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16) (threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32) (threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 ) (threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT16)(threshold), (UNITY_INT)(UNITY_INT16) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT32)(threshold), (UNITY_INT)(UNITY_INT32) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT) (threshold), (UNITY_INT) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX8(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT8 )(threshold), (UNITY_INT)(UNITY_UINT8 )(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX16(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT16)(threshold), (UNITY_INT)(UNITY_UINT16)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX32(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_UINT32)(threshold), (UNITY_INT)(UNITY_UINT32)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_CHAR(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(UNITY_INT8 )(threshold), (UNITY_INT)(UNITY_INT8 ) (actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT) +#define UNITY_TEST_ASSERT_INT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8) +#define UNITY_TEST_ASSERT_INT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_INT16) (expected), (UNITY_INT)(UNITY_INT16) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16) +#define UNITY_TEST_ASSERT_INT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_INT32) (expected), (UNITY_INT)(UNITY_INT32) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32) +#define UNITY_TEST_ASSERT_UINT_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin( (delta), (UNITY_INT) (expected), (UNITY_INT) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT) +#define UNITY_TEST_ASSERT_UINT8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8) +#define UNITY_TEST_ASSERT_UINT16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16) +#define UNITY_TEST_ASSERT_UINT32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32) +#define UNITY_TEST_ASSERT_HEX8_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT8 )(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8) +#define UNITY_TEST_ASSERT_HEX16_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT16)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT16)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16) +#define UNITY_TEST_ASSERT_HEX32_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT32)(delta), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(expected), (UNITY_INT)(UNITY_UINT)(UNITY_UINT32)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32) +#define UNITY_TEST_ASSERT_CHAR_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((UNITY_UINT8 )(delta), (UNITY_INT)(UNITY_INT8 ) (expected), (UNITY_INT)(UNITY_INT8 ) (actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR) + +#define UNITY_TEST_ASSERT_INT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_INT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin( (delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX8_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX16_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT16)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX32_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT32)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_CHAR_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT8 )(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), ((UNITY_UINT32)(num_elements)), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + + +#define UNITY_TEST_ASSERT_EQUAL_PTR(expected, actual, line, message) UnityAssertEqualNumber((UNITY_PTR_TO_INT)(expected), (UNITY_PTR_TO_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER) +#define UNITY_TEST_ASSERT_EQUAL_STRING(expected, actual, line, message) UnityAssertEqualString((const char*)(expected), (const char*)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_STRING_LEN(expected, actual, len, line, message) UnityAssertEqualStringLen((const char*)(expected), (const char*)(actual), (UNITY_UINT32)(len), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY(expected, actual, len, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), 1, (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EQUAL_INT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_INT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX8_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX16_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX32_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_PTR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_STRING_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_MEMORY_ARRAY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_CHAR_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_ARRAY) + +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT) (expected), (UNITY_INT_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT16)(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT32)(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX8(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX8, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX16(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT16 )(expected), 2), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX16, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX32(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT32 )(expected), 4), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX32, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_PTR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_PTR_TO_INT) (expected), (UNITY_POINTER_WIDTH / 8)), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_POINTER, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_STRING(expected, actual, num_elements, line, message) UnityAssertEqualStringArray((UNITY_INTERNAL_PTR)(expected), (const char**)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_MEMORY(expected, actual, len, num_elements, line, message) UnityAssertEqualMemory((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(len), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_CHAR(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT8 )(expected), 1), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_CHAR, UNITY_ARRAY_TO_VAL) + +#ifdef UNITY_SUPPORT_64 +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UnityAssertEqualNumber((UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UnityAssertEqualIntArray((UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_INT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_UINT64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_UINT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_EACH_EQUAL_HEX64(expected, actual, num_elements, line, message) UnityAssertEqualIntArray(UnityNumToPtr((UNITY_INT)(UNITY_INT64)(expected), 8), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UnityAssertNumbersWithin((delta), (UNITY_INT)(expected), (UNITY_INT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_NOT_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_NOT_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UnityAssertGreaterOrLessOrEqualNumber((UNITY_INT)(threshold), (UNITY_INT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_INT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_UINT64, UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertNumbersArrayWithin((UNITY_UINT64)(delta), (UNITY_INTERNAL_PTR)(expected), (UNITY_INTERNAL_PTR)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_DISPLAY_STYLE_HEX64, UNITY_ARRAY_TO_ARRAY) +#else +#define UNITY_TEST_ASSERT_EQUAL_INT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_INT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_UINT64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_EQUAL_HEX64_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_THAN_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_INT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_UINT64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_SMALLER_OR_EQUAL_HEX64(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_INT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_UINT64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#define UNITY_TEST_ASSERT_HEX64_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErr64) +#endif + +#ifdef UNITY_EXCLUDE_FLOAT +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrFloat) +#else +#define UNITY_TEST_ASSERT_FLOAT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertFloatsNotWithin((UNITY_FLOAT)(delta), (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_FLOAT(expected, actual, line, message) UNITY_TEST_ASSERT_FLOAT_NOT_WITHIN((UNITY_FLOAT)(expected) * (UNITY_FLOAT)UNITY_FLOAT_PRECISION, (UNITY_FLOAT)(expected), (UNITY_FLOAT)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_FLOAT_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)(delta), (UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_FLOAT_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, (UNITY_FLOAT*)(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_FLOAT(expected, actual, num_elements, line, message) UnityAssertWithinFloatArray((UNITY_FLOAT)0, UnityFloatToPtr(expected), (UNITY_FLOAT*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_FLOAT(threshold, actual, line, message) UnityAssertGreaterOrLessFloat((UNITY_FLOAT)(threshold), (UNITY_FLOAT)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_FLOAT_IS_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NEG_INF(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_NAN(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_FLOAT_IS_NOT_DETERMINATE(actual, line, message) UnityAssertFloatSpecial((UNITY_FLOAT)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +#ifdef UNITY_EXCLUDE_DOUBLE +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UNITY_TEST_FAIL((UNITY_LINE_TYPE)(line), UnityStrErrDouble) +#else +#define UNITY_TEST_ASSERT_DOUBLE_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN(delta, expected, actual, line, message) UnityAssertDoublesNotWithin((UNITY_DOUBLE)(delta), (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_NOT_EQUAL_DOUBLE(expected, actual, line, message) UNITY_TEST_ASSERT_DOUBLE_NOT_WITHIN((UNITY_DOUBLE)(expected) * (UNITY_DOUBLE)UNITY_DOUBLE_PRECISION, (UNITY_DOUBLE)(expected), (UNITY_DOUBLE)(actual), (UNITY_LINE_TYPE)(line), (message)) +#define UNITY_TEST_ASSERT_DOUBLE_ARRAY_WITHIN(delta, expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)(delta), (UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EQUAL_DOUBLE_ARRAY(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, (UNITY_DOUBLE*)(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_ARRAY) +#define UNITY_TEST_ASSERT_EACH_EQUAL_DOUBLE(expected, actual, num_elements, line, message) UnityAssertWithinDoubleArray((UNITY_DOUBLE)0, UnityDoubleToPtr(expected), (UNITY_DOUBLE*)(actual), (UNITY_UINT32)(num_elements), (message), (UNITY_LINE_TYPE)(line), UNITY_ARRAY_TO_VAL) +#define UNITY_TEST_ASSERT_GREATER_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_GREATER_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_GREATER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_THAN_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_THAN, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_LESS_OR_EQUAL_DOUBLE(threshold, actual, line, message) UnityAssertGreaterOrLessDouble((UNITY_DOUBLE)(threshold), (UNITY_DOUBLE)(actual), UNITY_SMALLER_OR_EQUAL, (message), (UNITY_LINE_TYPE)(line)) +#define UNITY_TEST_ASSERT_DOUBLE_IS_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_DET) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NEG_INF(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NEG_INF) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_NAN(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_NAN) +#define UNITY_TEST_ASSERT_DOUBLE_IS_NOT_DETERMINATE(actual, line, message) UnityAssertDoubleSpecial((UNITY_DOUBLE)(actual), (message), (UNITY_LINE_TYPE)(line), UNITY_FLOAT_IS_NOT_DET) +#endif + +/* End of UNITY_INTERNALS_H */ +#endif diff --git a/movement/lib/morsecalc/calc.c b/movement/lib/morsecalc/calc.c index 49b19a00..ed7eb25b 100644 --- a/movement/lib/morsecalc/calc.c +++ b/movement/lib/morsecalc/calc.c @@ -24,6 +24,7 @@ #include #include +#include #include "calc.h" #include "calc_fns.h" @@ -41,12 +42,11 @@ int calc_init(calc_state_t *cs) { } /* calc_input_function - * Try to execut the token as a calculator function - * TODO: Maybe replace this loop with binary search for token in a sorted calc_dict + * Try to execute the token as a calculator function */ int calc_input_function(calc_state_t *cs, char *token) { for(uint8_t idx=0; idxs--; return 0; } +int calc_torad(calc_state_t *cs) { + STACK_CHECK_1_IN_1_OUT; + cs->stack[cs->s-1] = cs->stack[cs->s-1]*to_rad; + return 0; +} +int calc_todeg(calc_state_t *cs) { + STACK_CHECK_1_IN_1_OUT; + cs->stack[cs->s-1] = cs->stack[cs->s-1]*to_deg; + return 0; +} diff --git a/movement/lib/morsecalc/calc_fns.h b/movement/lib/morsecalc/calc_fns.h index fd1d7aba..15f56b0e 100644 --- a/movement/lib/morsecalc/calc_fns.h +++ b/movement/lib/morsecalc/calc_fns.h @@ -67,57 +67,62 @@ int calc_asind(calc_state_t *cs); int calc_acosd(calc_state_t *cs); int calc_atand(calc_state_t *cs); int calc_atan2d(calc_state_t *cs); +int calc_torad(calc_state_t *cs); +int calc_todeg(calc_state_t *cs); // Dictionary definition typedef int (*calc_fn_t)(calc_state_t *cs); typedef struct { - char *names[3]; // Token to use to run this function + uint8_t n_names; // Number of aliases + const char ** names; // Token to use to run this function calc_fn_t fn; // Pointer to function } calc_dict_entry_t; static const calc_dict_entry_t calc_dict[] = { // Stack and register control - {{"x"}, &calc_delete}, - {{"xx"}, &calc_clear_stack}, - {{"xxx"}, &calc_init}, - {{"f"}, &calc_flip}, - {{"mc"}, &calc_mem_clear}, - {{"mr"}, &calc_mem_recall}, - {{"ma"}, &calc_mem_add}, - {{"ms"}, &calc_mem_subtract}, + {1, (const char*[]){"x"}, &calc_delete}, + {1, (const char*[]){"xx"}, &calc_clear_stack}, + {1, (const char*[]){"xxx"}, &calc_init}, + {1, (const char*[]){"f"}, &calc_flip}, + {1, (const char*[]){"mc"}, &calc_mem_clear}, + {1, (const char*[]){"mr"}, &calc_mem_recall}, + {1, (const char*[]){"ma"}, &calc_mem_add}, + {1, (const char*[]){"ms"}, &calc_mem_subtract}, // Basic operations - {{"a"}, &calc_add}, - {{"s"}, &calc_subtract}, - {{"n"}, &calc_negate}, - {{"m"}, &calc_multiply}, - {{"d"}, &calc_divide}, - {{"i"}, &calc_invert}, + {1, (const char*[]){"a"}, &calc_add}, + {1, (const char*[]){"s"}, &calc_subtract}, + {1, (const char*[]){"n"}, &calc_negate}, + {1, (const char*[]){"m"}, &calc_multiply}, + {1, (const char*[]){"d"}, &calc_divide}, + {1, (const char*[]){"i"}, &calc_invert}, // Constants - {{"e"}, &calc_e}, - {{"pi"}, &calc_pi}, + {1, (const char*[]){"e"}, &calc_e}, + {1, (const char*[]){"pi"}, &calc_pi}, // Exponential/logarithmic - {{"exp"}, &calc_exp}, - {{"pow"}, &calc_pow}, - {{"ln"}, &calc_ln}, - {{"log"}, &calc_log}, - {{"sqrt"}, &calc_sqrt}, + {1, (const char*[]){"exp"}, &calc_exp}, + {1, (const char*[]){"pow"}, &calc_pow}, + {1, (const char*[]){"ln"}, &calc_ln}, + {1, (const char*[]){"log"}, &calc_log}, + {1, (const char*[]){"sqrt"}, &calc_sqrt}, // Trigonometric - {{"sin", "sn"}, &calc_sin}, - {{"cos"}, &calc_cos}, - {{"tan"}, &calc_tan}, - {{"asin"}, &calc_asin}, - {{"acos"}, &calc_acos}, - {{"atan"}, &calc_atan}, - {{"atan2"}, &calc_atan2}, - {{"sind"}, &calc_sind}, - {{"cosd"}, &calc_cosd}, - {{"tand"}, &calc_tand}, - {{"asind"}, &calc_asind}, - {{"acosd"}, &calc_acosd}, - {{"atand"}, &calc_atand}, - {{"atan2d"}, &calc_atan2d}, + {2, (const char*[]){"sin", "sn"}, &calc_sin}, + {1, (const char*[]){"cos"}, &calc_cos}, + {1, (const char*[]){"tan"}, &calc_tan}, + {1, (const char*[]){"asin"}, &calc_asin}, + {1, (const char*[]){"acos"}, &calc_acos}, + {1, (const char*[]){"atan"}, &calc_atan}, + {1, (const char*[]){"atan2"}, &calc_atan2}, + {1, (const char*[]){"sind"}, &calc_sind}, + {1, (const char*[]){"cosd"}, &calc_cosd}, + {1, (const char*[]){"tand"}, &calc_tand}, + {1, (const char*[]){"asind"}, &calc_asind}, + {1, (const char*[]){"acosd"}, &calc_acosd}, + {1, (const char*[]){"atand"}, &calc_atand}, + {1, (const char*[]){"atan2d"}, &calc_atan2d}, + {1, (const char*[]){"tor"}, &calc_torad}, + {1, (const char*[]){"tod"}, &calc_todeg}, }; diff --git a/movement/lib/morsecalc/mc.c b/movement/lib/morsecalc/mc.c deleted file mode 100644 index 94f6511b..00000000 --- a/movement/lib/morsecalc/mc.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2023 Christian Chapman - * - * 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 -#include "mc.h" - -/* mc_reset Initialize or reset an MC buffer - * Input: mc = location of buffer to reset - */ -void mc_reset(mc_state_t * mc) { - memset(mc->b, '\0', BUFFLEN*sizeof(mc->b[0])); - mc->bidx = 0; - return; - return; -} - -/* mc_input Read an input into a morse code buffer - * Input: mc = buffer to read into - * c = character to read into buffer ('.' or '-', ignored otherwise). - * If the buffer is full, reset it instead of entering the new character. - */ -void mc_input(mc_state_t * mc, char c) { - if(mc->bidx >= BUFFLEN) mc_reset(mc); - else if( ('.' == c) || ('-' == c) ) { - mc->b[mc->bidx] = c; - mc->bidx++; - } - return; -} - -/* mc_dec Decode a Morse code character (descend MC_DEC_KEY[]) - * Input: b = BUFFLEN-length char array with '.'s and '-'s - * Output: c = Character b represents, or '\0' if not a Morse code. - */ -char mc_dec(char b[BUFFLEN]) { - uint8_t pos = 1; // Binary tree position ('.'=0; '-'=1) - for(uint8_t idx=0; idx +#include + +#include "watch_private_display.h" +#include "morsecalc_display.h" + +// Display float on screen +void morsecalc_display_float(double d) { + // Special cases + if(d == 0) { + watch_display_string(" 0", 4); + return; + } + else if(isnan(d)) { + watch_display_string(" nan", 4); + return; + } + else if(d == (1.0)/(0.0)) { + watch_display_string(" inf", 4); + return; + } + else if(d == (-1.0)/(0.0)) { + watch_display_character('X', 1); + watch_display_string(" inf", 4); + return; + } + + // Record number properties + // Sign + int is_negative = d<0; + if(is_negative) d = -d; + + // Order of magnitude + int om = (int) floor(log(d)/log(10)); + int om_is_negative = (om<0); + + // Get the first 4 significant figures + int digits; + digits = round(d*pow(10.0, 3-om)); + if(digits>9999) { + digits = 1000; + om++; + } + + // Print signs + if(is_negative) { + // Xi; see https://joeycastillo.github.io/Sensor-Watch-Documentation/segmap + watch_set_pixel(0,11); + watch_set_pixel(2,12); + watch_set_pixel(2,11); + } + else watch_display_character(' ', 1); + if(om_is_negative) watch_set_pixel(1,9); + else watch_display_character(' ', 2); + + // Print first 4 significant figures + watch_display_character('0'+(digits/1000)%10, 4); + watch_display_character('0'+(digits/100 )%10, 5); + watch_display_character('0'+(digits/10 )%10, 6); + watch_display_character('0'+(digits/1 )%10, 7); + + // Prinat exponent + if(om_is_negative) om = -om; // Make exponent positive for display + if(om<=99) { + watch_display_character('0'+(om/10 )%10, 8); + watch_display_character('0'+(om/1 )%10, 9); + } else { // Over/underflow + if(om_is_negative) watch_display_string(" uf", 4); + else watch_display_string(" of", 4); + if(om<9999) { // Use main display to show order of magnitude + // (Should always succeed; max double is <2e308) + watch_display_character('0'+(om/1000)%10, 4); + watch_display_character('0'+(om/100 )%10, 5); + watch_display_character('0'+(om/10 )%10, 6); + watch_display_character('0'+(om/1 )%10, 7); + } + } + return; +} + +// Print current input token +void morsecalc_display_token(morsecalc_state_t *mcs) { + watch_display_string(" ", 0); // Clear display + + // Print morse code buffer + char c = MORSECODE_TREE[mcs->mc]; // Decode the morse code buffer's current contents + if('\0' == c) c = ' '; // Needed for watch_display_character + watch_display_character(c, 0); // Display current morse code char in mode position + + unsigned int v = mcs->mc+1; + char bidx = 0; while (v >>= 1) bidx++; + watch_display_character('0'+bidx, 3); // Display buffer position in top right + + // Print last 6 chars of current input line + uint8_t nlen = strlen(mcs->token); // number of characters in token + uint8_t nprint = min(nlen,6); // number of characters to print + watch_display_string(mcs->token+nlen-nprint, 10-nprint); // print right-aligned + return; +} + +// Print stack or memory register contents. +void morsecalc_display_stack(morsecalc_state_t * mcs) { + watch_display_string(" ", 0); // Clear display + + char c = MORSECODE_TREE[mcs->mc]; + if('m' == c) { // Display memory + morsecalc_display_float(mcs->cs->mem); + watch_display_character(c, 0); + } + else { + // If the morse code buffer has a numeral in it, print that stack item + // Otherwise print top of stack + uint8_t idx = 0; + if(c >= '0' && c <= '9') idx = c - '0'; + if(idx >= mcs->cs->s) watch_display_string(" empty", 4); // Stack empty + else morsecalc_display_float(mcs->cs->stack[mcs->cs->s-1-idx]); // Print stack item + + watch_display_character('0'+idx, 0); // Print which stack item this is top center + } + watch_display_character('0'+(mcs->cs->s), 3); // Print the # of stack items top right + return; +} + diff --git a/movement/lib/morsecalc/mc.h b/movement/lib/morsecalc/morsecalc_display.h similarity index 58% rename from movement/lib/morsecalc/mc.h rename to movement/lib/morsecalc/morsecalc_display.h index 0daa470e..74f8b0cc 100644 --- a/movement/lib/morsecalc/mc.h +++ b/movement/lib/morsecalc/morsecalc_display.h @@ -22,30 +22,14 @@ * SOFTWARE. */ +#include "morsecalc_face.h" -/* mc Morse code reading methods -*/ -#include "stdint.h" +// Display float on screen +void morsecalc_display_float(double d); -#define BUFFLEN 5 -typedef struct { - char b[BUFFLEN]; - uint8_t bidx; -} mc_state_t; +// Print current input token +void morsecalc_display_token(morsecalc_state_t *mcs); -// MC_DEC_KEY represents a binary tree of International Morse Code. -// where '.' = 0 and '-' = 1. Levels of the tree are concatenated. -// -// Capitals denote special characters: -// C = Ch digraph -// V = VERIFY (ITU-R "UNDERSTOOD") -// R = REPEAT -// W = WAIT -// S = START TRANSMISSION -// E = END OF WORK -static const char MC_DEC_KEY[] = " etianmsurwdkgohvf\0l\0pjbxcyzq\0C\x35\x34V\x33\0R\0\x32W\0+\0\0\0\0\x31\x36=/\0\0S(\0\x37\0\0\0\x38\0\x39\x30\0\0\0\0\0E\0\0\0\0\0\0?_\0\0\0\0\"\0\0.\0\0\0\0@\0\0\0'\0\0-\0\0\0\0\0\0\0\0;!\0)\0\0\0\0\0,\0\0\0\0:\0\0\0\0\0\0\0"; - -void mc_reset(mc_state_t * mcb); -void mc_input(mc_state_t * mc, char c); -char mc_dec(char b[BUFFLEN]); +// Print stack or memory register contents. +void morsecalc_display_stack(morsecalc_state_t *mcs); diff --git a/movement/lib/morsecalc/test_morsecalc.c b/movement/lib/morsecalc/test_morsecalc.c new file mode 100644 index 00000000..fc640bad --- /dev/null +++ b/movement/lib/morsecalc/test_morsecalc.c @@ -0,0 +1,66 @@ +/* + * MIT License + * + * Copyright (c) 2023 Christian Chapman + * + * 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. + */ + +// Computer console interface to calc and morsecode for testing without involving watch stuff. +// cc calc_strtof.c calc.c calc_fns.c test_morsecalc.c -lm + +#include +#include +#include +#include + +#include "calc.h" +#include "calc_fns.h" + +int main(void) { + calc_state_t cs; + calc_init(&cs); + + char * word = malloc(0); + unsigned int nword = 0; + char c; + int retval = 0; + for(unsigned int ii = 0; ii < 100; ii++) { + c = getchar(); + word = realloc(word, (++nword)*sizeof(char)); + word[nword-1] = c; + if((nword > 0) && isspace(c)) { // Word is finished + word[nword-1] = '\0'; + retval = calc_input(&cs, word); // Submit word + word = realloc(word, 0); nword = 0; // Clear word + + switch(retval) { + case 0: printf("Success.\n"); break; + case -1: printf("Bad command.\n"); break; + case -2: printf("Stack over/underflow.\n"); break; + case -3: printf("Error.\n"); break; + } + if(cs.s > 0) printf("[%i]: %.4f\n", cs.s, cs.stack[cs.s-1]); + else printf("[%i]\n", cs.s); + } + } + + free(word); + return 0; +} diff --git a/movement/make/Makefile b/movement/make/Makefile index 417be4c5..952f3c70 100644 --- a/movement/make/Makefile +++ b/movement/make/Makefile @@ -17,6 +17,7 @@ INCLUDES += \ -I../watch_faces/sensor/ \ -I../watch_faces/demo/ \ -I../../littlefs/ \ + -I../lib/chirpy_tx/ \ -I../lib/TOTP/ \ -I../lib/base32/ \ -I../lib/sunriset/ \ @@ -31,6 +32,7 @@ INCLUDES += \ # ../drivers/lis2dh.c \ # ../watch_faces/fitness/step_count_face.c SRCS += \ + ../lib/chirpy_tx/chirpy_tx.c \ ../lib/TOTP/sha1.c \ ../lib/TOTP/sha256.c \ ../lib/TOTP/sha512.c \ @@ -42,7 +44,7 @@ SRCS += \ ../lib/morsecalc/calc.c \ ../lib/morsecalc/calc_fns.c \ ../lib/morsecalc/calc_strtof.c \ - ../lib/morsecalc/mc.c \ + ../lib/morsecalc/morsecalc_display.c \ ../../littlefs/lfs.c \ ../../littlefs/lfs_util.c \ ../movement.c \ @@ -95,9 +97,23 @@ SRCS += \ ../watch_faces/complication/tarot_face.c \ ../watch_faces/complication/morsecalc_face.c \ ../watch_faces/complication/rpn_calculator_face.c \ + ../watch_faces/complication/activity_face.c \ + ../watch_faces/demo/chirpy_demo_face.c \ ../watch_faces/complication/ships_bell_face.c \ + ../watch_faces/sensor/lightmeter_face.c \ + ../watch_faces/complication/discgolf_face.c \ ../watch_faces/complication/habit_face.c \ + ../watch_faces/complication/planetary_time_face.c \ + ../watch_faces/complication/planetary_hours_face.c \ + ../watch_faces/complication/breathing_face.c \ + ../watch_faces/clock/repetition_minute_face.c \ ../watch_faces/complication/timer_face.c \ + ../watch_faces/complication/invaders_face.c \ + ../watch_faces/clock/world_clock2_face.c \ + ../watch_faces/complication/time_left_face.c \ + ../watch_faces/complication/randonaut_face.c \ + ../watch_faces/complication/toss_up_face.c \ + ../watch_faces/complication/geomancy_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. diff --git a/movement/movement_faces.h b/movement/movement_faces.h index 56e722dd..0e2a45b1 100644 --- a/movement/movement_faces.h +++ b/movement/movement_faces.h @@ -73,9 +73,24 @@ #include "interval_face.h" #include "morsecalc_face.h" #include "rpn_calculator_face.h" +#include "activity_face.h" +#include "chirpy_demo_face.h" #include "ships_bell_face.h" +#include "lightmeter_face.h" +#include "discgolf_face.h" #include "habit_face.h" +#include "planetary_time_face.h" +#include "planetary_hours_face.h" +#include "breathing_face.h" +#include "repetition_minute_face.h" #include "timer_face.h" +#include "invaders_face.h" +#include "world_clock2_face.h" +#include "time_left_face.h" +#include "randonaut_face.h" +#include "toss_up_face.h" +#include "geomancy_face.h" +#include "dual_timer_face.h" // New includes go above this line. #endif // MOVEMENT_FACES_H_ diff --git a/movement/watch_faces/clock/repetition_minute_face.c b/movement/watch_faces/clock/repetition_minute_face.c new file mode 100644 index 00000000..a0fbe077 --- /dev/null +++ b/movement/watch_faces/clock/repetition_minute_face.c @@ -0,0 +1,231 @@ +/* + * MIT License + * + * Copyright (c) 2023 Jonas Termeau + * + * 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 +#include "repetition_minute_face.h" +#include "watch.h" +#include "watch_utility.h" +#include "watch_private_display.h" + +void play_hour_chime(void) { + watch_buzzer_play_note(BUZZER_NOTE_C6, 75); + watch_buzzer_play_note(BUZZER_NOTE_REST, 500); +} + +void play_quarter_chime(void) { + watch_buzzer_play_note(BUZZER_NOTE_E6, 75); + watch_buzzer_play_note(BUZZER_NOTE_REST, 150); + watch_buzzer_play_note(BUZZER_NOTE_C6, 75); + watch_buzzer_play_note(BUZZER_NOTE_REST, 750); +} + +void play_minute_chime(void) { + watch_buzzer_play_note(BUZZER_NOTE_E6, 75); + watch_buzzer_play_note(BUZZER_NOTE_REST, 500); +} + +static void _update_alarm_indicator(bool settings_alarm_enabled, repetition_minute_state_t *state) { + state->alarm_enabled = settings_alarm_enabled; + if (state->alarm_enabled) watch_set_indicator(WATCH_INDICATOR_SIGNAL); + else watch_clear_indicator(WATCH_INDICATOR_SIGNAL); +} + +void repetition_minute_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(repetition_minute_state_t)); + repetition_minute_state_t *state = (repetition_minute_state_t *)*context_ptr; + state->signal_enabled = false; + state->watch_face_index = watch_face_index; + } +} + +void repetition_minute_face_activate(movement_settings_t *settings, void *context) { + repetition_minute_state_t *state = (repetition_minute_state_t *)context; + + if (watch_tick_animation_is_running()) watch_stop_tick_animation(); + + if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H); + + // handle chime indicator + if (state->signal_enabled) watch_set_indicator(WATCH_INDICATOR_BELL); + else watch_clear_indicator(WATCH_INDICATOR_BELL); + + // show alarm indicator if there is an active alarm + _update_alarm_indicator(settings->bit.alarm_enabled, state); + + watch_set_colon(); + + // this ensures that none of the timestamp fields will match, so we can re-render them all. + state->previous_date_time = 0xFFFFFFFF; +} + +bool repetition_minute_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + repetition_minute_state_t *state = (repetition_minute_state_t *)context; + char buf[11]; + uint8_t pos; + + watch_date_time date_time; + uint32_t previous_date_time; + switch (event.event_type) { + case EVENT_ACTIVATE: + case EVENT_TICK: + case EVENT_LOW_ENERGY_UPDATE: + date_time = watch_rtc_get_date_time(); + previous_date_time = state->previous_date_time; + state->previous_date_time = date_time.reg; + + // check the battery voltage once a day... + if (date_time.unit.day != state->last_battery_check) { + state->last_battery_check = date_time.unit.day; + watch_enable_adc(); + uint16_t voltage = watch_get_vcc_voltage(); + watch_disable_adc(); + // 2.2 volts will happen when the battery has maybe 5-10% remaining? + // we can refine this later. + state->battery_low = (voltage < 2200); + } + + // ...and set the LAP indicator if low. + if (state->battery_low) watch_set_indicator(WATCH_INDICATOR_LAP); + + if ((date_time.reg >> 6) == (previous_date_time >> 6) && event.event_type != EVENT_LOW_ENERGY_UPDATE) { + // everything before seconds is the same, don't waste cycles setting those segments. + watch_display_character_lp_seconds('0' + date_time.unit.second / 10, 8); + watch_display_character_lp_seconds('0' + date_time.unit.second % 10, 9); + break; + } else if ((date_time.reg >> 12) == (previous_date_time >> 12) && event.event_type != EVENT_LOW_ENERGY_UPDATE) { + // everything before minutes is the same. + pos = 6; + sprintf(buf, "%02d%02d", date_time.unit.minute, date_time.unit.second); + } else { + // other stuff changed; let's do it all. + if (!settings->bit.clock_mode_24h) { + // if we are in 12 hour mode, do some cleanup. + if (date_time.unit.hour < 12) { + watch_clear_indicator(WATCH_INDICATOR_PM); + } else { + watch_set_indicator(WATCH_INDICATOR_PM); + } + date_time.unit.hour %= 12; + if (date_time.unit.hour == 0) date_time.unit.hour = 12; + } + pos = 0; + if (event.event_type == EVENT_LOW_ENERGY_UPDATE) { + if (!watch_tick_animation_is_running()) watch_start_tick_animation(500); + sprintf(buf, "%s%2d%2d%02d ", watch_utility_get_weekday(date_time), date_time.unit.day, date_time.unit.hour, date_time.unit.minute); + } else { + sprintf(buf, "%s%2d%2d%02d%02d", watch_utility_get_weekday(date_time), date_time.unit.day, date_time.unit.hour, date_time.unit.minute, date_time.unit.second); + } + } + watch_display_string(buf, pos); + // handle alarm indicator + if (state->alarm_enabled != settings->bit.alarm_enabled) _update_alarm_indicator(settings->bit.alarm_enabled, state); + break; + case EVENT_ALARM_LONG_PRESS: + state->signal_enabled = !state->signal_enabled; + if (state->signal_enabled) watch_set_indicator(WATCH_INDICATOR_BELL); + else watch_clear_indicator(WATCH_INDICATOR_BELL); + break; + case EVENT_BACKGROUND_TASK: + // uncomment this line to snap back to the clock face when the hour signal sounds: + // movement_move_to_face(state->watch_face_index); + if (watch_is_buzzer_or_led_enabled()) { + // if we are in the foreground, we can just beep. + movement_play_signal(); + } else { + // if we were in the background, we need to enable the buzzer peripheral first, + watch_enable_buzzer(); + // beep quickly (this call blocks for 275 ms), + movement_play_signal(); + // and then turn the buzzer peripheral off again. + watch_disable_buzzer(); + } + break; + case EVENT_LIGHT_LONG_UP: + /* + * Howdy neighbors, this is the actual complication. Like an actual + * (very expensive) watch with a repetition minute complication it's + * boring at 00:00 or 1:00 and very quite musical at 23:59 or 12:59. + */ + + date_time = watch_rtc_get_date_time(); + + + int hours = date_time.unit.hour; + int quarters = date_time.unit.minute / 15; + int minutes = date_time.unit.minute % 15; + + // chiming hours + if (!settings->bit.clock_mode_24h) { + hours = date_time.unit.hour % 12; + if (hours == 0) hours = 12; + } + if (hours > 0) { + int count = 0; + for(count = hours; count > 0; --count) { + play_hour_chime(); + } + } + + // chiming quarters (if needed) + if (quarters > 0) { + int count = 0; + for(count = quarters; count > 0; --count) { + play_quarter_chime(); + } + } + + // chiming minutes (if needed) + if (minutes > 0) { + int count = 0; + for(count = minutes; count > 0; --count) { + play_minute_chime(); + } + } + + break; + default: + return movement_default_loop_handler(event, settings); + } + + return true; +} + +void repetition_minute_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; +} + +bool repetition_minute_face_wants_background_task(movement_settings_t *settings, void *context) { + (void) settings; + repetition_minute_state_t *state = (repetition_minute_state_t *)context; + if (!state->signal_enabled) return false; + + watch_date_time date_time = watch_rtc_get_date_time(); + + return date_time.unit.minute == 0; +} diff --git a/movement/watch_faces/clock/repetition_minute_face.h b/movement/watch_faces/clock/repetition_minute_face.h new file mode 100644 index 00000000..5a897bc1 --- /dev/null +++ b/movement/watch_faces/clock/repetition_minute_face.h @@ -0,0 +1,83 @@ +/* + * MIT License + * + * Copyright (c) 2023 Jonas Termeau + * + * 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 REPETITION_MINUTE_FACE_H_ +#define REPETITION_MINUTE_FACE_H_ + +#include "movement.h" + +/* + * A hopefully useful complication for friendly neighbors in the dark + * + * Originating from 1676 from reverend and mechanician Edward Barlow, and + * perfected in 1820 by neighbor Abraham Breguet, a minute repeater or + * "repetition minute" is a complication in a mechanical watch or clock that + * chimes the hours and often minutes at the press of a button. There are many + * types of repeater, from the simple repeater which merely strikes the number + * of hours, to the minute repeater which chimes the time down to the minute, + * using separate tones for hours, quarter hours, and minutes. They originated + * before widespread artificial illumination, to allow the time to be determined + * in the dark, and were also used by the visually impaired. + * + * + * How to use it : + * + * Long press the light button to get an auditive reading of the time like so : + * 0..23 (1..12 if 24-hours format isn't enabled) low beep(s) for the hours + * 0..3 low-high couple pitched beeps for the quarters + * 0..14 high pitched beep(s) for the remaining minutes + * + * Prerequisite : a watch with a working buzzer + * + * ~ Only in the darkness can you see the stars. - Martin Luther King ~ + * + */ + +typedef struct { + uint32_t previous_date_time; + uint8_t last_battery_check; + uint8_t watch_face_index; + bool signal_enabled; + bool battery_low; + bool alarm_enabled; +} repetition_minute_state_t; + +void play_hour_chime(void); +void play_quarter_chime(void); +void play_minute_chime(void); +void repetition_minute_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void repetition_minute_face_activate(movement_settings_t *settings, void *context); +bool repetition_minute_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void repetition_minute_face_resign(movement_settings_t *settings, void *context); +bool repetition_minute_face_wants_background_task(movement_settings_t *settings, void *context); + +#define repetition_minute_face ((const watch_face_t){ \ + repetition_minute_face_setup, \ + repetition_minute_face_activate, \ + repetition_minute_face_loop, \ + repetition_minute_face_resign, \ + repetition_minute_face_wants_background_task, \ +}) + +#endif // REPETITION_MINUTE_FACE_H_ diff --git a/movement/watch_faces/clock/world_clock2_face.c b/movement/watch_faces/clock/world_clock2_face.c new file mode 100644 index 00000000..0077f639 --- /dev/null +++ b/movement/watch_faces/clock/world_clock2_face.c @@ -0,0 +1,450 @@ +/* + * MIT License + * + * Copyright (c) 2023 Konrad Rieck + * 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. + */ + +/* + * World Clock 2 + * ============= + * + * This is an alternative world clock face that allows the user to cycle + * through a list of selected time zones. It extends the original + * implementation by Joey Castillo. The face has two modes *display mode* + * and *settings mode*. + * + * ### Settings mode + * + * When the clock face is activated for the first time, it enters + * *settings mode*. Here, the user can select the time zones they want to + * display. The face shows a summary of the current time zone: + * + * - The top of the face displays the first two letters of the time zone + * abbreviation, such as "PS" for Pacific Standard Time or CE for + * "Central European Time". + * + * - The upper-right corner shows the index number of the time zone. This + * helps avoid confusion when multiple time zones have the same + * two-letter abbreviation. + * + * - The main display shows the offset from UTC, with a "+" indicating a + * positive offset and a "-" indicating a negative offset. For example, + * the offset for Japanese Standard Time is displayed as "+9:00". + * + * The user can navigate through the time zones and select them using the + * following buttons: + * + * - The *alarm button* moves forward to the next time zone, while the + * *light button* moves backward to the previous zone. This way, the + * user can cycle through all 41 supported time zones. + * + * - A *long press* on the *light button* selects the current time zone, + * and the signal indicator appears at the top left. Another *long + * press* of the *light button* deselects the time zone. + * + * - A *long press* on the *alarm button* exits settings mode and returns + * to display mode. + * + * ### Display mode + * + * In the display mode, the face shows the time of the currently selected + * time zone. The face includes the following components: + * + * - The top of the face displays the first two letters of the time zone + * abbreviation, such as "PS" for Pacific Standard Time or "CE" for + * Central European Time. + * + * - The upper-right corner shows the current day of the month, which + * helps indicate time zones that cross the international date line + * with respect to the local time. + * + * - The main display shows the time in the selected time zone in either + * 12-hour or 24-hour form. There is no timeout, allowing users to keep + * the chosen time zone displayed for as long as they wish. + * + * The user can navigate through the selected time zones using the + * following buttons: + * + * - The *alarm button* moves to the next selected time zone, while the + * light button moves to the *previous zone*. If no time zone is + * selected, the face simply shows UTC. + * + * - A *long press* on the *alarm button* enters settings mode and + * enables the user to re-configure the selected time zones. + * + * - A *long press* on the *light button* activates the LED illumination + * of the watch. + * + */ + +#include +#include +#include "world_clock2_face.h" +#include "watch.h" +#include "watch_utility.h" +#include "watch_utility.h" + +static bool refresh_face; + +/* Simple macros for navigation */ +#define FORWARD +1 +#define BACKWARD -1 + +/* Activate refresh of time */ +#define REFRESH_TIME 0xffffffff + +/* List of all time zone names */ +const char *zone_names[] = { + "UTC", // 0 : 0:00:00 (UTC) + "CET", // 1 : 1:00:00 (Central European Time) + "SAST", // 2 : 2:00:00 (South African Standard Time) + "ARST", // 3 : 3:00:00 (Arabia Standard Time) + "IRST", // 4 : 3:30:00 (Iran Standard Time) + "GET", // 5 : 4:00:00 (Georgia Standard Time) + "AFT", // 6 : 4:30:00 (Afghanistan Time) + "PKT", // 7 : 5:00:00 (Pakistan Standard Time) + "IST", // 8 : 5:30:00 (Indian Standard Time) + "NPT", // 9 : 5:45:00 (Nepal Time) + "KGT", // 10 : 6:00:00 (Kyrgyzstan time) + "MYST", // 11 : 6:30:00 (Myanmar Time) + "THA", // 12 : 7:00:00 (Thailand Standard Time) + "CST", // 13 : 8:00:00 (China Standard Time, Australian Western Standard Time) + "ACWS", // 14 : 8:45:00 (Australian Central Western Standard Time) + "JST", // 15 : 9:00:00 (Japan Standard Time, Korea Standard Time) + "ACST", // 16 : 9:30:00 (Australian Central Standard Time) + "AEST", // 17 : 10:00:00 (Australian Eastern Standard Time) + "LHST", // 18 : 10:30:00 (Lord Howe Standard Time) + "SBT", // 19 : 11:00:00 (Solomon Islands Time) + "NZST", // 20 : 12:00:00 (New Zealand Standard Time) + "CHAS", // 21 : 12:45:00 (Chatham Standard Time) + "TOT", // 22 : 13:00:00 (Tonga Time) + "CHAD", // 23 : 13:45:00 (Chatham Daylight Time) + "LINT", // 24 : 14:00:00 (Line Islands Time) + "BIT", // 25 : -12:00:00 (Baker Island Time) + "NUT", // 26 : -11:00:00 (Niue Time) + "HST", // 27 : -10:00:00 (Hawaii-Aleutian Standard Time) + "MART", // 28 : -9:30:00 (Marquesas Islands Time) + "AKST", // 29 : -9:00:00 (Alaska Standard Time) + "PST", // 30 : -8:00:00 (Pacific Standard Time) + "MST", // 31 : -7:00:00 (Mountain Standard Time) + "CST", // 32 : -6:00:00 (Central Standard Time) + "EST", // 33 : -5:00:00 (Eastern Standard Time) + "VET", // 34 : -4:30:00 (Venezuelan Standard Time) + "AST", // 35 : -4:00:00 (Atlantic Standard Time) + "NST", // 36 : -3:30:00 (Newfoundland Standard Time) + "BRT", // 37 : -3:00:00 (Brasilia Time) + "NDT", // 38 : -2:30:00 (Newfoundland Daylight Time) + "FNT", // 39 : -2:00:00 (Fernando de Noronha Time) + "AZOT", // 40 : -1:00:00 (Azores Standard Time) +}; + +/* Modulo function */ +static inline unsigned int mod(int a, int b) +{ + int r = a % b; + return r < 0 ? r + b : r; +} + +/* Find the next selected time zone */ +static inline uint8_t find_selected_zone(world_clock2_state_t *state, int direction) +{ + uint8_t i = state->current_zone; + + do { + i = mod(i + direction, NUM_TIME_ZONES); + /* Could not find a selected zone. Return UTC */ + if (i == state->current_zone) { + return 0; + } + } while (!state->zones[i].selected); + + return i; +} + +/* Beep when zone is enabled. An octave up */ +static void beep_enable() { + watch_buzzer_play_note(BUZZER_NOTE_G7, 50); + watch_buzzer_play_note(BUZZER_NOTE_REST, 75); + watch_buzzer_play_note(BUZZER_NOTE_C8, 75); +} + +/* Beep when zone id disable. An octave down */ +static void beep_disable() { + watch_buzzer_play_note(BUZZER_NOTE_C8, 50); + watch_buzzer_play_note(BUZZER_NOTE_REST, 75); + watch_buzzer_play_note(BUZZER_NOTE_G7, 75); +} + +void world_clock2_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(world_clock2_state_t)); + memset(*context_ptr, 0, sizeof(world_clock2_state_t)); + + /* Start in settings mode */ + world_clock2_state_t *state = (world_clock2_state_t *) * context_ptr; + state->current_mode = WORLD_CLOCK2_MODE_SETTINGS; + } +} + +void world_clock2_face_activate(movement_settings_t *settings, void *context) +{ + (void) settings; + world_clock2_state_t *state = (world_clock2_state_t *) context; + + if (watch_tick_animation_is_running()) + watch_stop_tick_animation(); + + switch (state->current_mode) { + case WORLD_CLOCK2_MODE_DISPLAY: + /* Normal tick frequency */ + movement_request_tick_frequency(1); + break; + case WORLD_CLOCK2_MODE_SETTINGS: + /* Faster frequency for blinking effect */ + movement_request_tick_frequency(4); + break; + } + refresh_face = true; +} + +static bool mode_display(movement_event_t event, movement_settings_t *settings, world_clock2_state_t *state) +{ + char buf[11]; + uint8_t pos; + + uint32_t timestamp; + uint32_t previous_date_time; + watch_date_time date_time; + + switch (event.event_type) { + case EVENT_ACTIVATE: + case EVENT_TICK: + case EVENT_LOW_ENERGY_UPDATE: + /* Update indicators and colon on refresh */ + if (refresh_face) { + watch_clear_indicator(WATCH_INDICATOR_SIGNAL); + watch_set_colon(); + if (settings->bit.clock_mode_24h) + watch_set_indicator(WATCH_INDICATOR_24H); + + state->previous_date_time = REFRESH_TIME; + refresh_face = false; + } + + /* Determine current time at time zone and store date/time */ + date_time = watch_rtc_get_date_time(); + timestamp = watch_utility_date_time_to_unix_time(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60); + date_time = watch_utility_date_time_from_unix_time(timestamp, movement_timezone_offsets[state->current_zone] * 60); + previous_date_time = state->previous_date_time; + state->previous_date_time = date_time.reg; + + if ((date_time.reg >> 6) == (previous_date_time >> 6) && event.event_type != EVENT_LOW_ENERGY_UPDATE) { + /* Everything before seconds is the same, don't waste cycles setting those segments. */ + pos = 8; + sprintf(buf, "%02d", date_time.unit.second); + } else if ((date_time.reg >> 12) == (previous_date_time >> 12) && event.event_type != EVENT_LOW_ENERGY_UPDATE) { + /* Everything before minutes is the same. */ + pos = 6; + sprintf(buf, "%02d%02d", date_time.unit.minute, date_time.unit.second); + } else { + /* Other stuff changed; Let's do it all. */ + if (!settings->bit.clock_mode_24h) { + /* If we are in 12 hour mode, do some cleanup. */ + if (date_time.unit.hour < 12) { + watch_clear_indicator(WATCH_INDICATOR_PM); + } else { + watch_set_indicator(WATCH_INDICATOR_PM); + } + date_time.unit.hour %= 12; + if (date_time.unit.hour == 0) + date_time.unit.hour = 12; + } + + pos = 0; + if (event.event_type == EVENT_LOW_ENERGY_UPDATE) { + if (!watch_tick_animation_is_running()) + watch_start_tick_animation(500); + + sprintf(buf, "%.2s%2d%2d%02d ", + zone_names[state->current_zone], + date_time.unit.day, + date_time.unit.hour, + date_time.unit.minute); + } else { + sprintf(buf, "%.2s%2d%2d%02d%02d", + zone_names[state->current_zone], + date_time.unit.day, + date_time.unit.hour, + date_time.unit.minute, + date_time.unit.second); + } + } + watch_display_string(buf, pos); + break; + case EVENT_ALARM_BUTTON_UP: + state->current_zone = find_selected_zone(state, FORWARD); + state->previous_date_time = REFRESH_TIME; + break; + case EVENT_LIGHT_BUTTON_DOWN: + /* Do nothing. */ + break; + case EVENT_LIGHT_BUTTON_UP: + state->current_zone = find_selected_zone(state, BACKWARD); + state->previous_date_time = REFRESH_TIME; + break; + case EVENT_LIGHT_LONG_PRESS: + movement_illuminate_led(); + break; + case EVENT_ALARM_LONG_PRESS: + /* Switch to settings mode */ + state->current_mode = WORLD_CLOCK2_MODE_SETTINGS; + refresh_face = true; + movement_request_tick_frequency(1); + + if (settings->bit.button_should_sound) + watch_buzzer_play_note(BUZZER_NOTE_C8, 50); + break; + case EVENT_MODE_BUTTON_UP: + /* Reset frequency and move to next face */ + movement_request_tick_frequency(1); + movement_move_to_next_face(); + break; + default: + return movement_default_loop_handler(event, settings); + } + + return true; +} + +static bool mode_settings(movement_event_t event, movement_settings_t *settings, world_clock2_state_t *state) +{ + char buf[11]; + int8_t hours, minutes; + uint8_t zone; + div_t result; + + switch (event.event_type) { + case EVENT_ACTIVATE: + case EVENT_TICK: + case EVENT_LOW_ENERGY_UPDATE: + /* Update indicator and colon on refresh */ + if (refresh_face) { + watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_24H); + watch_clear_indicator(WATCH_INDICATOR_PM); + refresh_face = false; + } + result = div(movement_timezone_offsets[state->current_zone], 60); + hours = result.quot; + minutes = result.rem; + + /* + * Display time zone. The range of the parameters is reduced + * to avoid accidentally overflowing the buffer and to suppress + * corresponding compiler warnings. + */ + sprintf(buf, "%.2s%2d %c%02d%02d", + zone_names[state->current_zone], + state->current_zone % 100, + hours < 0 ? '-' : '+', + abs(hours) % 24, + abs(minutes) % 60); + + /* Let the zone number blink */ + if (event.subsecond % 2) + buf[2] = buf[3] = ' '; + + if (state->zones[state->current_zone].selected) + watch_set_indicator(WATCH_INDICATOR_SIGNAL); + else + watch_clear_indicator(WATCH_INDICATOR_SIGNAL); + + watch_display_string(buf, 0); + break; + case EVENT_ALARM_BUTTON_UP: + state->current_zone = mod(state->current_zone + FORWARD, NUM_TIME_ZONES); + break; + case EVENT_LIGHT_BUTTON_UP: + state->current_zone = mod(state->current_zone + BACKWARD, NUM_TIME_ZONES); + break; + case EVENT_LIGHT_BUTTON_DOWN: + /* Do nothing */ + break; + case EVENT_ALARM_LONG_PRESS: + /* Find next selected zone */ + if (!state->zones[state->current_zone].selected) + state->current_zone = find_selected_zone(state, FORWARD); + + /* Switch to display mode */ + state->current_mode = WORLD_CLOCK2_MODE_DISPLAY; + refresh_face = true; + movement_request_tick_frequency(1); + + if (settings->bit.button_should_sound) + watch_buzzer_play_note(BUZZER_NOTE_C8, 50); + break; + case EVENT_LIGHT_LONG_PRESS: + /* Toggle selection of current zone */ + zone = state->current_zone; + state->zones[zone].selected = !state->zones[zone].selected; + + if (settings->bit.button_should_sound) { + if (state->zones[zone].selected) { + beep_enable(); + } else { + beep_disable(); + } + } + break; + case EVENT_MODE_BUTTON_UP: + /* Reset frequency and move to next face */ + movement_request_tick_frequency(1); + movement_move_to_next_face(); + break; + default: + return movement_default_loop_handler(event, settings); + } + + return true; +} + +bool world_clock2_face_loop(movement_event_t event, movement_settings_t *settings, void *context) +{ + world_clock2_state_t *state = (world_clock2_state_t *) context; + switch (state->current_mode) { + case WORLD_CLOCK2_MODE_DISPLAY: + return mode_display(event, settings, state); + case WORLD_CLOCK2_MODE_SETTINGS: + return mode_settings(event, settings, state); + } + return false; +} + +void world_clock2_face_resign(movement_settings_t *settings, void *context) +{ + (void) settings; + (void) context; +} diff --git a/movement/watch_faces/clock/world_clock2_face.h b/movement/watch_faces/clock/world_clock2_face.h new file mode 100644 index 00000000..f70dca1f --- /dev/null +++ b/movement/watch_faces/clock/world_clock2_face.h @@ -0,0 +1,63 @@ +/* + * MIT License + * + * Copyright (c) 2023 Konrad Rieck + * 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 WORLD_CLOCK2_FACE_H_ +#define WORLD_CLOCK2_FACE_H_ + +/* Number of zones. See movement_timezone_offsets. */ +#define NUM_TIME_ZONES 41 + +#include "movement.h" + +typedef enum { + WORLD_CLOCK2_MODE_DISPLAY, + WORLD_CLOCK2_MODE_SETTINGS +} world_clock2_mode_t; + +typedef struct { + bool selected; +} world_clock2_zone_t; + +typedef struct { + world_clock2_zone_t zones[NUM_TIME_ZONES]; + world_clock2_mode_t current_mode; + uint8_t current_zone; + uint32_t previous_date_time; +} world_clock2_state_t; + +void world_clock2_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void **context_ptr); +void world_clock2_face_activate(movement_settings_t *settings, void *context); +bool world_clock2_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void world_clock2_face_resign(movement_settings_t *settings, void *context); + +#define world_clock2_face ((const watch_face_t){ \ + world_clock2_face_setup, \ + world_clock2_face_activate, \ + world_clock2_face_loop, \ + world_clock2_face_resign, \ + NULL, \ +}) + +#endif /* WORLD_CLOCK2_FACE_H_ */ diff --git a/movement/watch_faces/complication/activity_face.c b/movement/watch_faces/complication/activity_face.c new file mode 100644 index 00000000..f92984cd --- /dev/null +++ b/movement/watch_faces/complication/activity_face.c @@ -0,0 +1,725 @@ +/* + * MIT License + * + * Copyright (c) 2023 Gabor L Ugray + * + * 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. + */ + +/* ** TODO + * =================== + * -- Additional power-saving optimizations + */ + +#include +#include +#include "activity_face.h" +#include "chirpy_tx.h" +#include "watch.h" +#include "watch_utility.h" + +// =========================================================================== +// This part is configurable: you can edit values here to customize you activity face +// In particular, with num_enabled_activities and enabled_activities you can choose a subset of the +// activities that you want to see in your watch. +// You can also add new items to activity_names, but don't redefine or remove existing ones. + +// If a logged activity is shorter than this, then it won't be added to log when it ends. +// This way scarce log slots are not taken up by aborted events that weren't real activities. +static const uint16_t activity_min_length_sec = 60; + +// Supported activities. ID of activity is index in this buffer +// W e should never change order or redefine items, only add new items when needed. +static const char activity_names[][7] = { + " bIKE ", + "uuaLK ", + " rUn ", + "DAnCE ", + " yOgA ", + "CrOSS ", + "Suuinn", + "ELLIP ", + " gYnn", + " rOuu", + "SOCCEr", + " FOOTb", + " bALL ", + " SKI ", +}; + +// Currently enabled activities. This makes picking on first subface easier: why show activities you personally never do. +static const uint8_t enabled_activities[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}; + +// Number of currently enabled activities (size of enabled_activities). +static const uint8_t num_enabled_activities = sizeof(enabled_activities) / sizeof(uint8_t); + +// End configurable section +// =========================================================================== + +// One logged activity +typedef struct __attribute__((__packed__)) { + // Activity's start time + watch_date_time start_time; + + // Total duration of activity, including time spend in paus + uint16_t total_sec; + + // Number of seconds the activity was paused + uint16_t pause_sec; + + // Type of activity (index in activity_names) + uint8_t activity_type; + +} activity_item_t; + +#define MAX_ACTIVITY_SECONDS 28800 // 8 hours = 28800 sec + +// Size of (fixed) buffer to log activites. Takes up x9 bytes in SRAM if face is installed. +#define ACTIVITY_LOG_SZ 99 + +// Number of activities in buffer. +static uint8_t activity_log_count = 0; + +// Buffer with all logged activities. +static activity_item_t activity_log_buffer[ACTIVITY_LOG_SZ]; + +#define CHIRPY_PREFIX_LEN 2 +// First two bytes chirped out, to identify transmission as from the activity face +static const uint8_t activity_chirpy_prefix[CHIRPY_PREFIX_LEN] = {0x27, 0x00}; + +// The face's different UI modes (views). +typedef enum { + ACTM_CHOOSE = 0, + ACTM_LOGGING, + ACTM_PAUSED, + ACTM_DONE, + ACTM_LOGSIZE, + ACTM_CHIRP, + ACTM_CHIRPING, + ACTM_CLEAR, + ACTM_CLEAR_CONFIRM, + ACTM_CLEAR_DONE, +} activity_mode_t; + +// The full state of the activity face +typedef struct { + // Current mode (which secondary face, or ongoing operation like logging) + activity_mode_t mode; + + // Index of currently selected activity in enabled_activities + uint8_t type_ix; + + // Used for different things depending on mode + // In ACTM_DONE: countdown for animation, before returning to start face + // In ACTM_LOGGING and ACTM_PAUSED: drives blinking colon and alternating time display + // In ACTM_LOGSIZE, ACTM_CLEAR: enables timeout return to choose screen + uint16_t counter; + + // Start of currently logged activity, if any + watch_date_time start_time; + + // Total seconds elapsed since logging started + uint16_t curr_total_sec; + + // Total paused seconds in current log + uint16_t curr_pause_sec; + + // Helps us handle 1/64 ticks during transmission; including countdown timer + chirpy_tick_state_t chirpy_tick_state; + + // Used by chirpy encoder during transmission + chirpy_encoder_state_t chirpy_encoder_state; + + // 0: Running normally + // 1: In LE mode + // 2: Just woke up from LE mode. Will go to 0 after ignoring ALARM_BUTTON_UP. + uint8_t le_state; + +} activity_state_t; + +#define ACTIVITY_BUF_SZ 14 + +// Temp buffer used for sprintf'ing content for the display. +char activity_buf[ACTIVITY_BUF_SZ]; + +// Needed by _activity_get_next_byte to keep track of where we are in transmission +uint16_t *activity_seq_pos; + +static void _activity_clear_buffers() { + // Clear activity buffer; 0xcd is good for diagnostics + memset(activity_log_buffer, 0xcd, ACTIVITY_LOG_SZ * sizeof(activity_item_t)); + // Clear display buffer + memset(activity_buf, 0, ACTIVITY_BUF_SZ); +} + +static void _activity_display_choice(activity_state_t *state); +static void _activity_update_logging_screen(movement_settings_t *settings, activity_state_t *state); +static uint8_t _activity_get_next_byte(uint8_t *next_byte); + +void activity_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(activity_state_t)); + memset(*context_ptr, 0, sizeof(activity_state_t)); + // This happens only at boot + _activity_clear_buffers(); + } + // Do any pin or peripheral setup here; this will be called whenever the watch wakes from deep sleep. +} + +void activity_face_activate(movement_settings_t *settings, void *context) { + (void)settings; + (void)context; + + // Not using this function. Calling _activity_activate from the event handler. + // That is what we get both when the face is shown upon navigation by MODE, + // and when waking from low energy state. +} + +// Called from the ACTIVATE event handler in the loop +static void _activity_activate(movement_settings_t *settings, activity_state_t *state) { + // If waking from low-energy state and currently logging: update seconds values + // Those are not up-to-date because ticks have not been coming + if (state->le_state != 0 && state->mode == ACTM_LOGGING) { + state->le_state = 2; + watch_date_time now = watch_rtc_get_date_time(); + uint32_t now_timestamp = watch_utility_date_time_to_unix_time(now, 0); + uint32_t start_timestamp = watch_utility_date_time_to_unix_time(state->start_time, 0); + uint32_t total_seconds = now_timestamp - start_timestamp; + state->curr_total_sec = total_seconds; + _activity_update_logging_screen(settings, state); + } + // Regular activation: start from defaults + else { + state->le_state = 0; + state->mode = 0; + state->type_ix = 0; + _activity_display_choice(state); + } +} + +static void _activity_display_choice(activity_state_t *state) { + watch_display_string("AC", 0); + // If buffer is full: We say "FULL" + if (activity_log_count >= ACTIVITY_LOG_SZ) { + watch_display_string(" FULL ", 4); + } + // Otherwise, we show currently activity + else { + uint8_t activity_ix = enabled_activities[state->type_ix]; + const char *name = activity_names[activity_ix]; + watch_display_string((char *)name, 4); + } +} + +const uint8_t activity_anim_pixels[][2] = { + {1, 4}, // TL + {0, 5}, // BL + {0, 6}, // BOT + {1, 6}, // BR + {2, 5}, // TR + {2, 4}, // TOP + // {2, 4}, // MID +}; + +static void _activity_update_logging_screen(movement_settings_t *settings, activity_state_t *state) { + watch_duration_t duration; + + watch_display_string("AC ", 0); + + // If we're in LE state: per-minute update is special + if (state->le_state == 1) { + watch_date_time now = watch_rtc_get_date_time(); + uint32_t now_timestamp = watch_utility_date_time_to_unix_time(now, 0); + uint32_t start_timestamp = watch_utility_date_time_to_unix_time(state->start_time, 0); + uint32_t total_seconds = now_timestamp - start_timestamp; + duration = watch_utility_seconds_to_duration(total_seconds); + sprintf(activity_buf, " %d%02d ", duration.hours, duration.minutes); + watch_display_string(activity_buf, 4); + watch_set_colon(); + watch_set_indicator(WATCH_INDICATOR_LAP); + watch_clear_indicator(WATCH_INDICATOR_PM); + watch_clear_indicator(WATCH_INDICATOR_24H); + return; + } + + // Show elapsed time, or PAUSE + if ((state->counter % 5) < 3) { + watch_set_indicator(WATCH_INDICATOR_LAP); + watch_clear_indicator(WATCH_INDICATOR_PM); + watch_clear_indicator(WATCH_INDICATOR_24H); + if (state->mode == ACTM_PAUSED) { + watch_display_string(" PAUSE", 4); + watch_clear_colon(); + } else { + duration = watch_utility_seconds_to_duration(state->curr_total_sec); + // Under 10 minutes: M:SS + if (state->curr_total_sec < 600) { + sprintf(activity_buf, " %01d%02d", duration.minutes, duration.seconds); + watch_display_string(activity_buf, 4); + watch_clear_colon(); + } + // Under an hour: MM:SS + else if (state->curr_total_sec < 3600) { + sprintf(activity_buf, " %02d%02d", duration.minutes, duration.seconds); + watch_display_string(activity_buf, 4); + watch_clear_colon(); + } + // Over an hour: H:MM:SS + // (We never go to two-digit hours; stop at 8) + else { + sprintf(activity_buf, " %d%02d%02d", duration.hours, duration.minutes, duration.seconds); + watch_display_string(activity_buf, 4); + watch_set_colon(); + } + } + } + // Briefly, show time without seconds + else { + watch_clear_indicator(WATCH_INDICATOR_LAP); + watch_date_time now = watch_rtc_get_date_time(); + uint8_t hour = now.unit.hour; + if (!settings->bit.clock_mode_24h) { + watch_clear_indicator(WATCH_INDICATOR_24H); + if (hour < 12) + watch_clear_indicator(WATCH_INDICATOR_PM); + else + watch_set_indicator(WATCH_INDICATOR_PM); + hour %= 12; + if (hour == 0) hour = 12; + } + else { + watch_set_indicator(WATCH_INDICATOR_24H); + watch_clear_indicator(WATCH_INDICATOR_PM); + } + sprintf(activity_buf, "%2d%02d ", hour, now.unit.minute); + watch_set_colon(); + watch_display_string(activity_buf, 4); + } +} + +static void _activity_quit_chirping() { + watch_clear_indicator(WATCH_INDICATOR_BELL); + watch_set_buzzer_off(); + movement_request_tick_frequency(1); +} + +static void _activity_chirp_tick_transmit(void *context) { + activity_state_t *state = (activity_state_t *)context; + + uint8_t tone = chirpy_get_next_tone(&state->chirpy_encoder_state); + // Transmission over? + if (tone == 255) { + _activity_quit_chirping(); + state->mode = ACTM_CHIRP; + state->counter = 0; + watch_display_string("AC CHIRP ", 0); + return; + } + uint16_t period = chirpy_get_tone_period(tone); + watch_set_buzzer_period(period); + watch_set_buzzer_on(); +} + +static void _activity_chirp_tick_countdown(void *context) { + activity_state_t *state = (activity_state_t *)context; + + // Countdown over: start actual broadcast + if (state->chirpy_tick_state.seq_pos == 8 * 3) { + state->chirpy_tick_state.tick_compare = 3; + state->chirpy_tick_state.tick_count = 2; // tick_compare - 1, so it starts immediately + state->chirpy_tick_state.seq_pos = 0; + state->chirpy_tick_state.tick_fun = _activity_chirp_tick_transmit; + return; + } + // Sound or turn off buzzer + if ((state->chirpy_tick_state.seq_pos % 8) == 0) { + watch_set_buzzer_period(NotePeriods[BUZZER_NOTE_A5]); + watch_set_buzzer_on(); + if (state->chirpy_tick_state.seq_pos == 0) { + watch_display_string(" --- ", 4); + } else if (state->chirpy_tick_state.seq_pos == 8) { + watch_display_string(" --", 5); + } else if (state->chirpy_tick_state.seq_pos == 16) { + watch_display_string(" -", 5); + } + } else if ((state->chirpy_tick_state.seq_pos % 8) == 1) { + watch_set_buzzer_off(); + } + ++state->chirpy_tick_state.seq_pos; +} + +static uint8_t _activity_get_next_byte(uint8_t *next_byte) { + uint16_t num_bytes = 2 + activity_log_count * sizeof(activity_item_t); + uint16_t pos = *activity_seq_pos; + + // Init counter + if (pos == 0) { + sprintf(activity_buf, "%3d", activity_log_count); + watch_display_string(activity_buf, 5); + } + + if (pos == num_bytes) { + return 0; + } + // Two-byte prefix + if (pos < 2) { + (*next_byte) = activity_chirpy_prefix[pos]; + } + // Data + else { + pos -= 2; + uint16_t ix = pos / sizeof(activity_item_t); + const activity_item_t *itm = &activity_log_buffer[ix]; + uint16_t ofs = pos % sizeof(activity_item_t); + + // Update counter when starting new item + if (ofs == 0) { + sprintf(activity_buf, "%3d", activity_log_count - ix); + watch_display_string(activity_buf, 5); + } + + // Do this the hard way, byte by byte, to avoid high/low endedness issues + // Higher order bytes first, is our serialization format + uint8_t val; + // watch_date_time start_time; + // uint16_t total_sec; + // uint16_t pause_sec; + // uint8_t activity_type; + if (ofs == 0) + val = (itm->start_time.reg & 0xff000000) >> 24; + else if (ofs == 1) + val = (itm->start_time.reg & 0x00ff0000) >> 16; + else if (ofs == 2) + val = (itm->start_time.reg & 0x0000ff00) >> 8; + else if (ofs == 3) + val = (itm->start_time.reg & 0x000000ff); + else if (ofs == 4) + val = (itm->total_sec & 0xff00) >> 8; + else if (ofs == 5) + val = (itm->total_sec & 0x00ff); + else if (ofs == 6) + val = (itm->pause_sec & 0xff00) >> 8; + else if (ofs == 7) + val = (itm->pause_sec & 0x00ff); + else + val = itm->activity_type; + (*next_byte) = val; + } + ++(*activity_seq_pos); + return 1; +} + +static void _activity_finish_logging(activity_state_t *state) { + // Save this activity + // If shorter than minimum for log: don't save + // Sanity check about buffer length. This should never happen, but also we never want to overrun by error + if (state->curr_total_sec >= activity_min_length_sec && activity_log_count + 1 < ACTIVITY_LOG_SZ) { + activity_item_t *itm = &activity_log_buffer[activity_log_count]; + itm->start_time = state->start_time; + itm->total_sec = state->curr_total_sec; + itm->pause_sec = state->curr_pause_sec; + itm->activity_type = state->type_ix; + ++activity_log_count; + } + + // Go to DONE animation + // TODO: Not in LE mode + state->mode = ACTM_DONE; + watch_clear_indicator(WATCH_INDICATOR_LAP); + movement_request_tick_frequency(2); + state->counter = 6 * 1; + watch_clear_display(); + watch_display_string("AC dONE ", 0); +} + +static void _activity_handle_tick(movement_settings_t *settings, activity_state_t *state) { + // Display stopwatch-like duration while logging, alternating with time + if (state->mode == ACTM_LOGGING || state->mode == ACTM_PAUSED) { + ++state->counter; + ++state->curr_total_sec; + if (state->mode == ACTM_PAUSED) + ++state->curr_pause_sec; + // If we've reached max activity length: finish logging + if (state->curr_total_sec == MAX_ACTIVITY_SECONDS) { + _activity_finish_logging(state); + } + // Still logging: refresh display + else { + _activity_update_logging_screen(settings, state); + } + } + // Display countown animation, and exit face when down + else if (state->mode == ACTM_DONE) { + if (state->counter == 0) { + movement_move_to_face(0); + movement_request_tick_frequency(1); + } + else { + uint8_t cd = state->counter % 6; + watch_clear_pixel(activity_anim_pixels[cd][0], activity_anim_pixels[cd][1]); + --state->counter; + cd = state->counter % 6; + watch_set_pixel(activity_anim_pixels[cd][0], activity_anim_pixels[cd][1]); + } + } + // Log size, chirp, clear: return to choose after some time + else if (state->mode == ACTM_LOGSIZE || state->mode == ACTM_CHIRP || state->mode == ACTM_CLEAR) { + ++state->counter; + // Leave Log Size after 20 seconds + // Leave Clear after only 10: this is danger zone, we don't like hanging around here + // Leave Chirp after 2 minutes: most likely need to the time to fiddle with mic & Chirpy RX on the computer + uint16_t timeout = 20; + if (state->mode == ACTM_CLEAR) timeout = 10; + else if (state->mode == ACTM_CHIRP) timeout = 120; + if (state->counter > timeout) { + state->mode = ACTM_CHOOSE; + _activity_display_choice(state); + } + } + // Chirping + else if (state->mode == ACTM_CHIRPING) { + ++state->chirpy_tick_state.tick_count; + if (state->chirpy_tick_state.tick_count == state->chirpy_tick_state.tick_compare) { + state->chirpy_tick_state.tick_count = 0; + state->chirpy_tick_state.tick_fun(state); + } + } + // Clear confirm: blink CLEAR + else if (state->mode == ACTM_CLEAR_CONFIRM) { + ++state->counter; + if ((state->counter % 2) == 0) + watch_display_string("CLEAR ", 4); + else + watch_display_string(" ", 4); + if (state->counter > 12) { + state->mode = ACTM_CHOOSE; + _activity_display_choice(state); + movement_request_tick_frequency(1); + } + } + // Clear done: fill up zeroes, then return to choose screen + else if (state->mode == ACTM_CLEAR_DONE) { + ++state->counter; + // Animation done + if (state->counter == 7) { + state->mode = ACTM_CHOOSE; + _activity_display_choice(state); + movement_request_tick_frequency(1); + return; + } + // Display current state of animation + sprintf(activity_buf, " "); + uint8_t nZeros = state->counter + 1; + if (nZeros > 6) nZeros = 6; + for (uint8_t i = 0; i < nZeros; ++i) { + activity_buf[i] = '0'; + } + watch_display_string(activity_buf, 4); + } +} + +static void _activity_alarm_long(movement_settings_t *settings, activity_state_t *state) { + // On choose face: start logging activity + if (state->mode == ACTM_CHOOSE) { + // If buffer is full: Ignore this long press + if (activity_log_count >= ACTIVITY_LOG_SZ) + return; + // OK, we go ahead and start logging + state->start_time = watch_rtc_get_date_time(); + state->curr_total_sec = 0; + state->curr_pause_sec = 0; + state->counter = -1; + state->mode = ACTM_LOGGING; + watch_set_indicator(WATCH_INDICATOR_LAP); + _activity_update_logging_screen(settings, state); + } + // If logging or paused: end logging + else if (state->mode == ACTM_LOGGING || state->mode == ACTM_PAUSED) { + _activity_finish_logging(state); + } + // If chirp: kick off chirping + else if (state->mode == ACTM_CHIRP) { + // Set up our tick handling for countdown beeps + activity_seq_pos = &state->chirpy_tick_state.seq_pos; + state->chirpy_tick_state.tick_compare = 8; + state->chirpy_tick_state.tick_count = 7; // tick_compare - 1, so it starts immediately + state->chirpy_tick_state.seq_pos = 0; + state->chirpy_tick_state.tick_fun = _activity_chirp_tick_countdown; + // Set up chirpy encoder + chirpy_init_encoder(&state->chirpy_encoder_state, _activity_get_next_byte); + // Show bell; switch to 64/sec ticks + watch_set_indicator(WATCH_INDICATOR_BELL); + movement_request_tick_frequency(64); + state->mode = ACTM_CHIRPING; + } + // If clear: confirm (unless empty) + else if (state->mode == ACTM_CLEAR) { + if (activity_log_count == 0) + return; + state->mode = ACTM_CLEAR_CONFIRM; + state->counter = -1; + movement_request_tick_frequency(4); + } + // If clear confirm: do clear. + else if (state->mode == ACTM_CLEAR_CONFIRM) { + _activity_clear_buffers(); + activity_log_count = 0; + state->mode = ACTM_CLEAR_DONE; + state->counter = -1; + watch_display_string("0 ", 4); + movement_request_tick_frequency(2); + } +} + +static void _activity_alarm_short(movement_settings_t *settings, activity_state_t *state) { + // In the choose face, short ALARM cycles through activities + if (state->mode == ACTM_CHOOSE) { + state->type_ix = (state->type_ix + 1) % num_enabled_activities; + _activity_display_choice(state); + } + // If logging: pause + else if (state->mode == ACTM_LOGGING) { + state->mode = ACTM_PAUSED; + state->counter = 0; + _activity_update_logging_screen(settings, state); + } + // If paused: Update paused seconds count and return to logging + else if (state->mode == ACTM_PAUSED) { + state->mode = ACTM_LOGGING; + state->counter = 0; + _activity_update_logging_screen(settings, state); + } + // If chirping: stoppit + else if (state->mode == ACTM_CHIRPING) { + _activity_quit_chirping(); + state->mode = ACTM_CHIRP; + state->counter = 0; + watch_display_string("AC CHIRP ", 0); + } +} + +static void _activity_light_short(activity_state_t *state) { + // If choose face: move to log size + if (state->mode == ACTM_CHOOSE) { + state->mode = ACTM_LOGSIZE; + state->counter = 0; + sprintf(activity_buf, "AC L#g%3d", activity_log_count); + watch_display_string(activity_buf, 0); + } + // If log size face: move to chirp + else if (state->mode == ACTM_LOGSIZE) { + state->mode = ACTM_CHIRP; + state->counter = 0; + watch_display_string("AC CHIRP ", 0); + } + // If chirp face: move to clear + else if (state->mode == ACTM_CHIRP) { + state->mode = ACTM_CLEAR; + state->counter = 0; + watch_display_string("AC CLEAR ", 0); + } + // If clear face: return to choose face + else if (state->mode == ACTM_CLEAR || state->mode == ACTM_CLEAR_CONFIRM) { + state->mode = ACTM_CHOOSE; + _activity_display_choice(state); + movement_request_tick_frequency(1); + } + // While logging or paused, light is light + else if (state->mode == ACTM_LOGGING || state->mode == ACTM_PAUSED) { + movement_illuminate_led(); + } + // Otherwise, we don't do light. +} + +bool activity_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + activity_state_t *state = (activity_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + _activity_activate(settings, state); + break; + case EVENT_TICK: + _activity_handle_tick(settings, state); + break; + case EVENT_MODE_BUTTON_UP: + if (state->mode != ACTM_LOGGING && state->mode != ACTM_PAUSED && state->mode != ACTM_CHIRPING) { + movement_request_tick_frequency(1); + movement_move_to_next_face(); + } + break; + case EVENT_LIGHT_BUTTON_UP: + _activity_light_short(state); + break; + case EVENT_ALARM_BUTTON_UP: + // We also receive ALARM press that woke us up from LE state + // Don't want to act on that as if it were a real button press for us + if (state->le_state != 2) + _activity_alarm_short(settings, state); + else + state->le_state = 0; + break; + case EVENT_ALARM_LONG_PRESS: + _activity_alarm_long(settings, state); + break; + case EVENT_TIMEOUT: + if (state->mode != ACTM_LOGGING && state->mode != ACTM_PAUSED && + state->mode != ACTM_CHIRP && state->mode != ACTM_CHIRPING) { + movement_request_tick_frequency(1); + movement_move_to_face(0); + } + break; + case EVENT_LOW_ENERGY_UPDATE: + state->le_state = 1; + // If we're in paused logging mode: let's lose this activity. Pause is not meant for over an hour. + if (state->mode == ACTM_PAUSED) { + // When waking, face will revert to default screen + state->mode = ACTM_CHOOSE; + watch_display_string("AC SLEEP ", 0); + watch_clear_colon(); + watch_clear_indicator(WATCH_INDICATOR_LAP); + watch_clear_indicator(WATCH_INDICATOR_PM); + } + else { + _activity_update_logging_screen(settings, state); + watch_start_tick_animation(500); + } + break; + default: + movement_default_loop_handler(event, settings); + break; + } + + // Return true if the watch can enter standby mode. False needed when chirping. + if (state->mode == ACTM_CHIRPING) + return false; + else + return true; +} + +void activity_face_resign(movement_settings_t *settings, void *context) { + (void)settings; + (void)context; + + // Face should only ever temporarily request a higher frequency, so by the time we're resigning, + // this should not be needed. But we don't want an error to create a situation that drains the battery. + // Rather do this defensively here. + movement_request_tick_frequency(1); +} diff --git a/movement/watch_faces/complication/activity_face.h b/movement/watch_faces/complication/activity_face.h new file mode 100644 index 00000000..c72f7099 --- /dev/null +++ b/movement/watch_faces/complication/activity_face.h @@ -0,0 +1,89 @@ +/* + * MIT License + * + * Copyright (c) 2023 Gabor L Ugray + * + * 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 ACTIVITY_FACE_H_ +#define ACTIVITY_FACE_H_ + +#include "movement.h" + +/* + * ACTIVITY WATCH FACE + * + * The Activity face lets you record activities like you would do with a fitness watch. + * It supports different activities like running, biking, rowing etc., and for each recorded activity + * it stores when it started and how long it was. + * + * You can save up to 99 activities this way. Every once in a while you can chirp them out + * using the watch's piezo buzzer as a modem, then clear the log in the watch. + * To record and decode a chirpy transmission on your computer, you can use the web app here: + * https://jealousmarkup.xyz/off/chirpy/rx/ + * + * Using the face + * + * When you activate the face, it starts with the first screen to select the activity you want to log. + * ALARM cycles through the list of activities. + * LONG ALARM starts logging. + * While logging is in progress, the face alternates between the elapsed time and the current time. + * You can press ALARM to pause (e.g., while you hop in to the baker's for a croissant during your jog). + * Pressing ALARM again resumes the activity. + * LONG ALARM stops logging and saves the activity. + * + * When you're not loggin, you can press LIGHT to access the secondary faces. + * LIGHT #1 => Shows the size of the log (how many activities have been recorded). + * LIGHT #2 => The screen to chirp out the data. Press LONG ALARM to start chirping. + * LIGHT #3 => The screen to clear the log in the watch. Press LONG ALARM twice to clear data. + * + * Quirky details + * + * The face will discard short activities (less than a minute) when you press LONG ALARM to finish logging. + * These were probably logged by mistake, and it's better to save slots and chirping battery power for + * stuff that really matters. + * + * The face will continue to record an activity past the normal one-hour mark, when the watch + * enters low energy mode. However, it will always stop at 8 hours. If an activity takes that long, + * you probably just forgot to stop logging. + * + * The log is stored in regular memory. It will be lost when you remove the battery, so make + * sure you chirp it out before taking the watch apart. + * + * See the top of activity_face.c for some customization options. What you most likely want to do + * is reduce the list of activities shown on the first screen to the ones you are regularly doing. + * + */ + +void activity_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void activity_face_activate(movement_settings_t *settings, void *context); +bool activity_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void activity_face_resign(movement_settings_t *settings, void *context); + +#define activity_face ((const watch_face_t){ \ + activity_face_setup, \ + activity_face_activate, \ + activity_face_loop, \ + activity_face_resign, \ + NULL, \ +}) + +#endif // ACTIVITY_FACE_H_ + diff --git a/movement/watch_faces/complication/breathing_face.c b/movement/watch_faces/complication/breathing_face.c new file mode 100644 index 00000000..8c1fdec7 --- /dev/null +++ b/movement/watch_faces/complication/breathing_face.c @@ -0,0 +1,208 @@ +/* + * MIT License + * + * Copyright (c) 2023 Bernd Plontsch + * + * 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 +#include +#include "breathing_face.h" +#include "watch.h" + +typedef struct { + uint8_t current_stage; + bool sound_on; +} breathing_state_t; + +static void beep_in (void); +static void beep_in_hold (void); +static void beep_out (void); +static void beep_out_hold (void); + +void breathing_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr) { + // These next two lines just silence the compiler warnings associated with unused parameters. + // We have no use for the settings or the watch_face_index, so we make that explicit here. + (void) settings; + (void) watch_face_index; + // At boot, context_ptr will be NULL indicating that we don't have anyplace to store our context. + if (*context_ptr == NULL) { + // in this case, we allocate an area of memory sufficient to store the stuff we need to track. + *context_ptr = malloc(sizeof(breathing_state_t)); + } +} + +void breathing_face_activate(movement_settings_t *settings, void *context) { + // same as above: silence the warning, we don't need to check the settings. + (void) settings; + // we do however need to set some things in our context. Here we cast it to the correct type... + breathing_state_t *state = (breathing_state_t *)context; + // ...and set the initial state of our watch face. + state->current_stage = 0; + state->sound_on = true; +} + +const int NOTE_LENGTH = 80; + +void beep_in (void) { + const BuzzerNote notes[] = { + BUZZER_NOTE_C4, + BUZZER_NOTE_D4, + BUZZER_NOTE_E4, + }; + const uint16_t durations[] = { + NOTE_LENGTH, + NOTE_LENGTH, + NOTE_LENGTH + }; + for(size_t i = 0, count = sizeof(notes) / sizeof(notes[0]); i < count; i++) { + watch_buzzer_play_note(notes[i], durations[i]); + } +} + +void beep_in_hold (void) { + const BuzzerNote notes[] = { + BUZZER_NOTE_E4, + BUZZER_NOTE_REST, + BUZZER_NOTE_E4, + }; + const uint16_t durations[] = { + NOTE_LENGTH, + NOTE_LENGTH * 2, + NOTE_LENGTH, + }; + for(size_t i = 0, count = sizeof(notes) / sizeof(notes[0]); i < count; i++) { + watch_buzzer_play_note(notes[i], durations[i]); + } +} + +void beep_out (void) { + const BuzzerNote notes[] = { + BUZZER_NOTE_E4, + BUZZER_NOTE_D4, + BUZZER_NOTE_C4, + }; + const uint16_t durations[] = { + NOTE_LENGTH, + NOTE_LENGTH, + NOTE_LENGTH, + }; + for(size_t i = 0, count = sizeof(notes) / sizeof(notes[0]); i < count; i++) { + watch_buzzer_play_note(notes[i], durations[i]); + } +} + +void beep_out_hold (void) { + const BuzzerNote notes[] = { + BUZZER_NOTE_C4, + BUZZER_NOTE_REST * 2, + BUZZER_NOTE_C4, + }; + const uint16_t durations[] = { + NOTE_LENGTH, + NOTE_LENGTH, + NOTE_LENGTH, + }; + for(size_t i = 0, count = sizeof(notes) / sizeof(notes[0]); i < count; i++) { + watch_buzzer_play_note(notes[i], durations[i]); + } +} + +bool breathing_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + (void) settings; + breathing_state_t *state = (breathing_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + case EVENT_TICK: + + if (state->sound_on == true) { + watch_set_indicator(WATCH_INDICATOR_BELL); + } else { + watch_clear_indicator(WATCH_INDICATOR_BELL); + } + + switch (state->current_stage) + { + case 0: { watch_display_string("Breath", 4); if (state->sound_on) beep_in(); } break; + case 1: watch_display_string("In 3", 4); break; + case 2: watch_display_string("In 2", 4); break; + case 3: watch_display_string("In 1", 4); break; + + case 4: { watch_display_string("Hold 4", 4); if (state->sound_on) beep_in_hold(); } break; + case 5: watch_display_string("Hold 3", 4); break; + case 6: watch_display_string("Hold 2", 4); break; + case 7: watch_display_string("Hold 1", 4); break; + + case 8: { watch_display_string("Ou t 4", 4); if (state->sound_on) beep_out(); } break; + case 9: watch_display_string("Ou t 3", 4); break; + case 10: watch_display_string("Ou t 2", 4); break; + case 11: watch_display_string("Ou t 1", 4); break; + + case 12: { watch_display_string("Hold 4", 4); if (state->sound_on) beep_out_hold(); } break; + case 13: watch_display_string("Hold 3", 4); break; + case 14: watch_display_string("Hold 2", 4); break; + case 15: watch_display_string("Hold 1", 4); break; + default: + break; + } + + // and increment it so that it will update on the next tick. + state->current_stage = (state->current_stage + 1) % 16; + + break; + case EVENT_ALARM_BUTTON_UP: + state->sound_on = !state->sound_on; + if (state->sound_on == true) { + watch_set_indicator(WATCH_INDICATOR_BELL); + } else { + watch_clear_indicator(WATCH_INDICATOR_BELL); + } + break; + case EVENT_LOW_ENERGY_UPDATE: + // This low energy mode update occurs once a minute, if the watch face is in the + // foreground when Movement enters low energy mode. We have the option of supporting + // this mode, but since our watch face animates once a second, the "Hello there" face + // isn't very useful in this mode. So we choose not to support it. (continued below) + break; + case EVENT_TIMEOUT: + // ... Instead, we respond to the timeout event. This event happens after a configurable + // interval on screen (1-30 minutes). The watch will give us this event as a chance to + // resign control if we want to, and in this case, we do. + // This function will return the watch to the first screen (usually a simple clock), + // and it will do it long before the watch enters low energy mode. This ensures we + // won't be on screen, and thus opts us out of getting the EVENT_LOW_ENERGY_UPDATE above. + + // movement_move_to_face(0); + break; + default: + movement_default_loop_handler(event, settings); + break; + } + + return true; +} + +void breathing_face_resign(movement_settings_t *settings, void *context) { + // our watch face, like most watch faces, has nothing special to do when resigning. + // watch faces that enable a peripheral or interact with a sensor may want to turn it off here. + (void) settings; + (void) context; +} diff --git a/movement/watch_faces/complication/breathing_face.h b/movement/watch_faces/complication/breathing_face.h new file mode 100644 index 00000000..2ff947a2 --- /dev/null +++ b/movement/watch_faces/complication/breathing_face.h @@ -0,0 +1,43 @@ +/* + * MIT License + * + * Copyright (c) 2023 Bernd Plontsch + * + * 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 BREATHING_FACE_H_ +#define BREATHING_FACE_H_ + +#include "movement.h" + +void breathing_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void breathing_face_activate(movement_settings_t *settings, void *context); +bool breathing_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void breathing_face_resign(movement_settings_t *settings, void *context); + +#define breathing_face ((const watch_face_t){ \ + breathing_face_setup, \ + breathing_face_activate, \ + breathing_face_loop, \ + breathing_face_resign, \ + NULL, \ +}) + +#endif // BREATHING_FACE_H_ diff --git a/movement/watch_faces/complication/day_one_face.c b/movement/watch_faces/complication/day_one_face.c index 7ce43bfa..25ce1c23 100644 --- a/movement/watch_faces/complication/day_one_face.c +++ b/movement/watch_faces/complication/day_one_face.c @@ -33,7 +33,7 @@ static uint32_t _day_one_face_juliandaynum(uint16_t year, uint16_t month, uint16 } static void _day_one_face_update(day_one_state_t state) { - char buf[14]; + char buf[15]; watch_date_time date_time = watch_rtc_get_date_time(); uint32_t julian_date = _day_one_face_juliandaynum(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR, date_time.unit.month, date_time.unit.day); uint32_t julian_birthdate = _day_one_face_juliandaynum(state.birth_year, state.birth_month, state.birth_day); diff --git a/movement/watch_faces/complication/discgolf_face.c b/movement/watch_faces/complication/discgolf_face.c new file mode 100644 index 00000000..0852bf1f --- /dev/null +++ b/movement/watch_faces/complication/discgolf_face.c @@ -0,0 +1,326 @@ +#include +#include +#include "discgolf_face.h" +#include "watch.h" // Remember to change number of courses in this file +#include "watch_utility.h" + +/* + * Keep track of scores in discgolf or golf! + * The watch face operates in three different modes: + * + * - dg_setting: Select a course + * Enter this mode by holding down the light button. The screen will display + * the label for the hole and the lowest score since last boot. + * Press alarm to loop through the holes. Press the light button to make a + * selection. This will reset all scores and start a new game in dg_idle mode. + * + * -dg_idle: We're playing a hole + * This either shows your current score relative to par, or the score for a + * particular hole. + * At the start of a game, press alarm to loop through the holes and leave it + * your starting hole. For optimal experience, play the course linearly after that + * If you're viewing the hole you're supposed to be playing, the watch face will + * display your score relative to par. + * Use the alarm button to view other holes than the one you're playing, in which + * case the input score for that hole will be displayed, in case it needs changing. + * Long press the alarm button to snap back to currently playing hole. + * To input scores for a hole in this mode, press the light button. + * + * -dg_scoring: Input score for a hole + * In this mode, if the score is 0 (hasn't been entered during this round), + * it will blink, indicating we're in scoring mode. Press the alarm button + * to increment the score up until 15, in which case it loops back to 0. + * Press the light button to save the score for that hole, advance one hole + * if you're not editing an already input score, and returning to idle mode. + * + * When all scores have been entered, the LAP indicator turns on. At that point, if we enter + * dg_setting to select a course, the score for that round is evaluated against the current + * lowest score for that course, and saved if it is better. +*/ +/////////////////////////////////////////////////////////////////////////////////////////////// +// Enter course data +/* Initialize lowest scores with a high number */ +int8_t best[courses]; + +static const uint8_t pars[][18] = { + { 3, 3, 4, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }, // Grafarholt + { 3, 4, 3, 3, 4, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 3 }, // Gufunes + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Vífilsstaðir + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Dalvegur + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Laugardalur + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0 }, // Guðmundarlundur + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Víðistaðatún + { 3, 3, 3, 4, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Fossvogur + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Klambratún + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // Seljahverfi + { 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 } // Fella- og Hóla +}; +static const uint8_t holes[] = { // Number of holes on each course + 18, + 18, + 10, + 10, + 10, + 10, + 9, + 9, + 9, + 9, + 9 +}; +/* Two-letter descriptive labels, second field can only be A, B, C, D, E, F, H, I, J, L, N, O, R, T, U and X. */ +static const char labels[][2] = { + { 'G', 'H' }, + { 'G', 'N' }, + { 'V', 'I' }, + { 'D', 'V' }, + { 'L', 'A' }, + { 'G', 'L' }, + { 'V', 'T' }, + { 'F', 'V' }, + { 'K', 'T' }, + { 'S', 'E' }, + { 'F', 'H' } +}; + +// End of course data +/////////////////////////////////////////////////////////////////////////////////////////////// + +/* Beep function */ +static inline void beep(movement_settings_t *settings) { + if (settings->bit.button_should_sound) watch_buzzer_play_note(BUZZER_NOTE_C7, 50); +} + +/* Prep for a new round */ +static inline void reset(discgolf_state_t *state) { + for (int i = 0; i < holes[state->course]; i++) { + state->scores[i] = 0; + } + state->hole = 1; + watch_clear_indicator(WATCH_INDICATOR_LAP); + return; +} + +/* Total number of throws so far */ +static inline uint8_t score_sum(discgolf_state_t *state) { + uint8_t sum = 0; + for (int i = 0; i < holes[state->course]; i++) { + sum = sum + state->scores[i]; + } + return sum; +} + +/* Count how many holes have been played */ +static inline uint8_t count_played(discgolf_state_t *state) { + uint8_t holes_played = 0; + for (int i = 0; i < holes[state->course]; i++) { + if (state->scores[i] > 0) holes_played++; + } + return holes_played; +} + + +/* Calculate the current score relative to par */ +static inline int8_t calculate_score(discgolf_state_t *state) { + uint8_t par_sum = 0; + uint8_t score_sum = 0; + + for (int i = 0; i < holes[state->course]; i++) { + if (state->scores[i] > 0) { + par_sum = par_sum + pars[state->course][i]; + score_sum = score_sum + state->scores[i]; + } + } + return score_sum - par_sum; +} + +/* Store score if it's the best so far */ +static inline void store_best(discgolf_state_t *state) { + uint8_t played = count_played(state); + if ( played == holes[state->course] ) { + int8_t high_score = calculate_score(state); + if (high_score < best[state->course] ) { + best[state->course] = high_score; + } + } +} + +/* Configuration at boot, the high score array can be initialized with your high scores if they're known */ +void discgolf_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(discgolf_state_t)); + discgolf_state_t *state = (discgolf_state_t *)*context_ptr; + memset(*context_ptr, 0, sizeof(discgolf_state_t)); + state->hole = 1; + state->course = 0; + state->playing = holes[state->course] + 1; + for (int i = 0; i < courses; i++) best[i] = 99; + state->mode = dg_setting; + } +} + +void discgolf_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + watch_clear_colon(); + discgolf_state_t *state = (discgolf_state_t *)context; + + /* If we were playing, go to current hole */ + if (state->playing <= holes[0]) { + state->hole = state->playing; + } + /* Set LAP if round finished */ + if (count_played(state) == holes[state->course] ) { + watch_set_indicator(WATCH_INDICATOR_LAP); + } + movement_request_tick_frequency(4); +} + +bool discgolf_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + (void) settings; + + discgolf_state_t *state = (discgolf_state_t *)context; + + switch (event.event_type) { + case EVENT_TIMEOUT: + /* Snap to first screen if we're not playing*/ + if ( count_played(state) == holes[state->course] || state->mode == dg_setting) { + movement_move_to_face(0); + } + /* Cancel scoring if timed out */ + if (state->mode == dg_scoring) { + state->scores[state->hole] = 0; + state->mode = dg_idle; + } + break; + /* Advance if not scoring */ + case EVENT_MODE_BUTTON_UP: + if ( state->mode != dg_scoring ) { + movement_move_to_next_face(); + } + break; + /* Go to default face if not scoring */ + case EVENT_MODE_LONG_PRESS: + if ( state->mode != dg_scoring ) { + movement_move_to_face(0); + } + break; + case EVENT_LIGHT_BUTTON_UP: + switch ( state->mode ) { + case dg_idle: + /* Check if selected hole is the first one */ + if ( score_sum(state) == 0 ) { + state->playing = state->hole; + } + /* Enter scoring mode */ + state->mode = dg_scoring; + break; + case dg_scoring: + /* Set the LAP indicator if all scores are entered */ + if (count_played(state) == holes[state->course] ) { + watch_set_indicator(WATCH_INDICATOR_LAP); + } + /* Advance to next hole if not editing previously set score */ + if ( state->hole == state->playing ) { + if (state->hole < holes[state->course]) state->hole++; + else state->hole = 1; + if (state->playing < holes[state->course]) state->playing++; + else state->playing = 1; + } + /* Return to idle */ + state->mode = dg_idle; + break; + case dg_setting: + /* Return to idle */ + state->playing = holes[state->course] + 1; + state->mode = dg_idle; + break; + } + beep(settings); + break; + case EVENT_ALARM_BUTTON_UP: + switch (state->mode) { + /* Setting, loop through courses */ + case dg_setting: + state->course = (state->course + 1) % courses; + break; + /* Scoring, increment score for current hole */ + case dg_scoring: + state->scores[state->hole - 1] = (state->scores[state->hole - 1] + 1) % 16; // Loop around at 15 + break; + /* Idle, loop through holes */ + case dg_idle: + if (state->hole < holes[state->course]) { + state->hole++; + } else { state->hole = 1; } + break; + } + break; + case EVENT_LIGHT_LONG_PRESS: + /* Enter setting mode, reset state */ + if ( state->mode == dg_idle ) { + state->mode = dg_setting; + store_best(state); + reset(state); + beep(settings); + } + break; + case EVENT_ALARM_LONG_PRESS: + /* Snap back to currently playing hole if we've established one*/ + if ( (state->mode == dg_idle) && (state->hole != state->playing) && (state->playing <= holes[state->course]) ) { + state->hole = state->playing; + beep(settings); + } + break; + default: + break; + } + + char buf[21]; + char prefix; + int8_t diff; + + switch (state->mode) { + /* Setting mode, display course label and high score */ + case dg_setting: + if ( best[state->course] < 0 ) { + prefix = '-'; + } else { prefix = ' '; } + sprintf(buf, "%c%c %c%2d ", labels[state->course][0], labels[state->course][1], prefix, abs(best[state->course])); + break; + /* Idle, show relative or input score */ + case dg_idle: + if (state->hole == state->playing) { + diff = calculate_score(state); + if ( diff < 0 ) { + prefix = '-'; + } else { prefix = ' '; } + sprintf(buf, "%c%c%2d %c%2d ", labels[state->course][0], labels[state->course][1], state->hole, prefix, abs(diff)); + } else { + sprintf(buf, "%c%c%2d %2d ", labels[state->course][0], labels[state->course][1], state->hole, state->scores[state->hole - 1]); + } + break; + /* Scoring, show set score */ + case dg_scoring: + sprintf(buf, "%c%c%2d %2d ", labels[state->course][0], labels[state->course][1], state->hole, state->scores[state->hole - 1]); + break; + } + + /* Blink during scoring */ + if (event.subsecond % 2 && state->mode == dg_scoring) { + buf[6] = buf[7] = ' '; + } + + /* Draw screen */ + watch_display_string(buf, 0); + + return true; +} + +void discgolf_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + watch_clear_indicator(WATCH_INDICATOR_LAP); +} diff --git a/movement/watch_faces/complication/discgolf_face.h b/movement/watch_faces/complication/discgolf_face.h new file mode 100644 index 00000000..5e8068e0 --- /dev/null +++ b/movement/watch_faces/complication/discgolf_face.h @@ -0,0 +1,95 @@ +/* + * MIT License + * + * Copyright (c) 2023 Þorsteinn Jón Gautason + * + * 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. + */ + +///////////////////////////////////////////////////////////////////////////////////// + +/* + * Keep track of scores in discgolf or golf! + * The watch face operates in three different modes: + * + * - dg_setting: Select a course + * Enter this mode by holding down the light button. The screen will display + * the label for the hole and the lowest score since last boot. + * Press alarm to loop through the holes. Press the light button to make a + * selection. This will reset all scores and start a new game in dg_idle mode. + * + * -dg_idle: We're playing a hole + * This either shows your current score relative to par, or the score for a + * particular hole. + * At the start of a game, press alarm to loop through the holes and leave it + * your starting hole. For optimal experience, play the course linearly after that + * If you're viewing the hole you're supposed to be playing, the watch face will + * display your score relative to par. + * Use the alarm button to view other holes than the one you're playing, in which + * case the input score for that hole will be displayed, in case it needs changing. + * Long press the alarm button to snap back to currently playing hole. + * To input scores for a hole in this mode, press the light button. + * + * -dg_scoring: Input score for a hole + * In this mode, if the score is 0 (hasn't been entered during this round), + * it will blink, indicating we're in scoring mode. Press the alarm button + * to increment the score up until 15, in which case it loops back to 0. + * Press the light button to save the score for that hole, advance one hole + * if you're not editing an already input score, and returning to idle mode. + * + * When all scores have been entered, the LAP indicator turns on. At that point, if we enter + * dg_setting to select a course, the score for that round is evaluated against the current + * lowest score for that course, and saved if it is better. +*/ + + +#ifndef DISCGOLF_FACE_H_ +#define DISCGOLF_FACE_H_ + +#include "movement.h" +#define courses 11 + +typedef enum { + dg_setting, // We are selecting a course + dg_scoring, // We are inputting our score + dg_idle, // We have input our score and are playing a hole +} discgolf_mode_t; + +typedef struct { + uint8_t course; // Index for course selection, from 0 + uint8_t hole; // Index for current hole, from 1 + uint8_t playing; // Current hole + int scores[18]; // Scores for each played hole + discgolf_mode_t mode; // Watch face mode +} discgolf_state_t; + +void discgolf_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void discgolf_face_activate(movement_settings_t *settings, void *context); +bool discgolf_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void discgolf_face_resign(movement_settings_t *settings, void *context); + +#define discgolf_face ((const watch_face_t){ \ + discgolf_face_setup, \ + discgolf_face_activate, \ + discgolf_face_loop, \ + discgolf_face_resign, \ + NULL, \ +}) + +#endif // DISCGOLF_FACE_H_ diff --git a/movement/watch_faces/complication/dual_timer_face.c b/movement/watch_faces/complication/dual_timer_face.c new file mode 100644 index 00000000..f98c35b4 --- /dev/null +++ b/movement/watch_faces/complication/dual_timer_face.c @@ -0,0 +1,334 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * Copyright (c) 2022 Andreas Nebinger + * + * 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 +#include +#include "dual_timer_face.h" +#include "watch.h" +#include "watch_utility.h" +#include "watch_rtc.h" + +/* + * IMPORTANT: This watch face uses the same TC2 callback counter as the Stock Stopwatch + * watch-face. It works through calling a global handler function. The two watch-faces + * therefore can't coexist within the same firmware. If you want to compile this watch-face + * then you need to remove the line <../watch_faces/complication/stock_stopwatch_face.c \> + * from the Makefile. + */ + +// FROM stock_stopwatch_face.c //////////////////////////////////////////////// +// Copyright (c) 2022 Andreas Nebinger + +#if __EMSCRIPTEN__ +#include +#include +#else +#include "../../../watch-library/hardware/include/saml22j18a.h" +#include "../../../watch-library/hardware/include/component/tc.h" +#include "../../../watch-library/hardware/hri/hri_tc_l22.h" +#endif + +static const watch_date_time distant_future = {.unit = {0, 0, 0, 1, 1, 63}}; +static bool _is_running; +static uint32_t _ticks; + +#if __EMSCRIPTEN__ + +static long _em_interval_id = 0; + +void em_dual_timer_cb_handler(void *userData) { + // interrupt handler for emscripten 128 Hz callbacks + (void) userData; + _ticks++; +} + +static void _dual_timer_cb_initialize() { } + +static inline void _dual_timer_cb_stop() { + emscripten_clear_interval(_em_interval_id); + _em_interval_id = 0; + _is_running = false; +} + +static inline void _dual_timer_cb_start() { + // initiate 128 hz callback + _em_interval_id = emscripten_set_interval(em_dual_timer_cb_handler, (double)(1000/128), (void *)NULL); +} + +#else + +static inline void _dual_timer_cb_start() { + // start the TC2 timer + hri_tc_set_CTRLA_ENABLE_bit(TC2); + _is_running = true; +} + +static inline void _dual_timer_cb_stop() { + // stop the TC2 timer + hri_tc_clear_CTRLA_ENABLE_bit(TC2); + _is_running = false; +} + +static void _dual_timer_cb_initialize() { + // setup and initialize TC2 for a 64 Hz interrupt + hri_mclk_set_APBCMASK_TC2_bit(MCLK); + hri_gclk_write_PCHCTRL_reg(GCLK, TC2_GCLK_ID, GCLK_PCHCTRL_GEN_GCLK3 | GCLK_PCHCTRL_CHEN); + _dual_timer_cb_stop(); + hri_tc_write_CTRLA_reg(TC2, TC_CTRLA_SWRST); + hri_tc_wait_for_sync(TC2, TC_SYNCBUSY_SWRST); + hri_tc_write_CTRLA_reg(TC2, TC_CTRLA_PRESCALER_DIV64 | // 32 Khz divided by 64 divided by 4 results in a 128 Hz interrupt + TC_CTRLA_MODE_COUNT8 | + TC_CTRLA_RUNSTDBY); + hri_tccount8_write_PER_reg(TC2, 3); + hri_tc_set_INTEN_OVF_bit(TC2); + NVIC_ClearPendingIRQ(TC2_IRQn); + NVIC_EnableIRQ (TC2_IRQn); +} + +// you need to take stock_stopwatch.c out of the Makefile or this will create a conflict +// you have to choose between one of the stopwatches + void TC2_Handler(void) { + // interrupt handler for TC2 (globally!) + _ticks++; + TC2->COUNT8.INTFLAG.reg |= TC_INTFLAG_OVF; +} + +#endif + +// STATIC FUNCTIONS /////////////////////////////////////////////////////////// + +/** @brief converts tick counts to duration struct for time display + */ +static dual_timer_duration_t ticks_to_duration(uint32_t ticks) { + dual_timer_duration_t duration; + uint8_t hours = 0; + uint8_t days = 0; + + // count hours and days + while (ticks >= (128 * 60 * 60)) { + ticks -= (128 * 60 * 60); + hours++; + if (hours >= 24) { + hours -= 24; + days++; + } + } + + // convert minutes, seconds, centiseconds + duration.centiseconds = (ticks & 0x7F) * 100 / 128; + duration.seconds = (ticks >> 7) % 60; + duration.minutes = (ticks >> 7) / 60; + duration.hours = hours; + duration.days = days; + + return duration; +} + +/** @brief starts one of the dual timers + * @details Starts a dual timer. If no previous timer is running it starts the global + * tick counter. If a previous timer is already running it registers the current tick. + */ +static void start_timer(dual_timer_state_t *state, bool timer) { + // if it is not running yet, run it + if ( !_is_running ) { + _is_running = true; + movement_request_tick_frequency(16); + state->start_ticks[timer] = 0; + state->stop_ticks[timer] = 0; + _ticks = 0; + _dual_timer_cb_start(); + movement_schedule_background_task(distant_future); + } else { + // if another timer is already running save the current tick + state->start_ticks[timer] = _ticks; + state->stop_ticks[timer] = _ticks; + } + state->running[timer] = true; +} + +/** @brief stops one of the dual timers + * @details Stops a dual timer. If no other timer is running it stops the global + * tick counter. If another timer is already running it registers the current stop tick. + */ +static void stop_timer(dual_timer_state_t *state, bool timer) { + // stop timer and save duration + state->stop_ticks[timer] = _ticks; + state->duration[timer] = ticks_to_duration(state->stop_ticks[timer] - state->start_ticks[timer]); + state->running[timer] = false; + // if the other timer is not running, stop callback + if ( state->running[!timer] == false ) { + _is_running = false; + _dual_timer_cb_stop(); + movement_request_tick_frequency(1); + movement_cancel_background_task(); + } +} + +/** @brief displays the measured time for each of the dual timers + * @details displays the dual timer. Below 1 hour it displays the timed minutes, seconds, + * and centiseconds. Above that it shows the timed hours, minutes, and seconds. If it + * has run for more than a day it shows the days, hours, and minutes. + * When the timer is running, the colon blinks every half second. + * It also indicates at the top if another counter is running and for how long. + */ +static void dual_timer_display(dual_timer_state_t *state) { + char buf[11]; + char oi[3]; + // get the current time count of the selected counter + dual_timer_duration_t timer = state->running[state->show] ? ticks_to_duration(state->stop_ticks[state->show] - state->start_ticks[state->show]) : state->duration[state->show]; + // get the current time count of the other counter + dual_timer_duration_t other = ticks_to_duration(state->stop_ticks[!state->show] - state->start_ticks[!state->show]); + + if ( timer.days > 0 ) + sprintf(buf, "%02u%02u%02u", timer.days, timer.hours, timer.minutes); + else if ( timer.hours > 0 ) + sprintf(buf, "%02u%02u%02u", timer.hours, timer.minutes, timer.seconds); + else + sprintf(buf, "%02u%02u%02u", timer.minutes, timer.seconds, timer.centiseconds); + watch_display_string(buf, 4); + + // which counter is displayed + watch_display_string(state->show ? "B" : "A", 0); + + // indicate whether other counter is running + watch_display_string(state->running[!state->show] && (_ticks % 100) < 50 ? "+" : " ", 1); + + // indicate for how long the other counter has been running + sprintf(oi, "%2u", other.days > 0 ? other.days : (other.hours > 0 ? other.hours : (other.minutes > 0 ? other.minutes : (other.seconds > 0 ? other.seconds : other.centiseconds)))); + watch_display_string( (state->stop_ticks[!state->show] - state->start_ticks[!state->show]) > 0 ? oi : " ", 2); + + // blink colon when running + if ( timer.centiseconds > 50 || !state->running[state->show] ) watch_set_colon(); + else watch_clear_colon(); +} + +// PUBLIC WATCH FACE FUNCTIONS //////////////////////////////////////////////// + +void dual_timer_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(dual_timer_state_t)); + memset(*context_ptr, 0, sizeof(dual_timer_state_t)); + _ticks = 0; + } + if (!_is_running) { + _dual_timer_cb_initialize(); + } +} + +void dual_timer_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + if (_is_running) { + movement_schedule_background_task(distant_future); + } +} + +bool dual_timer_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + dual_timer_state_t *state = (dual_timer_state_t *)context; + + // timers stop at 99:23:59:59:99 + if ( (_ticks - state->start_ticks[0]) >= 1105919999 ) + stop_timer(state, 0); + + if ( (_ticks - state->start_ticks[1]) >= 1105919999 ) + stop_timer(state, 1); + + switch (event.event_type) { + case EVENT_ACTIVATE: + watch_set_colon(); + if (_is_running) { + movement_request_tick_frequency(16); + if ( state->running[0] ) + state->show = 0; + else state->show = 1; + } else { + if (state->stop_ticks[0] > 0 || state->stop_ticks[1] > 0) + dual_timer_display(state); + else watch_display_string("A 000000", 0); + } + break; + case EVENT_TICK: + if ( _is_running ) { + // update stop ticks + if ( state->running[0] ) + state->stop_ticks[0] = _ticks; + if ( state->running[1] ) + state->stop_ticks[1] = _ticks; + dual_timer_display(state); + } + break; + case EVENT_LIGHT_BUTTON_DOWN: + // start/stop timer B + state->running[1] = !state->running[1]; + if ( state->running[1] ) { + start_timer(state, 1); + } else { + stop_timer(state, 1); + } + break; + case EVENT_ALARM_BUTTON_DOWN: + // start/stop timer A + state->running[0] = !state->running[0]; + if ( state->running[0] ) { + start_timer(state, 0); + } else { + stop_timer(state, 0); + } + break; + case EVENT_MODE_BUTTON_DOWN: + // switch between the timers + state->show = !state->show; + dual_timer_display(state); + break; + case EVENT_MODE_BUTTON_UP: + // don't switch to next face... + break; + case EVENT_MODE_LONG_PRESS: + // ...but do it on long press MODE! + movement_move_to_next_face(); + break; + case EVENT_TIMEOUT: + // go back to + if (!_is_running) movement_move_to_face(0); + break; + case EVENT_LOW_ENERGY_UPDATE: + dual_timer_display(state); + break; + default: + return movement_default_loop_handler(event, settings); + } + + return true; +} + +void dual_timer_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + movement_cancel_background_task(); + // handle any cleanup before your watch face goes off-screen. +} + diff --git a/movement/watch_faces/complication/dual_timer_face.h b/movement/watch_faces/complication/dual_timer_face.h new file mode 100644 index 00000000..d7c6cfa0 --- /dev/null +++ b/movement/watch_faces/complication/dual_timer_face.h @@ -0,0 +1,111 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * Copyright (c) 2022 Andreas Nebinger + * + * 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 DUAL_TIMER_FACE_H_ +#define DUAL_TIMER_FACE_H_ + +#include "movement.h" + +/* + * IMPORTANT: This watch face uses the same TC2 callback counter as the Stock Stopwatch + * watch-face. It works through calling a global handler function. The two watch-faces + * therefore can't coexist within the same firmware. If you want to compile this watch-face + * then you need to remove the line <../watch_faces/complication/stock_stopwatch_face.c \> + * from the Makefile. + */ + +/* + * DUAL TIMER + * ========== + * + * Inspired by special ops and tactical trope targeted watches like the Nixon Regulus + * that feature two chronographs for timing two simultaneous events, here is a watch + * face that expands upon Andreas Nebinger's Stock Stopwatch Face code to implement this + * functionality. + * + * ALARM starts/stops timer A, resets on the next start + * LIGHT starts/stops timer B, resets on the next start + * + * When a timer is running, tapping MODE toggles between displaying timers A or B, as + * indicated at the top of the display. + * + * The currently selected timer shows minutes, seconds, and 100ths of seconds until the + * timed event passes the hour mark. Then it shows hours, minutes, and seconds. Once + * it runs for more than a day it shows days, hours, and minutes. The blinking colon + * indicates that the timer is running. + * + * The longest time span the timers are able to track as 99 days and 23:59:59:99 hours and + * they will simply stop. + * + * If the other timer that is not currently selected is also running then a plus sign is + * blinking next to the A or B indicator. Its progress is indicated by showing the timer's + * currently highest time unit ( 100ths of seconds if less than a second, seconds if less + * than a minute, minutes if less than an hour, hours if less than a day, days if more than + * a day). + * + * Please Note: If at least one timer is running then the default function of the MODE + * button to move to the next watch face is disabled to be able to use it to toggle between + * the timers. In this case LONG PRESSING MODE will move to the next face instead of moving + * back to the default watch face. + * + */ + +typedef struct { + uint8_t centiseconds : 7; // 0-59 + uint8_t seconds : 6; // 0-59 + uint8_t minutes : 6; // 0-59 + uint8_t hours : 5; // 0-23 + uint8_t days : 7; // 0-99 +} dual_timer_duration_t; + +typedef struct { + uint32_t start_ticks[2]; + uint32_t stop_ticks[2]; + dual_timer_duration_t duration[2]; + bool running[2]; + bool show; +} dual_timer_state_t; + +void dual_timer_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void dual_timer_face_activate(movement_settings_t *settings, void *context); +bool dual_timer_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void dual_timer_face_resign(movement_settings_t *settings, void *context); + +#if __EMSCRIPTEN__ +void em_dual_timer_cb_handler(void *userData); +#else +void TC2_Handler(void); +#endif + +#define dual_timer_face ((const watch_face_t){ \ + dual_timer_face_setup, \ + dual_timer_face_activate, \ + dual_timer_face_loop, \ + dual_timer_face_resign, \ + NULL, \ +}) + +#endif // DUAL_TIMER_FACE_H_ + diff --git a/movement/watch_faces/complication/geomancy_face.c b/movement/watch_faces/complication/geomancy_face.c new file mode 100644 index 00000000..c741b2d7 --- /dev/null +++ b/movement/watch_faces/complication/geomancy_face.c @@ -0,0 +1,363 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 +#include +#include "toss_up_face.h" +#include "geomancy_face.h" + +// CONSTANTS ////////////////////////////////////////////////////////////////// + +// The Bagua 八卦 Trigrams encoded as 3bit tribbles, represented as binary integer +static const uint32_t bagua = 0b00000101001110010111011100000000; + +// The King Wen Sequence 文王卦序 of the I Ching 易經 Hexagrams 卦 encoded as an array +// of decimal integers in the order of two combined Trigram tribbles from 0b000000 to +// 0b111111 +static const uint8_t wen_order[] = { + 1, 22, 7, 19, 15, 34, 44, 11, + 14, 51, 38, 52, 61, 55, 30, 32, + 6, 3, 28, 58, 39, 63, 46, 5, + 45, 17, 47, 56, 31, 49, 27, 43, + 23, 26, 2, 41, 50, 20, 16, 24, + 35, 21, 62, 36, 54, 29, 48, 12, + 18, 40, 59, 60, 53, 37, 57, 9, + 10, 25, 4, 8, 33, 13, 42, 0 +}; + +// The geomantic figures encoded as 4 bit nibbles, represented as hexadecimal integer +static const uint64_t geomantic = 0x4ABF39D25E76C180; + +// Abbreviations of the Names of the Geomantic Figures in the order of the 4 bit nibbles +// from 0b0000 to 0b1111 +static const char figures[16][2] = { + "VI" /* Via */, "Hd" /* Head of the Dragon */, "PA" /* Puella */, "GF" /* Greater Fortune*/, + "PR" /* Puer */, "AQ" /* Acquisitio */, "CA" /* Carcer */, "TR" /* Tristitia */, + "Td" /* Tail of the Dragon */, "CO" /* Conjunctio */, "AM" /* Amissio */, "AL" /* Albus */, + "LF" /* Lesser Fortune */, "RU" /* Rubeus */, "LA" /* Laetitia */, "PO" /* Populus */ +}; + +// DECLARATIONS /////////////////////////////////////////////////////////////// + +static void geomancy_face_display(); +static nibble_t _geomancy_pick_figure(); +static tribble_t _iching_pick_trigram(); +static uint8_t _iching_form_hexagram(); +static void _geomancy_display(nibble_t code); +static void _display_hexagram(uint8_t hexagram, char* str); +static void _fix_broken_line(uint8_t hexagram); +static void _throw_animation(geomancy_state_t *state); + +// WATCH FACE FUNCTIONS /////////////////////////////////////////////////////// + +void geomancy_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(geomancy_state_t)); + memset(*context_ptr, 0, sizeof(geomancy_state_t)); + } +} + +void geomancy_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; +} + +bool geomancy_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + geomancy_state_t *state = (geomancy_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + state->animate = false; + state->animation = 0; + watch_display_string(" IChing", 0); + break; + case EVENT_TICK: + if ( state->animate ) { + state->animation = (state->animation + 1) % 39; + geomancy_face_display(state); + } + break; + case EVENT_LIGHT_BUTTON_DOWN: + break; + case EVENT_LIGHT_BUTTON_UP: + if ( state->animate ) break; + if ( state->mode <= 1 ) state->mode = 2; + else if ( state->mode >= 2 ) state->mode = 0; + geomancy_face_display(state); + break; + case EVENT_ALARM_BUTTON_UP: + if ( state->animate ) break; + switch ( state->mode ) { + case 0: + state->mode++; + // fall through + case 1: + state->animate = true; + state->i_ching_hexagram = _iching_form_hexagram(); + break; + case 2: + state->mode++; + // fall through + case 3: + state->animate = true; + state->geomantic_figure = _geomancy_pick_figure().bits; + break; + default: + break; + } + geomancy_face_display(state); + break; + case EVENT_ALARM_LONG_PRESS: + if ( state->animate ) break; + state->caption = !state->caption; + watch_display_string(" ", 0); + geomancy_face_display(state); + break; + default: + return movement_default_loop_handler(event, settings); + } + return true; +} + +void geomancy_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; +} + +// STATIC FUNCTIONS /////////////////////////////////////////////////////////// + +/** @brief display handler */ +static void geomancy_face_display(geomancy_state_t *state); +static void geomancy_face_display(geomancy_state_t *state) { + char token[7] = {0}; + nibble_t figure = *((nibble_t*) &state->geomantic_figure); + switch ( state->mode ) { + case 0: + watch_display_string(" IChing", 0); + break; + case 1: + _throw_animation(state); + if ( !state->animate ) { + _display_hexagram(state->i_ching_hexagram, token); + watch_display_string(token, 4); + _fix_broken_line(state->i_ching_hexagram); + if (state->caption) { + sprintf(token, "%2d", wen_order[state->i_ching_hexagram] + 1); + watch_display_string(token, 2); + } + } + break; + case 2: + watch_display_string(" GeomCy", 0); + break; + case 3: + _throw_animation(state); + if ( !state->animate ) { + if ( state->caption ) { + sprintf(token, "%c%c", figures[state->geomantic_figure][0], figures[state->geomantic_figure][1]); + watch_display_string(token, 0); + } + _geomancy_display(figure); + } + break; + default: + break; + } +} + +/** @brief screen clearing animation between castings */ +static void _throw_animation(geomancy_state_t *state) { + movement_request_tick_frequency(16); + switch ( state->animation ) { + case 0: + watch_set_pixel(0, 22); + break; + case 1: + watch_set_pixel(2, 22); + watch_set_pixel(2, 23); + watch_clear_pixel(0, 22); + break; + case 2: + watch_set_pixel(1, 22); + watch_set_pixel(0, 23); + break; + case 3: + watch_set_pixel(2, 0); + watch_set_pixel(1, 0); + watch_set_pixel(2, 21); + watch_set_pixel(1, 21); + watch_clear_pixel(2, 22); + watch_clear_pixel(1, 22); + watch_clear_pixel(2, 23); + watch_clear_pixel(0, 23); + watch_clear_pixel(1, 23); + break; + case 4: + watch_set_pixel(1, 17); + watch_set_pixel(0, 20); + watch_set_pixel(2, 10); + watch_set_pixel(0, 1); + break; + case 5: + watch_clear_pixel(2, 21); + watch_clear_pixel(1, 21); + watch_clear_pixel(2, 0); + watch_clear_pixel(1, 0); + watch_clear_pixel(1, 20); + watch_clear_pixel(2, 20); + watch_clear_pixel(0, 21); + watch_clear_pixel(1, 1); + watch_clear_pixel(0, 0); + watch_clear_pixel(2, 1); + watch_set_pixel(2, 19); + watch_set_pixel(0, 19); + watch_set_pixel(1, 2); + watch_set_pixel(0, 2); + break; + case 6: + watch_clear_pixel(1, 17); + watch_clear_pixel(0, 20); + watch_clear_pixel(2, 10); + watch_clear_pixel(0, 1); + watch_set_pixel(2, 18); + watch_set_pixel(0, 18); + watch_set_pixel(2, 3); + watch_set_pixel(0, 4); + break; + case 7: + watch_clear_pixel(2, 19); + watch_clear_pixel(0, 19); + watch_clear_pixel(1, 18); + watch_clear_pixel(1, 19); + watch_clear_pixel(1, 2); + watch_clear_pixel(0, 2); + watch_clear_pixel(1, 3); + watch_clear_pixel(0, 3); + watch_clear_pixel(2, 2); + watch_set_pixel(1, 4); + watch_set_pixel(0, 5); + break; + case 8: + watch_clear_pixel(2, 18); + watch_clear_pixel(0, 18); + watch_clear_pixel(2, 3); + watch_clear_pixel(0, 4); + watch_set_pixel(2, 5); + watch_set_pixel(1, 6); + break; + case 9: + watch_clear_pixel(1, 4); + watch_clear_pixel(0, 5); + watch_clear_pixel(1, 5); + watch_clear_pixel(2, 4); + watch_clear_pixel(0, 6); + break; + case 10: + watch_clear_pixel(2, 5); + watch_clear_pixel(1, 6); + break; + case 11: + state->animate = false; + state->animation = 0; + movement_request_tick_frequency(1); + break; + } +} + +// I CHING FUNCTIONS ////////////////////////////////////////////////////////// + +/** @brief form a trigram from three random bit picks + */ +static tribble_t _iching_pick_trigram(void) { + uint8_t index = (divine_bit() << 2) | (divine_bit() << 1) | divine_bit(); + tribble_t trigram = {(bagua >> (3 * index)) & 0b111}; + return trigram; +} + +/** @brief form a hexagram from two trigrams + */ +static uint8_t _iching_form_hexagram(void); +static uint8_t _iching_form_hexagram(void) { + tribble_t inner = _iching_pick_trigram(); + tribble_t outer = _iching_pick_trigram(); + uint8_t hexagram = (inner.bits << 3) | outer.bits; + return hexagram; +} + +/** @brief display hexagram + * @details | for unbroken lines and Ξ for broken lines, left of display is bottom + */ +static void _display_hexagram(uint8_t hexagram, char* str); +static void _display_hexagram(uint8_t hexagram, char* str) { + str[6] = '\0'; // Null-terminate the string + for (uint8_t i = 0; i < 6; i++) { + if (hexagram & (1 << (5 - i))) { + str[i] = '1'; + } else { + str[i] = '='; + } + } +} + +/** @brief when Ξ digits show as = then manually add a line on top + */ +static void _fix_broken_line(uint8_t hexagram) { + for (uint8_t i = 0; i < 6; i++) { + if (!(hexagram & (1 << (5 - i)))) { + if ( i == 1 ) watch_set_pixel(2, 20); + if ( i == 3 ) watch_set_pixel(2, 1); + if ( i == 4 ) watch_set_pixel(2, 2); + if ( i == 5 ) watch_set_pixel(2, 4); + } + } +} + +// GEOMANCY FUNCTIONS ///////////////////////////////////////////////////////// + +/** @brief choose a geomantic figure from four random bits + * @details 0 represents · and 1 represents : counting from the bottom + */ +static nibble_t _geomancy_pick_figure(void); +static nibble_t _geomancy_pick_figure(void) { + uint8_t index = (divine_bit() << 3) | (divine_bit() << 2) | (divine_bit() << 1) | divine_bit(); + nibble_t figure = {(geomantic >> (4 * (15 - index))) & 0xF}; + return figure; +} + +/** @brief display the geomantic figure, left of display is bottom + */ +static void _geomancy_display(nibble_t code) { + // draw geomantic figures + bool row1 = (code.bits >> 3) & 1; + bool row2 = (code.bits >> 2) & 1; + bool row3 = (code.bits >> 1) & 1; + bool row4 = code.bits & 1; + + if ( row1 ) watch_set_pixel(1, 18); else watch_set_pixel(1, 19); + if ( row2 ) { watch_set_pixel(2, 20); watch_set_pixel(0, 21);} else watch_set_pixel(1, 20); + if ( row3 ) watch_set_pixel(0, 22); else watch_set_pixel(1, 23); + if ( row4 ) { watch_set_pixel(2, 1); watch_set_pixel(0, 0);} else watch_set_pixel(1, 1); +} \ No newline at end of file diff --git a/movement/watch_faces/complication/geomancy_face.h b/movement/watch_faces/complication/geomancy_face.h new file mode 100644 index 00000000..4a19ba85 --- /dev/null +++ b/movement/watch_faces/complication/geomancy_face.h @@ -0,0 +1,99 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 GEOMANCY_FACE_H_ +#define GEOMANCY_FACE_H_ + +#include "movement.h" + +/* + * GEOMANCY WATCH FACE + * + * A simple and straightforward watch face for the ancient Eastern geomantic divination system + * of I Ching and the western system of "Geomancy". It is an optional addition to the Toss Up + * Face. + * + * The LIGHT button toggles between the two systems of geomancy. + * + * The ALARM button casts an I Ching hexagram or Geomantic figure based on drawing virtual + * stalks from the True Random Number Generator in the Sensor Watch. + * + * The figures are flipped 90 degrees clockwise, so the left side is the bottom and the + * right side the top. + * + * LONG PRESSING ALARM toggles the display of the King Wen sequence index for the cast I Ching + * Hexagram (https://en.wikipedia.org/wiki/King_Wen_sequence )or the abbreviated name for the + * cast Geomantic Figure: + * + * GF - Greater Fortune (Fortuna Major) + * LF - Lesser Fortune (Fortuna Minor) + * PO - Populus + * VI - Via + * AL - Albus + * CO - Conjunctio + * PA - Puella + * AM - Amissio + * PR - Puer + * RU - Rubeus + * AQ - Acquisitio + * LA - Laetitia + * TR - Tristitia + * CA - Carcer + * HD - Head of the Dragon (Caput Draconis) + * TD - Tail of the Dragon (Cauda Draconis) + * + */ + +typedef struct { + uint8_t bits : 4; +} nibble_t; + +typedef struct { + uint8_t bits : 3; +} tribble_t; + +typedef struct { + uint8_t mode : 3; + uint8_t geomantic_figure; + uint8_t i_ching_hexagram : 6; + bool caption; + uint8_t animation; + bool animate; +} geomancy_state_t; + +void geomancy_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void geomancy_face_activate(movement_settings_t *settings, void *context); +bool geomancy_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void geomancy_face_resign(movement_settings_t *settings, void *context); + +#define geomancy_face ((const watch_face_t){ \ + geomancy_face_setup, \ + geomancy_face_activate, \ + geomancy_face_loop, \ + geomancy_face_resign, \ + NULL, \ +}) + +#endif // GEOMANCY_FACE_H_ + diff --git a/movement/watch_faces/complication/interval_face.c b/movement/watch_faces/complication/interval_face.c index e8ebe321..dabc6b1e 100644 --- a/movement/watch_faces/complication/interval_face.c +++ b/movement/watch_faces/complication/interval_face.c @@ -129,15 +129,15 @@ static const int8_t _sound_seq_break[] = {BUZZER_NOTE_B6, 15, BUZZER_NOTE_REST, static const int8_t _sound_seq_cooldown[] = {BUZZER_NOTE_C7, 15, BUZZER_NOTE_REST, 1, -2, 1, BUZZER_NOTE_C7, 24, 0}; static const int8_t _sound_seq_finish[] = {BUZZER_NOTE_C7, 6, BUZZER_NOTE_E7, 6, BUZZER_NOTE_G7, 6, BUZZER_NOTE_C8, 18, 0}; -interval_setting_idx_t _setting_idx; -int8_t _ticks; -bool _erase_timer_flag; -uint32_t _target_ts; -uint32_t _now_ts; -uint32_t _paused_ts; -uint8_t _timer_work_round; -uint8_t _timer_full_round; -uint8_t _timer_run_state; +static interval_setting_idx_t _setting_idx; +static int8_t _ticks; +static bool _erase_timer_flag; +static uint32_t _target_ts; +static uint32_t _now_ts; +static uint32_t _paused_ts; +static uint8_t _timer_work_round; +static uint8_t _timer_full_round; +static uint8_t _timer_run_state; static inline void _inc_uint8(uint8_t *value, uint8_t step, uint8_t max) { *value += step; diff --git a/movement/watch_faces/complication/invaders_face.c b/movement/watch_faces/complication/invaders_face.c new file mode 100644 index 00000000..c3b13c68 --- /dev/null +++ b/movement/watch_faces/complication/invaders_face.c @@ -0,0 +1,434 @@ +/* + * MIT License + * + * Copyright (c) 2023 Andreas Nebinger + * + * 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 +#endif + +#include +#include +#include "watch_private_display.h" +#include "invaders_face.h" + +#define INVADERS_FACE_WAVES_PER_STAGE 9 // number of waves per stage (there are two stages) +#define INVADERS_FACE_WAVE_INVADERS 16 // number of invaders attacking per wave + +static const uint8_t _defense_lines_segdata[3][2] = {{2, 12}, {2, 11}, {0, 11}}; +static const uint8_t _bonus_points_segdata[4][2] = {{2, 7}, {2, 8}, {2, 9}, {0, 10}}; +static const uint8_t _bonus_points_helper[] = {1, 5, 9, 11, 15, 19, 21, 25, 29}; + +static const int8_t _sound_seq_game_start[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 1, BUZZER_NOTE_REST, 10, BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 1, 0}; +static const int8_t _sound_seq_shot_hit[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 2, 0}; +static const int8_t _sound_seq_shot_miss[] = {BUZZER_NOTE_A7, 1, 0}; +static const int8_t _sound_seq_ufo_hit[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 2, -2, 1, 0}; +static const int8_t _sound_seq_def_gone[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 3, BUZZER_NOTE_REST, 40, BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 4, 0}; +static const int8_t _sound_seq_next_wave[] = {BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, BUZZER_NOTE_REST, 8, BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, -2, 1, + BUZZER_NOTE_REST, 32, + BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, BUZZER_NOTE_REST, 8, BUZZER_NOTE_A6, 2, BUZZER_NOTE_A7, 2, -2, 1, 0}; +static const int8_t _sound_seq_game_over[] = {BUZZER_NOTE_A6, 1, BUZZER_NOTE_A7, 3, -2, 11, 0}; + +typedef enum { + invaders_state_activated, + invaders_state_pre_game, + invaders_state_playing, + invaders_state_in_wave_break, + invaders_state_pre_next_wave, + invaders_state_next_wave, + invaders_state_game_over +} invaders_current_state_t; + +typedef struct { + bool ufo_next : 1; // indicates whether next invader is a ufo + bool inv_checking : 1; // flag to indicate whether we are currently moving invaders (to prevent race conditions) + bool suspend_buttons : 1; // used while playing the game over sequence to prevent involuntary immediate restarts +} invaders_signals_t; + +static int8_t _invaders[6]; // array of current invaders values (-1 = empty, 10 = ufo) +static uint8_t _wave_invaders[INVADERS_FACE_WAVE_INVADERS]; // all invaders for the current wave. (Predefined to save cpu cycles when playing.) +static invaders_current_state_t _current_state; +static uint8_t _defense_lines; // number of defense lines which have been broken in the current wave +static uint8_t _aim; // current "aim" digit +static uint8_t _invader_idx; // index of next invader attacking in current wave (0 to 15) +static uint8_t _wave_position; // current position of first invader. When > 6 the defense is broken +static uint8_t _wave_tick_freq; // number of ticks passing until the next invader is inserted +static uint8_t _ticks; // counts the ticks +static uint8_t _bonus_countdown; // ticks countdown until the bonus point indicator is cleared +static uint8_t _waves; // counts the waves (_wave_tick_freq decreases slowly depending on _wave value) +static uint8_t _shots_in_wave; // number of shots in current wave. If 30 is reached, the game is over +static uint8_t _invaders_shot; // number of sucessfully shot invaders in current wave +static uint8_t _invaders_shot_sum; // current sum of invader digits shot (needed to determine if a ufo is coming) +static invaders_signals_t _signals; // holds severals flags +static uint16_t _score; // score of the current game + +/// @brief return a random number. 0 <= return_value < num_values +static inline uint8_t _get_rand_num(uint8_t num_values) { +#if __EMSCRIPTEN__ + return rand() % num_values; +#else + return arc4random_uniform(num_values); +#endif +} + +/// @brief callback function to re-enable light and alarm buttons after playing a sound sequence +static inline void _resume_buttons() { + _signals.suspend_buttons = false; +} + +/// @brief play a sound sequence if the game is in beepy mode +static inline void _play_sequence(invaders_state_t *state, int8_t *sequence) { + if (state->sound_on) watch_buzzer_play_sequence((int8_t *)sequence, NULL); +} + +/// @brief draw the remaining defense lines +static void _display_defense_lines() { + watch_display_character(' ', 1); + for (uint8_t i = 0; i < 3 - _defense_lines; i++) watch_set_pixel(_defense_lines_segdata[i][0], _defense_lines_segdata[i][1]); +} + +/** @brief draw label followed by the given score value + * @param label string displayed in the upper left corner + * @param score score to display + */ +static void _display_score(char *label, uint16_t score) { + watch_display_character(label[0], 0); + watch_display_character(label[1], 1); + char buf[10]; + sprintf(buf, " %06d", (score * 10)); + watch_display_string(buf, 2); +} + +/// @brief draw an invader at the given position +static inline void _display_invader(int8_t invader, uint8_t position) { + switch (invader) { + case 10: + watch_display_character('n', position); + break; + case -1: + watch_display_character(' ', position); + break; + default: + watch_display_character(invader + 48, position); + break; + } +} + +/// @brief game over: show score and set state +static void _game_over(invaders_state_t *state) { + _display_score("GO", _score); + _current_state = invaders_state_game_over; + movement_request_tick_frequency(1); + _signals.suspend_buttons = true; + if (state->sound_on) watch_buzzer_play_sequence((int8_t *)_sound_seq_game_over, _resume_buttons); + // save current score to highscore, if applicable + if (_score > state->highscore) state->highscore = _score; +} + +/// @brief initialize the current wave +static void _init_wave() { + uint8_t i; + if (_current_state == invaders_state_in_wave_break) { + _invader_idx = _invaders_shot; + } else { + _invader_idx = _invaders_shot = _invaders_shot_sum = _defense_lines = _shots_in_wave = 0; + } + // pre-fill invaders + for (i = _invader_idx; i < INVADERS_FACE_WAVE_INVADERS; i++) _wave_invaders[i] = _get_rand_num(10); + // init invaders field + for (i = 1; i < 6; i++) _invaders[i] = -1; + _invaders[0] = _wave_invaders[_invader_idx]; + _wave_position = _aim = _bonus_countdown = 0; + _signals.ufo_next = _signals.inv_checking = _signals.suspend_buttons = false; + _current_state = invaders_state_playing; + // determine wave speed + _wave_tick_freq = 6 - ((_waves % INVADERS_FACE_WAVES_PER_STAGE) + 1) / 2; + if (_waves >= INVADERS_FACE_WAVES_PER_STAGE) _wave_tick_freq--; + // clear display + watch_display_string(" ", 2); + watch_display_character('0', 0); + _display_defense_lines(); + // draw first invader + watch_display_character(_wave_invaders[_invader_idx] + 48, 9); +} + +/** @brief move invaders and add a new one, if necessary + * @returns true, if invaders have reached position 6, false otherwise + */ +static bool _move_invaders() { + if (_wave_position == 5) return true; + _signals.inv_checking = true; + if (_invaders[_wave_position] >= 0) _wave_position++; + int8_t i; + // move invaders + for (i = _wave_position; i > 0; i--) _invaders[i] = _invaders[i - 1]; + if (_invader_idx < INVADERS_FACE_WAVE_INVADERS - 1) { + // add invader + _invader_idx++; + if (_signals.ufo_next) { + _invaders[0] = 10; + _signals.ufo_next = false; + } else { + _invaders[0] = _wave_invaders[_invader_idx]; + } + } else { + // just add an empty invader slot + _invaders[0] = -1; + } + // update display + for (i = 0; i <= _wave_position; i++) { + _display_invader(_invaders[i], 9 - i); + } + _signals.inv_checking = false; + return false; +} + +void invaders_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(invaders_state_t)); + memset(*context_ptr, 0, sizeof(invaders_state_t)); + invaders_state_t *state = (invaders_state_t *)*context_ptr; + // default: sound on + state->sound_on = true; + } +#if __EMSCRIPTEN__ + // simulator only: seed the randon number generator + time_t t; + srand((unsigned) time(&t)); +#endif +} + +void invaders_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + _current_state = invaders_state_activated; + _signals.suspend_buttons = false; +} + +bool invaders_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + invaders_state_t *state = (invaders_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + // show highscore + _display_score("GA", state->highscore); + break; + case EVENT_TICK: + _ticks++; + switch (_current_state) { + case invaders_state_in_wave_break: + case invaders_state_pre_game: + case invaders_state_next_wave: + // wait 2 secs to start the first round + if (_ticks >= 2) { + _ticks = 0; + _init_wave(); + _current_state = invaders_state_playing; + movement_request_tick_frequency(4); + } + break; + case invaders_state_playing: + // game is playing + if (_ticks >= _wave_tick_freq) { + _ticks = 0; + if (_move_invaders()) { + // invaders broke through + if (_defense_lines < 2) { + // start current wave over + _defense_lines++; + _display_defense_lines(); + _display_score("GA", _score); + _current_state = invaders_state_in_wave_break; + movement_request_tick_frequency(1); + _play_sequence(state, (int8_t *)_sound_seq_def_gone); + } else { + // game over + _game_over(state); + } + } + } + // handle bonus points indicators + if (_bonus_countdown) { + _bonus_countdown--; + if (!_bonus_countdown) { + watch_display_character(' ', 2); + watch_display_character(' ', 3); + } + } + break; + case invaders_state_pre_next_wave: + if (_ticks >= 3) { + // switch to next wave + _ticks = 0; + movement_request_tick_frequency(1); + _display_score("GA", _score); + watch_set_pixel(1, 9); + watch_display_character((_waves % INVADERS_FACE_WAVES_PER_STAGE) + 49, 3); + _current_state = invaders_state_next_wave; + _waves++; + if (_waves == INVADERS_FACE_WAVES_PER_STAGE * 2) _waves = 0; + _play_sequence(state, (int8_t *)_sound_seq_next_wave); + } + default: + break; + } + break; + case EVENT_LIGHT_BUTTON_DOWN: + if (!_signals.suspend_buttons) { + if (_current_state == invaders_state_playing) { + // cycle the aim + _aim = (_aim + 1) % 11; + _display_invader(_aim, 0); + } else if (_current_state == invaders_state_activated || _current_state == invaders_state_game_over) { + // just illuminate the LED + movement_illuminate_led(); + } + } + break; + case EVENT_LIGHT_LONG_PRESS: + if ((_current_state == invaders_state_activated || _current_state == invaders_state_game_over) && !_signals.suspend_buttons) { + // switch between beepy and silent mode + state->sound_on = !state->sound_on; + watch_buzzer_play_note(BUZZER_NOTE_A7, state->sound_on ? 65 : 25); + } + break; + case EVENT_ALARM_BUTTON_DOWN: + if (!_signals.suspend_buttons) { + switch (_current_state) { + case invaders_state_game_over: + case invaders_state_activated: + // initialize the game + _waves = 0; + _score = 0; + movement_request_tick_frequency(1); + _ticks = 0; + _current_state = invaders_state_pre_game; + _play_sequence(state, (int8_t *)_sound_seq_game_start); + break; + case invaders_state_playing: { + // "shoot" + _shots_in_wave++; + if (_shots_in_wave == 30) { + // max number of shots reached: game over + _game_over(state); + } else { + // wait if we are currently deleting an invader + while (_signals.inv_checking); + // proceed + _signals.inv_checking = true; + bool skip = false; + for (int8_t i = _wave_position; i >= 0 && !skip; i--) { + // if (_invaders[i] == -1) break; + if (_invaders[i] == _aim) { + // invader is shot + skip = true; + _invaders_shot++; + _play_sequence(state, _aim == 10 ? (int8_t *)_sound_seq_ufo_hit : (int8_t *)_sound_seq_shot_hit); + if (_invaders_shot == INVADERS_FACE_WAVE_INVADERS) { + // last invader shot: wave sucessfully completed + watch_display_character(' ', 9 - _wave_position); + _ticks = 0; + _current_state = invaders_state_pre_next_wave; + _signals.inv_checking = false; + } else { + // check for ufo appearance + if (_aim && _aim < 10) { + _invaders_shot_sum = (_invaders_shot_sum + _aim) % 10; + if (_invaders_shot_sum == 0) _signals.ufo_next = true; + } + // remove invader + if (_wave_position == 0 || i == 5) { + _invaders[i] = -1; + } else { + for (uint8_t j = i; j < _wave_position; j++) { + _invaders[j] = _invaders[j + 1]; + _display_invader(_invaders[j], 9 - j); + } + } + watch_display_character(' ', 9 - _wave_position); + if (_wave_position) _wave_position--; + // update score + if (_aim == 10) { + // ufo shot. The original game uses a ridiculously complicated scoring system here... + uint8_t bonus_points = 0; + uint8_t j; + for (j = 0; j < sizeof(_bonus_points_helper) && !bonus_points; j++) { + if (_shots_in_wave == _bonus_points_helper[j]) { + bonus_points = 30; + } else if (_shots_in_wave - 1 == _bonus_points_helper[j]) { + bonus_points = 20; + } + } + if (!bonus_points) bonus_points = 10; + bonus_points += (6 - i); + if ((_waves >= INVADERS_FACE_WAVES_PER_STAGE) && i) bonus_points += (6 - i); + _score += bonus_points; + // represent bonus points by bars + for (j = 0; j < (bonus_points / 10); j++) watch_set_pixel(_bonus_points_segdata[j][0], _bonus_points_segdata[j][1]); + _bonus_countdown = 9; + } else { + // regular invader + _score += (6 - _wave_position) * (_waves >= INVADERS_FACE_WAVES_PER_STAGE ? 2 : 1); + } + } + } + } + if (!skip) _play_sequence(state, (int8_t *)_sound_seq_shot_miss); + _signals.inv_checking = false; + } + break; + } + default: + break; + } + } + break; + case EVENT_TIMEOUT: + movement_move_to_face(0); + 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 if the watch can enter standby mode. Generally speaking, you should always return true. + // Exceptions: + // * If you are displaying a color using the low-level watch_set_led_color function, you should return false. + // * If you are sounding the buzzer using the low-level watch_set_buzzer_on function, you should return false. + // Note that if you are driving the LED or buzzer using Movement functions like movement_illuminate_led or + // movement_play_alarm, you can still return true. This guidance only applies to the low-level watch_ functions. + return true; +} + +void invaders_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + _current_state = invaders_state_game_over; +} + diff --git a/movement/watch_faces/complication/invaders_face.h b/movement/watch_faces/complication/invaders_face.h new file mode 100644 index 00000000..59126dd5 --- /dev/null +++ b/movement/watch_faces/complication/invaders_face.h @@ -0,0 +1,82 @@ +/* + * MIT License + * + * Copyright (c) 2023 Andreas Nebinger + * + * 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 INVADERS_FACE_H_ +#define INVADERS_FACE_H_ + +#include "movement.h" + +/* + * Remake of the "famous" Casio Number Invaders Game + * + * This is an authentic remake of the invaders game, found on the Casio + * calculator wristwatch CA-85 or CA-851. There were also some calculators + * sold with this game, like MG-880. + * + * How to play: + * + * Press the alarm button to start the game. + * "Invaders" (just digits, tbh) will start coming in from the right hand side. + * Press the light button to "aim". The digit on the top of the display cycles + * from 0 to 9. If your aiming digit is identical to one of the invaders, + * press the alarm button to "shoot". The corresponding invader will disappear. + * If the invaders reach beneath the very first position, you loose one defense + * line. When all three defense lines are gone, the game is over. + * Also: If you shoot more than 29 times per round, you loose the game. + * Good to know: There are 16 invaders per wave. There is a short break between + * waves. + * + * What are the "n" invaders? Ufos! + * + * Whenever the sum of all invaders shot is divisible by 10 the next invader + * will be an ufo, represented by the n-symbol. Shooting a ufo gets you extra + * points. Example: shoot 2, 5, 3 --> ufo next + * + * As for points: the earlier you shoot an invader, the more points you get. + * + * Anything else? Long pressing the light button toggles sound on or off. (Not + * while playing.) + * + */ + +typedef struct { + uint16_t highscore; + bool sound_on; +} invaders_state_t; + +void invaders_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void invaders_face_activate(movement_settings_t *settings, void *context); +bool invaders_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void invaders_face_resign(movement_settings_t *settings, void *context); + +#define invaders_face ((const watch_face_t){ \ + invaders_face_setup, \ + invaders_face_activate, \ + invaders_face_loop, \ + invaders_face_resign, \ + NULL, \ +}) + +#endif // INVADERS_FACE_H_ + diff --git a/movement/watch_faces/complication/morsecalc_face.c b/movement/watch_faces/complication/morsecalc_face.c index cdf0e198..ca03a1a9 100644 --- a/movement/watch_faces/complication/morsecalc_face.c +++ b/movement/watch_faces/complication/morsecalc_face.c @@ -26,7 +26,6 @@ ## Morse-code-based RPN calculator The calculator is operated by first composing a **token** in Morse code, then submitting it to the calculator. A token specifies either a calculator operation or a float value. - These two parts of the codebase are totally independent: 1. The Morse-code reader (`mc.h`, `mc.c`) @@ -39,7 +38,7 @@ The user interface (`morsecalc_face.h`, `morsecalc_face.c`) lets you talk to the - `light` is dash - `alarm` is dot - `mode` is "finish character" - - long-press `mode` to quit + - long-press `mode` or submit a blank token to switch faces - long-press `alarm` to show stack - long-press `light` to toggle the light @@ -48,7 +47,6 @@ As you enter `.`s and `-`s, the morse code char you've entered will appear in th At the top right is the # of morse code `.`/`-` you've input so far. The character resets at the 6th `.`/`-`. Once you have the character you want to enter, push `mode` to enter it. The character will be appended to the current token, whose 6 trailing chars are shown on the main display. - Once you've typed in the token you want, enter a blank Morse code character and then push `mode`. This submits it to the calculator. @@ -77,7 +75,6 @@ This can get long, so for convenience numerals can also be written in binary wit For example: "4.2e-3" can be entered directly, or as "4h2pC3" similarly, "0.0042" can also be entered as "eheedn" - Once you submit a number to the watch face, it pushes it to the top of the stack if there's room. ## Number display @@ -97,7 +94,6 @@ So for example, the watch face might look like this: ... representing `+4.200e-3` is in stack location 0 (the top) and it's one of five items in the stack. ## Looking at the stack - To show the top of the stack, push and hold `light`/`alarm` or submit a blank token by pushing `mode` a bunch of times. To show the N-th stack item (0 through 9): @@ -113,101 +109,25 @@ To see all the calculator operations and their token aliases, see the `calc_dict #include #include -#include "morsecalc_face.h" #include "watch.h" #include "watch_utility.h" #include "watch_private_display.h" -// Display float on screen -void morsecalc_print_float(double d) { - // Special cases - if(d == 0) { - watch_display_string(" 0", 4); - return; - } - else if(isnan(d)) { - watch_display_string(" nan", 4); - return; - } - else if(d == (1.0)/(0.0)) { - watch_display_string(" inf", 4); - return; - } - else if(d == (-1.0)/(0.0)) { - watch_display_character('X', 1); - watch_display_string(" inf", 4); - return; - } +#include "morsecalc_face.h" +#include "morsecalc_display.h" - // Record number properties - // Sign - int is_negative = d<0; - if(is_negative) d = -d; - - // Order of magnitude - int om = (int) floor(log(d)/log(10)); - int om_is_negative = (om<0); - - // Get the first 4 significant figures - int digits; - digits = round(d*pow(10.0, 3-om)); - if(digits>9999) { - digits = 1000; - om++; - } - - // Print signs - if(is_negative) { - // Xi; see https://joeycastillo.github.io/Sensor-Watch-Documentation/segmap - watch_set_pixel(0,11); - watch_set_pixel(2,12); - watch_set_pixel(2,11); - } - else watch_display_character(' ', 1); - if(om_is_negative) watch_set_pixel(1,9); - else watch_display_character(' ', 2); - - // Print first 4 significant figures - watch_display_character('0'+(digits/1000)%10, 4); - watch_display_character('0'+(digits/100 )%10, 5); - watch_display_character('0'+(digits/10 )%10, 6); - watch_display_character('0'+(digits/1 )%10, 7); - - // Prinat exponent - if(om_is_negative) om = -om; // Make exponent positive for display - if(om<=99) { - watch_display_character('0'+(om/10 )%10, 8); - watch_display_character('0'+(om/1 )%10, 9); - } else { // Over/underflow - if(om_is_negative) watch_display_string(" uf", 4); - else watch_display_string(" of", 4); - if(om<9999) { // Use main display to show order of magnitude - // (Should always succeed; max double is <2e308) - watch_display_character('0'+(om/1000)%10, 4); - watch_display_character('0'+(om/100 )%10, 5); - watch_display_character('0'+(om/10 )%10, 6); - watch_display_character('0'+(om/1 )%10, 7); - } - } +/* mc_input Read an input into a morse code buffer + * Input: mc = index of MORSECODE_TREE[] + * len = max morse code char length + * in = character to read into buffer (0='.', 1='-', ignored otherwise). + * If the buffer is full, reset it instead of entering the new character. + */ +static void morsecode_input(unsigned int *mc, unsigned int len, char in) { + if(*mc >= (unsigned int) ((1<mc->b); // Decode the morse code buffer's current contents - if('\0' == c) c = ' '; // Needed for watch_display_character - watch_display_character(c, 0); // Display current morse code char in mode position - watch_display_character('0'+(mcs->mc->bidx), 3); // Display buffer position in top right - - // Print last 6 chars of current input line - uint8_t nlen = strlen(mcs->token); // number of characters in token - uint8_t nprint = min(nlen,6); // number of characters to print - watch_display_string(mcs->token+nlen-nprint, 10-nprint); // print right-aligned - return; -} // Clear token buffer void morsecalc_reset_token(morsecalc_state_t *mcs) { @@ -216,75 +136,46 @@ void morsecalc_reset_token(morsecalc_state_t *mcs) { return; } -// Print stack or memory register contents. -void morsecalc_print_stack(morsecalc_state_t * mcs) { - watch_display_string(" ", 0); // Clear display - - char c = mc_dec(mcs->mc->b); - if('m' == c) { // Display memory - morsecalc_print_float(mcs->cs->mem); - watch_display_character(c, 0); - } - else { - // If the morse code buffer has a numeral in it, print that stack item - // Otherwise print top of stack - uint8_t idx = 0; - if(c >= '0' && c <= '9') idx = c - '0'; - if(idx >= mcs->cs->s) watch_display_string(" empty", 4); // Stack empty - else morsecalc_print_float(mcs->cs->stack[mcs->cs->s-1-idx]); // Print stack item - - watch_display_character('0'+idx, 0); // Print which stack item this is top center - } - watch_display_character('0'+(mcs->cs->s), 3); // Print the # of stack items top right - return; -} - -// Write something into the morse code buffer. -// Input: c = dot (0), dash (1), or 'complete' ('x') -void morsecalc_input(morsecalc_state_t * mcs, char c) { +// Write a completed morse code character to the calculator +void morsecalc_input(morsecalc_state_t * mcs) { int status = 0; - if( c != 'x' ) { // Dot or dash received - mc_input(mcs->mc, c); - morsecalc_print_token(mcs); - } - else { // Morse code character finished - char dec = mc_dec(mcs->mc->b); - mc_reset(mcs->mc); - switch(dec) { - case '\0': // Invalid character, do nothing - morsecalc_print_token(mcs); - break; - - case ' ': // Submit token to calculator - if(strlen(mcs->token) > 0) { - status = calc_input(mcs->cs, mcs->token); - morsecalc_reset_token(mcs); - } - morsecalc_print_stack(mcs); - break; - - case '(': // -.--. Erase previous character in token - if(mcs->idxt>0) { - mcs->idxt--; - mcs->token[mcs->idxt] = '\0'; - } - morsecalc_print_token(mcs); - break; - - case 'S': // -.-.- Erase entire token without submitting + char dec = MORSECODE_TREE[mcs->mc]; + mcs->mc = 0; + switch(dec) { + case '\0': // Invalid character, do nothing + morsecalc_display_token(mcs); + break; + + case ' ': // Submit token to calculator + if(mcs->idxt > 0) { + mcs->token[mcs->idxt] = '\0'; + status = calc_input(mcs->cs, mcs->token); morsecalc_reset_token(mcs); - morsecalc_print_stack(mcs); - break; - - default: // Add character to token - if(mcs->idxt < MORSECALC_TOKEN_LEN-1) { - mcs->token[mcs->idxt] = dec; - mcs->idxt++; - morsecalc_print_token(mcs); - } - else watch_display_string(" full", 4); - break; - } + } + morsecalc_display_stack(mcs); + break; + + case '(': // -.--. Erase previous character in token + if(mcs->idxt>0) { + mcs->idxt--; + mcs->token[mcs->idxt] = '\0'; + } + morsecalc_display_token(mcs); + break; + + case 'S': // -.-.- Erase entire token without submitting + morsecalc_reset_token(mcs); + morsecalc_display_stack(mcs); + break; + + default: // Add character to token + if(mcs->idxt < MORSECALC_TOKEN_LEN-1) { + mcs->token[mcs->idxt] = dec; + mcs->idxt = min(mcs->idxt+1, MORSECALC_TOKEN_LEN); + morsecalc_display_token(mcs); + } + else watch_display_string(" full", 4); + break; } // Print errors if there are any @@ -308,10 +199,7 @@ void morsecalc_face_setup(movement_settings_t *settings, uint8_t watch_face_inde mcs->cs = (calc_state_t *) malloc(sizeof(calc_state_t)); calc_init(mcs->cs); - - mcs->mc = (mc_state_t *) malloc(sizeof(mc_state_t)); - mc_reset(mcs->mc); - + mcs->mc = 0; mcs->led_is_on = 0; } return; @@ -320,8 +208,8 @@ void morsecalc_face_setup(movement_settings_t *settings, uint8_t watch_face_inde void morsecalc_face_activate(movement_settings_t *settings, void *context) { (void) settings; morsecalc_state_t *mcs = (morsecalc_state_t *) context; - mc_reset(mcs->mc); - morsecalc_print_stack(mcs); + mcs->mc = 0; + morsecalc_display_stack(mcs); return; } @@ -331,21 +219,24 @@ bool morsecalc_face_loop(movement_event_t event, movement_settings_t *settings, // input case EVENT_ALARM_BUTTON_UP: // dot - morsecalc_input(mcs, '.'); + morsecode_input(&mcs->mc, MORSECODE_LEN, 0); + morsecalc_display_token(mcs); break; case EVENT_LIGHT_BUTTON_UP: // dash - morsecalc_input(mcs, '-'); + morsecode_input(&mcs->mc, MORSECODE_LEN, 1); + morsecalc_display_token(mcs); break; case EVENT_MODE_BUTTON_UP: - // submit character - morsecalc_input(mcs, 'x'); + // submit character (or quit) + if(mcs->mc || mcs->idxt) morsecalc_input(mcs); + else movement_move_to_next_face(); break; // show stack case EVENT_ALARM_LONG_PRESS: - morsecalc_print_stack(mcs); - mc_reset(mcs->mc); + morsecalc_display_stack(mcs); + mcs->mc = 0; break; // toggle light @@ -364,7 +255,7 @@ bool morsecalc_face_loop(movement_event_t event, movement_settings_t *settings, // quit case EVENT_TIMEOUT: - movement_move_to_next_face(); + movement_move_to_face(0); break; case EVENT_MODE_LONG_PRESS: movement_move_to_next_face(); diff --git a/movement/watch_faces/complication/morsecalc_face.h b/movement/watch_faces/complication/morsecalc_face.h index bd0fd416..2ee18622 100644 --- a/movement/watch_faces/complication/morsecalc_face.h +++ b/movement/watch_faces/complication/morsecalc_face.h @@ -24,11 +24,27 @@ #ifndef MORSECALC_FACE_H_ #define MORSECALC_FACE_H_ -#define MORSECALC_TOKEN_LEN 9 + +#define MORSECALC_TOKEN_LEN 32 +#define MORSECODE_LEN 5 #include "movement.h" #include "calc.h" -#include "mc.h" + +/* + * MC International Morse Code binary tree + * Levels of the tree are concatenated. + * '.' = 0 and '-' = 1. + * + * Capitals denote special characters: + * C = Ch digraph + * V = VERIFY (ITU-R "UNDERSTOOD") + * R = REPEAT + * W = WAIT + * S = START TRANSMISSION + * E = END OF WORK + */ +static const char MORSECODE_TREE[] = " etianmsurwdkgohvf\0l\0pjbxcyzq\0C\x35\x34V\x33\0R\0\x32W\0+\0\0\0\0\x31\x36=/\0\0S(\0\x37\0\0\0\x38\0\x39\x30\0\0\0\0\0E\0\0\0\0\0\0?_\0\0\0\0\"\0\0.\0\0\0\0@\0\0\0'\0\0-\0\0\0\0\0\0\0\0;!\0)\0\0\0\0\0,\0\0\0\0:\0\0\0\0\0\0"; void morsecalc_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); void morsecalc_face_activate(movement_settings_t *settings, void *context); @@ -37,17 +53,14 @@ void morsecalc_face_resign(movement_settings_t *settings, void *context); typedef struct { calc_state_t *cs; - mc_state_t *mc; + unsigned int mc; // Morse code character char token[MORSECALC_TOKEN_LEN]; uint8_t idxt; uint8_t led_is_on; } morsecalc_state_t; -void morsecalc_print_float(double d); -void morsecalc_print_token(morsecalc_state_t *mcs); -void morsecalc_print_stack(morsecalc_state_t *mcs); void morsecalc_reset_token(morsecalc_state_t *mcs); -void morsecalc_input(morsecalc_state_t *mcs, char c); +void morsecalc_input(morsecalc_state_t *mcs); #define morsecalc_face ((const watch_face_t){ \ morsecalc_face_setup, \ diff --git a/movement/watch_faces/complication/planetary_hours_face.c b/movement/watch_faces/complication/planetary_hours_face.c new file mode 100644 index 00000000..acded917 --- /dev/null +++ b/movement/watch_faces/complication/planetary_hours_face.c @@ -0,0 +1,402 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 +#include +#include +#include "sunriset.h" +#include "watch.h" +#include "watch_utility.h" +#include "planetary_hours_face.h" + +#if __EMSCRIPTEN__ +#include +#endif + +// STATIC FUNCTIONS AND CONSTANTS ///////////////////////////////////////////// + +/** @brief Planetary rulers in the Chaldean order from slowest to fastest + * @details Planetary rulers in the Chaldean order from slowest to fastest: + * Jupiter, Mars, Sun, Venus, Mercury, Moon + */ +static const char planets[7][3] = {"Sa", "Ju", "Ma", "So", "Ve", "Me", "Lu"}; // Latin +static const char planetes[7][3] = {"Ch", "Ze", "Ar", "He", "Af", "Hr", "Se"}; // Greek + +/** @brief Ruler of each weekday for easy lookup + */ +static const uint8_t plindex[7] = {3, 6, 2, 5, 1, 4, 0}; // day ruler index + +/** @brief Astrological symbol for each planet + */ +static void _planetary_icon(uint8_t planet) { + + watch_clear_pixel(0, 13); + watch_clear_pixel(0, 14); + watch_clear_pixel(1, 13); + watch_clear_pixel(1, 14); + watch_clear_pixel(1, 15); + watch_clear_pixel(2, 13); + watch_clear_pixel(2, 14); + watch_clear_pixel(2, 15); + + switch (planet) { + case 0: // Saturn + watch_set_pixel(0, 14); + watch_set_pixel(2, 14); + watch_set_pixel(1, 15); + watch_set_pixel(2, 13); + break; + case 1: // Jupiter + watch_set_pixel(0, 14); + watch_set_pixel(1, 15); + watch_set_pixel(1, 14); + break; + case 2: // Mars + watch_set_pixel(2, 14); + watch_set_pixel(2, 15); + watch_set_pixel(1, 15); + watch_set_pixel(2, 13); + watch_set_pixel(1, 13);\ + break; + case 3: // Sol + watch_set_pixel(0, 14); + watch_set_pixel(2, 14); + watch_set_pixel(1, 13); + watch_set_pixel(2, 13); + watch_set_pixel(0, 13); + watch_set_pixel(2, 15); + break; + case 4: // Venus + watch_set_pixel(0, 14); + watch_set_pixel(0, 13); + watch_set_pixel(1, 13); + watch_set_pixel(1, 15); + watch_set_pixel(1, 14); + break; + case 5: // Mercury + watch_set_pixel(0, 14); + watch_set_pixel(1, 13); + watch_set_pixel(1, 14); + watch_set_pixel(1, 15); + watch_set_pixel(2, 15); + break; + case 6: // Luna + watch_set_pixel(2, 14); + watch_set_pixel(2, 15); + watch_set_pixel(2, 13); + break; + } +} + +/** @details A solar phase can be a day phase between sunrise and sunset or an alternating night phase. + * This function calculates the start and end of the current phase based on a given geographic location. + * It also calculates the start of the next following phase. + */ +static void _planetary_solar_phases(movement_settings_t *settings, planetary_hours_state_t *state) { + uint8_t phase, h; + double sunrise, sunset; + double hour_duration, next_hour_duration; + uint32_t now_epoch; + uint32_t sunrise_epoch_today, sunset_epoch_today, midnight_epoch_today; + uint32_t sunset_epoch_yesterday, midnight_epoch_yesterday; + uint32_t sunrise_epoch_tomorrow, sunset_epoch_tomorrow, midnight_epoch_tomorrow; + movement_location_t movement_location = (movement_location_t) watch_get_backup_data(1); + + // check if we have a location. If not, display error + if (movement_location.reg == 0) { + watch_display_string(" no Loc", 0); + state->no_location = true; + return; + } + + // location detected + state->no_location = false; + + watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); // the current date / time in UTC + watch_date_time scratch_time; // scratchpad, contains different values at different times + watch_date_time midnight; + scratch_time.reg = midnight.reg = utc_now.reg; + midnight.unit.hour = midnight.unit.minute = midnight.unit.second = 0; // start of the day at midnight + + // get location coordinate + int16_t lat_centi = (int16_t)movement_location.bit.latitude; + int16_t lon_centi = (int16_t)movement_location.bit.longitude; + double lat = (double)lat_centi / 100.0; + double lon = (double)lon_centi / 100.0; + + // save UTC offset + state->utc_offset = ((double)movement_timezone_offsets[settings->bit.time_zone]) / 60.0; + + // calculate sunrise and sunset of current day in decimal hours after midnight + sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &sunrise, &sunset); + + // calculate sunrise and sunset UNIX timestamps + midnight_epoch_today = watch_utility_date_time_to_unix_time(midnight, 0); + sunrise_epoch_today = midnight_epoch_today + sunrise * 3600; + sunset_epoch_today = midnight_epoch_today + sunset * 3600; + + // go back to yesterday and calculate sunset + midnight_epoch_yesterday = midnight_epoch_today - 86400; + scratch_time = watch_utility_date_time_from_unix_time(midnight_epoch_yesterday, 0); + sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &sunrise, &sunset); + sunset_epoch_yesterday = midnight_epoch_yesterday + sunset * 3600; + + // go to tomorrow and calculate sunrise and sunset + midnight_epoch_tomorrow = midnight_epoch_today + 86400; + scratch_time = watch_utility_date_time_from_unix_time(midnight_epoch_tomorrow, 0); + sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &sunrise, &sunset); + sunrise_epoch_tomorrow = midnight_epoch_tomorrow + sunrise * 3600; + sunset_epoch_tomorrow = midnight_epoch_tomorrow + sunset * 3600; + + // get UNIX epoch time + now_epoch = watch_utility_date_time_to_unix_time(utc_now, 0); + + // by default we assume it is daytime (phase 1) between sunrise and sunset + phase = 1; + state->phase_start = sunrise_epoch_today; + state->phase_end = sunset_epoch_today; + state->phase_next = sunrise_epoch_tomorrow; + state->start_at_night = false; + + // night time calculations + if ( now_epoch < sunrise_epoch_today && now_epoch < sunset_epoch_today ) phase = 0; // morning before dawn + if ( now_epoch > sunrise_epoch_today && now_epoch >= sunset_epoch_today ) phase = 2; // evening after dusk + + // phase 0: we are before sunrise + if ( phase == 0) { + state->phase_start = sunset_epoch_yesterday; + state->phase_end = sunrise_epoch_today; + state->phase_next = sunset_epoch_today; + state->start_at_night = true; + } + + // phase 2: we are after sunset + if ( phase == 2) { + state->phase_start = sunset_epoch_today; + state->phase_end = sunrise_epoch_tomorrow; + state->phase_next = sunset_epoch_tomorrow; + state->start_at_night = true; + } + + // calculate the duration of a planetary hour during this and the next solar phase + hour_duration = ( state->phase_end - state->phase_start ) / 12.0; + next_hour_duration = ( state->phase_next - state->phase_end ) / 12.0; + + // populate list of 24 planetary hour start points in UNIX timestamp format + // starting from the beginning of the current phase + for ( h = 0; h < 24; h++ ) { + if ( h < 12 ) state->planetary_hours[h] = state->phase_start + h * hour_duration; // current phase + else state->planetary_hours[h] = state->phase_end + ( h - 12 ) * next_hour_duration; // next phase + } + + // initialize + state->hour = 0; + state->ruler = 0; + state->skip_to_current = true; + +} + +/** @details A planetary hour is one of exactly twelve hours of a solar phase. Its length varies. + * This function calculates the current planetary hour and divides it up into relative minutes and seconds. + * It also calculates the current planetary ruler of the hour and of the day. + */ +static void _planetary_hours(movement_settings_t *settings, planetary_hours_state_t *state) { + char buf[14]; + char ruler[3]; + uint8_t weekday, planet, planetary_hour; + uint32_t current_hour_epoch; + watch_date_time scratch_time; + + // check if we have a location. If not, display error + if ( state->no_location ) { + watch_display_string(" no Loc", 0); + return; + } + + // get current time + watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); // the current date / time in UTC + current_hour_epoch = watch_utility_date_time_to_unix_time(utc_now, 0); + + // set the current planetary hour as default screen + if ( state->skip_to_current ) { + state->hour = ( current_hour_epoch - state->phase_start ) / (( state->phase_end - state->phase_start ) / 12.0); + state->skip_to_current = false; + } + + + // when current phase ends calculate the next phase + if ( watch_utility_date_time_to_unix_time(utc_now, 0) >= state->phase_end ) { + _planetary_solar_phases(settings, state); + return; + } + + if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H); + + // roll over hour iterator + if ( state->hour < 0 ) state->hour = 23; + if ( state->hour > 23 ) state->hour = 0; + if ( state->ruler < 0 ) state->hour = 2; + if ( state->ruler > 2 ) state->hour = 0; + + // clear indicators + watch_clear_indicator(WATCH_INDICATOR_BELL); + watch_clear_indicator(WATCH_INDICATOR_LAP); + + // display bell indicator when displaying the current planetary hour + if ( state->hour < 24 ) + if ( current_hour_epoch >= state->planetary_hours[state->hour] && current_hour_epoch < state->planetary_hours[state->hour + 1]) { + watch_set_indicator(WATCH_INDICATOR_BELL); + } + + // display LAP indicator when the hours of the next phase belong to the next day + if ( state->start_at_night == true && state->hour > 11 ) + watch_set_indicator(WATCH_INDICATOR_LAP); + + // determine weekday from start of current phase + scratch_time = watch_utility_date_time_from_unix_time(state->phase_start, 0); + scratch_time = watch_utility_date_time_convert_zone(scratch_time, 0, state->utc_offset * 3600); + weekday = watch_utility_get_iso8601_weekday_number(scratch_time.unit.year, scratch_time.unit.month, scratch_time.unit.day) - 1; + + // which planetary hour are we in? + planetary_hour = state->hour % 12; + + // accomodate night hour count + if ( state->hour < 12 ) { + if ( state->start_at_night ) { + planetary_hour += 12; + } + } else { + if ( state->start_at_night ) { + weekday = ( weekday + 1 ) % 7; + } else { + planetary_hour += 12; + } + } + + // make datetime object for selected planetary hour + scratch_time = watch_utility_date_time_from_unix_time(state->planetary_hours[state->hour], 0); + scratch_time = watch_utility_date_time_convert_zone(scratch_time, 0, state->utc_offset * 3600); + + // round minutes + if (scratch_time.unit.second < 30 && scratch_time.unit.minute > 0 ) scratch_time.unit.minute--; + else if ( scratch_time.unit.minute < 59 ) scratch_time.unit.minute++; + + // if we are in 12 hour mode, do some cleanup + if (!settings->bit.clock_mode_24h) { + if (scratch_time.unit.hour < 12) { + watch_clear_indicator(WATCH_INDICATOR_PM); + } else { + watch_set_indicator(WATCH_INDICATOR_PM); + } + scratch_time.unit.hour %= 12; + if (scratch_time.unit.hour == 0) scratch_time.unit.hour = 12; + } + + // planetary ruler of the hour + planet = ( plindex[weekday] + planetary_hour ) % 7; + + // latin or greek ruler names or astrological symbol + if ( state->ruler == 0 ) strncpy(ruler, planets[planet], 3); + if ( state->ruler == 1 ) strncpy(ruler, planetes[planet], 3); + if ( state->ruler == 2 ) strncpy(ruler, " ", 3); + + // display planetary time with ruler of the hour or ruler of the day + sprintf(buf, "%s%2d%2d%02d ", ruler, (planetary_hour % 24) + 1, scratch_time.unit.hour, scratch_time.unit.minute); + + watch_set_colon(); + watch_display_string(buf, 0); + + if ( state->ruler == 2 ) _planetary_icon(planet); +} + +// PUBLIC WATCH FACE FUNCTIONS //////////////////////////////////////////////// + +void planetary_hours_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(planetary_hours_state_t)); + memset(*context_ptr, 0, sizeof(planetary_hours_state_t)); + } +} + +void planetary_hours_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 + + planetary_hours_state_t *state = (planetary_hours_state_t *)context; + _planetary_solar_phases(settings, state); + +} + +bool planetary_hours_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + planetary_hours_state_t *state = (planetary_hours_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + // Show your initial UI here. + watch_clear_indicator(WATCH_INDICATOR_PM); + watch_clear_indicator(WATCH_INDICATOR_24H); + _planetary_hours(settings, state); + break; + case EVENT_LIGHT_BUTTON_UP: + state->ruler = (state->ruler + 1) % 3; + _planetary_hours(settings, state); + break; + case EVENT_LIGHT_LONG_PRESS: + state->skip_to_current = true; + _planetary_hours(settings, state); + break; + case EVENT_ALARM_BUTTON_UP: + state->hour++; + _planetary_hours(settings, state); + break; + case EVENT_ALARM_LONG_PRESS: + state->hour--; + _planetary_hours(settings, state); + break; + default: + return movement_default_loop_handler(event, settings); + } + return true; +} + +void planetary_hours_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; +} + diff --git a/movement/watch_faces/complication/planetary_hours_face.h b/movement/watch_faces/complication/planetary_hours_face.h new file mode 100644 index 00000000..53237df2 --- /dev/null +++ b/movement/watch_faces/complication/planetary_hours_face.h @@ -0,0 +1,107 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * Copyright (c) 2022 Joey Castillo (sunrise_sunset_face) + * + * 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 planetary_hours_face_H_ +#define planetary_hours_face_H_ + +#include "movement.h" +#include "sunrise_sunset_face.h" + +/* + * BACKGROUND + + * Both the 24 hour day and the order of our weekdays have quite esoteric roots. + * The ancient Egyptians divided the day up into 12 hours of sunlight and 12 hours + * of night time. Obviously the length of these hours varied throughout the year. + * + * The Greeks assigned each hour a ruler of the planetary gods in the ancient + * "Chaldean" order from slowest (Chronos for Saturn) to fastest (Selene for Moon). + * Because 24 hours cannot be equally divided by seven, the planetary rulers carried + * over to the first hour of the next day, effectively ruling over the entire day + * and lending the whole day their name. The seven day week was born. + * + * PLANETARY HOUR CHART COMPLICATION + * + * This complication watch face displays the start time of the current planetary hour + * according to the given location and day of the year. The number of the current + * planetary hour (1 - 24) is indicated at the top right. + * + * Short pressing the ALARM button flips through the start times of the following + * planetary hours, long pressing it flips backwards in time. A long press of the + * LIGHT button immediately switches back to the start time of the current hour. + * The Bell indicator always marks the current planetary hour in the list. + * The LAP indicator shows up when the hours of the next phase are part of the + * upcoming day instead of the current one. This happens when the watch face is + * launched after sunset. + * + * The planetary ruler of the current hour and day is displayed at the top in + * Latin or Greek shorthand notation: + * + * Saturn (SA) / Chronos (CH) / ♄ + * Jupiter (JU) / Zeus (ZE) / ♃ + * Mars (MA) / Ares (AR) / ♂ + * Sol (SO) / Helios (HE) / ☉ + * Venus (VE) / Aphrodite (AF) / ♀ + * Mercury (ME) / Hermes (HR) / ☿ + * Luna (LU) / Selene (SE) / ☾ + * + * A short press of the LIGHT button toggles between Latin and Greek ruler shorthand + * notation. + * + * (IMPORTANT: Make sure the watch's time, timezone and location are set correctly for this + * watch face to work properly!) + */ + +typedef struct { + // Anything you need to keep track of, put it here! + uint32_t planetary_hours[24]; + uint32_t phase_start; + uint32_t phase_end; + uint32_t phase_next; + bool next; + double utc_offset; + bool no_location; + int8_t hour; + int8_t ruler; + bool start_at_night; + bool skip_to_current; + sunrise_sunset_state_t sunstate; +} planetary_hours_state_t; + +void planetary_hours_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void planetary_hours_face_activate(movement_settings_t *settings, void *context); +bool planetary_hours_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void planetary_hours_face_resign(movement_settings_t *settings, void *context); + +#define planetary_hours_face ((const watch_face_t){ \ + planetary_hours_face_setup, \ + planetary_hours_face_activate, \ + planetary_hours_face_loop, \ + planetary_hours_face_resign, \ + NULL, \ +}) + +#endif // planetary_hours_face_H_ + diff --git a/movement/watch_faces/complication/planetary_time_face.c b/movement/watch_faces/complication/planetary_time_face.c new file mode 100644 index 00000000..56a18cf2 --- /dev/null +++ b/movement/watch_faces/complication/planetary_time_face.c @@ -0,0 +1,338 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 +#include +#include +#include "sunriset.h" +#include "watch.h" +#include "watch_utility.h" +#include "planetary_time_face.h" + +#if __EMSCRIPTEN__ +#include +#endif + +// STATIC FUNCTIONS AND CONSTANTS ///////////////////////////////////////////// + +/** @brief Planetary rulers in the Chaldean order from slowest to fastest + * @details Planetary rulers in the Chaldean order from slowest to fastest: + * Jupiter, Mars, Sun, Venus, Mercury, Moon + */ +static const char planets[7][3] = {"Sa", "Ju", "Ma", "So", "Ve", "Me", "Lu"}; // Latin +static const char planetes[7][3] = {"Ch", "Ze", "Ar", "He", "Af", "Hr", "Se"}; // Greek + +/** @brief Ruler of each weekday for easy lookup + */ +static const uint8_t plindex[7] = {3, 6, 2, 5, 1, 4, 0}; // day ruler index + +/** @brief Astrological symbol for each planet + */ +static void _planetary_icon(uint8_t planet) { + + watch_clear_pixel(0, 13); + watch_clear_pixel(0, 14); + watch_clear_pixel(1, 13); + watch_clear_pixel(1, 14); + watch_clear_pixel(1, 15); + watch_clear_pixel(2, 13); + watch_clear_pixel(2, 14); + watch_clear_pixel(2, 15); + + switch (planet) { + case 0: // Saturn + watch_set_pixel(0, 14); + watch_set_pixel(2, 14); + watch_set_pixel(1, 15); + watch_set_pixel(2, 13); + break; + case 1: // Jupiter + watch_set_pixel(0, 14); + watch_set_pixel(1, 15); + watch_set_pixel(1, 14); + break; + case 2: // Mars + watch_set_pixel(2, 14); + watch_set_pixel(2, 15); + watch_set_pixel(1, 15); + watch_set_pixel(2, 13); + watch_set_pixel(1, 13);\ + break; + case 3: // Sol + watch_set_pixel(0, 14); + watch_set_pixel(2, 14); + watch_set_pixel(1, 13); + watch_set_pixel(2, 13); + watch_set_pixel(0, 13); + watch_set_pixel(2, 15); + break; + case 4: // Venus + watch_set_pixel(0, 14); + watch_set_pixel(0, 13); + watch_set_pixel(1, 13); + watch_set_pixel(1, 15); + watch_set_pixel(1, 14); + break; + case 5: // Mercury + watch_set_pixel(0, 14); + watch_set_pixel(1, 13); + watch_set_pixel(1, 14); + watch_set_pixel(1, 15); + watch_set_pixel(2, 15); + break; + case 6: // Luna + watch_set_pixel(2, 14); + watch_set_pixel(2, 15); + watch_set_pixel(2, 13); + break; + } +} + +/** @details solar phase can be a day phase between sunrise and sunset or an alternating night phase. + * This function calculates the start and end of the current phase based on a given geographic location. + */ +static void _planetary_solar_phase(movement_settings_t *settings, planetary_time_state_t *state) { + uint8_t phase; + double sunrise, sunset; + uint32_t now_epoch, sunrise_epoch, sunset_epoch, midnight_epoch; + movement_location_t movement_location = (movement_location_t) watch_get_backup_data(1); + + // check if we have a location. If not, display error + if (movement_location.reg == 0) { + watch_display_string(" no Loc", 0); + state->no_location = true; + return; + } + + // location detected + state->no_location = false; + + watch_date_time date_time = watch_rtc_get_date_time(); // the current local date / time + watch_date_time utc_now = watch_utility_date_time_convert_zone(date_time, movement_timezone_offsets[settings->bit.time_zone] * 60, 0); // the current date / time in UTC + watch_date_time scratch_time; // scratchpad, contains different values at different times + watch_date_time midnight; + scratch_time.reg = midnight.reg = utc_now.reg; + midnight.unit.hour = midnight.unit.minute = midnight.unit.second = 0; // start of the day at midnight + + // get location coordinate + int16_t lat_centi = (int16_t)movement_location.bit.latitude; + int16_t lon_centi = (int16_t)movement_location.bit.longitude; + double lat = (double)lat_centi / 100.0; + double lon = (double)lon_centi / 100.0; + + // save UTC offset + state->utc_offset = ((double)movement_timezone_offsets[settings->bit.time_zone]) / 60.0; + + // get UNIX epoch time + now_epoch = watch_utility_date_time_to_unix_time(utc_now, 0); + midnight_epoch = watch_utility_date_time_to_unix_time(midnight, 0); + + // calculate sunrise and sunset of current day in decimal hours after midnight + sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &sunrise, &sunset); + + // calculate sunrise and sunset UNIX timestamps + sunrise_epoch = midnight_epoch + sunrise * 3600; + sunset_epoch = midnight_epoch + sunset * 3600; + + // by default we assume it is daytime (phase 1) between sunrise and sunset + phase = 1; + state->night = false; + state->phase_start = sunrise_epoch; + state->phase_end = sunset_epoch; + + // night time calculations + if ( now_epoch < sunrise_epoch && now_epoch < sunset_epoch ) phase = 0; // morning before dawn + if ( now_epoch > sunrise_epoch && now_epoch >= sunset_epoch ) phase = 2; // evening after dusk + + // phase 0: we are before sunrise + if ( phase == 0) { + // go back to yesterday and calculate sunset + midnight_epoch -= 86400; + scratch_time = watch_utility_date_time_from_unix_time(midnight_epoch, 0); + sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &sunrise, &sunset); + sunset_epoch = midnight_epoch + sunset * 3600; + // we are still in yesterday's night hours + state->night = true; + state->phase_start = sunset_epoch; + state->phase_end = sunrise_epoch; + } + + // phase 2: we are after sunset + if ( phase == 2) { + // skip to tomorrow and calculate sunrise + midnight_epoch += 86400; + scratch_time = watch_utility_date_time_from_unix_time(midnight_epoch, 0); + sun_rise_set(scratch_time.unit.year + WATCH_RTC_REFERENCE_YEAR, scratch_time.unit.month, scratch_time.unit.day, lon, lat, &sunrise, &sunset); + sunrise_epoch = midnight_epoch + sunrise * 3600; + // we are still in yesterday's night hours + state->night = true; + state->phase_start = sunset_epoch; + state->phase_end = sunrise_epoch; + } + + // calculate the duration of a planetary second during this solar phase + // and convert to Hertz so we can call a faster tick rate + state->freq = (1 / ((double)( state->phase_end - state->phase_start ) / 43200)); +} + +/** @details A planetary hour is one of exactly twelve hours of a solar phase. Its length varies. + * This function calculates the current planetary hour and divides it up into relative minutes and seconds. + * It also calculates the current planetary ruler of the hour and of the day. + */ +static void _planetary_time(movement_event_t event, movement_settings_t *settings, planetary_time_state_t *state) { + char buf[14]; + char ruler[3]; + double night_hour_count = 0.0; + uint8_t weekday, planet, planetary_hour; + double hour_duration, current_hour, current_minute, current_second; + + watch_set_colon(); + + // get current time and convert to UTC + state->scratch = watch_utility_date_time_convert_zone(watch_rtc_get_date_time(), movement_timezone_offsets[settings->bit.time_zone] * 60, 0); + + // when current phase ends calculate the next phase + if ( watch_utility_date_time_to_unix_time(state->scratch, 0) >= state->phase_end ) { + _planetary_solar_phase(settings, state); + return; + } + + if (settings->bit.clock_mode_24h) watch_set_indicator(WATCH_INDICATOR_24H); + + // PM for night hours, otherwise the night hours are counted from 13 + if ( state->night ) { + if (settings->bit.clock_mode_24h) night_hour_count = 12; + else watch_set_indicator(WATCH_INDICATOR_PM); + } + + // calculate the duration of a planetary hour during this solar phase + hour_duration = (( state->phase_end - state->phase_start)) / 12.0; + + // which planetary hour are we in? + + // RTC only provides full second precision, so we have to manually add subseconds with each tick + current_hour = ((( watch_utility_date_time_to_unix_time(state->scratch, 0) ) + event.subsecond * 0.11111111) - state->phase_start ) / hour_duration; + planetary_hour = floor(current_hour) + ( state->night ? 12 : 0 ); + current_hour += night_hour_count; //adjust for 24hr display + current_minute = modf(current_hour, ¤t_hour) * 60.0; + current_second = modf(current_minute, ¤t_minute) * 60.0; + + // the day changes after sunrise, so if we are at night it is yesterday's planetary day + // hence we take the datetime object of when the last solar phase started as the current day + // and then fill in the hours and minutes + state->scratch = watch_utility_date_time_from_unix_time(state->phase_start, 0); + state->scratch.unit.hour = floor(current_hour); + state->scratch.unit.minute = floor(current_minute); + state->scratch.unit.second = (uint8_t)floor(current_second) % 60; + + // what weekday is it (0 - 6) + weekday = watch_utility_get_iso8601_weekday_number(state->scratch.unit.year, state->scratch.unit.month, state->scratch.unit.day) - 1; + + // planetary ruler of the hour or the day + if ( state->day_ruler ) planet = plindex[weekday]; + else planet = ( plindex[weekday] + planetary_hour ) % 7; + + // latin or greek ruler names or astrological symbol + if ( state->ruler == 0 ) strncpy(ruler, planets[planet], 3); + if ( state->ruler == 1 ) strncpy(ruler, planetes[planet], 3); + if ( state->ruler == 2 ) strncpy(ruler, " ", 3); + + // display planetary time with ruler of the hour or ruler of the day + if ( state->day_ruler ) sprintf(buf, "%s d%2d%02d%02d", ruler, state->scratch.unit.hour, state->scratch.unit.minute, state->scratch.unit.second); + else sprintf(buf, "%s h%2d%02d%02d", ruler, state->scratch.unit.hour, state->scratch.unit.minute, state->scratch.unit.second); + + watch_display_string(buf, 0); + + if ( state->ruler == 2 ) _planetary_icon(planet); + +} + +// PUBLIC WATCH FACE FUNCTIONS //////////////////////////////////////////////// + +void planetary_time_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(planetary_time_state_t)); + memset(*context_ptr, 0, sizeof(planetary_time_state_t)); + } +} + +void planetary_time_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 + + planetary_time_state_t *state = (planetary_time_state_t *)context; + + // calculate phase + _planetary_solar_phase(settings, state); +} + +bool planetary_time_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + planetary_time_state_t *state = (planetary_time_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + _planetary_time(event, settings, state); + if ( state->freq > 1 ) + // for hours with shorter seconds let's increase the tick to not skip seconds in the display + movement_request_tick_frequency( 8 ); + break; + case EVENT_TICK: + _planetary_time(event, settings, state); + break; + case EVENT_LIGHT_BUTTON_UP: + state->ruler = (state->ruler + 1) % 3; + break; + case EVENT_ALARM_BUTTON_UP: + // Just in case you have need for another button. + state->day_ruler = !state->day_ruler; + break; + case EVENT_LOW_ENERGY_UPDATE: + watch_start_tick_animation(500); + break; + default: + return movement_default_loop_handler(event, settings); + } + + return true; +} + +void planetary_time_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + movement_request_tick_frequency( 1 ); +} + diff --git a/movement/watch_faces/complication/planetary_time_face.h b/movement/watch_faces/complication/planetary_time_face.h new file mode 100644 index 00000000..0ecc11af --- /dev/null +++ b/movement/watch_faces/complication/planetary_time_face.h @@ -0,0 +1,108 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * Copyright (c) 2022 Joey Castillo (sunrise_sunset_face) + * + * 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 planetary_time_face_H_ +#define planetary_time_face_H_ + +#include "movement.h" +#include "sunrise_sunset_face.h" + +/* + * BACKGROUND + + * Both the 24 hour day and the order of our weekdays have quite esoteric roots. + * The ancient Egyptians divided the day up into 12 hours of sunlight and 12 hours + * of night time. Obviously the length of these hours varied throughout the year. + * + * The Greeks assigned each hour a ruler of the planetary gods in the ancient + * "Chaldean" order from slowest (Chronos for Saturn) to fastest (Selene for Moon). + * Because 24 hours cannot be equally divided by seven, the planetary rulers carried + * over to the first hour of the next day, effectively ruling over the entire day + * and lending the whole day their name. The seven day week was born. + * + * PLANETARY TIME COMPLICATION + * + * The hour digits of this complication watch-face display the current planetary hour + * according to the given location and day of the year (First hour from 12am to 1am, + * the second hour from 1am to 2am, and so forth). + * + * Like with normal clocks the minutes and seconds help dividing the hour into smaller + * units. On this watch-face, all units naturally vary in length because the planetary + * hours are not fixed by duration but by the moments of sunrise and sunset which + * obviously vary throughout the year, especially in higher latitudes. + * + * On this watch-face the hours indicated as 12am to 12pm (00:00 - 12:00) are used for + * the planetary daytime hours between sunrise and sunset and hours indicated as 12pm + * to 12am (12:00 - 00:00) are used for the planetary night hours after sunset and before + * sunrise. + * + * The planetary ruler of the current hour and day is displayed at the top in Latin or + * Greek shorthand notation: + * + * Saturn (SA) / Chronos (CH) / ♄ + * Jupiter (JU) / Zeus (ZE) / ♃ + * Mars (MA) / Ares (AR) / ♂ + * Sol (SO) / Helios (HE) / ☉ + * Venus (VE) / Aphrodite (AF) / ♀ + * Mercury (ME) / Hermes (HR) / ☿ + * Luna (LU) / Selene (SE) / ☾ + * + * The ALARM button toggles between displaying the ruler of the hour and the ruler of the day + * + * The LIGHT button toggles between Latin and Greek ruler shorthand notation + * + * (IMPORTANT: Make sure the watch's time, timezone and location are set correctly for this + * watch face to work properly!) + */ + +typedef struct { + // Anything you need to keep track of, put it here! + uint32_t phase_start; + uint32_t phase_end; + bool night; + double utc_offset; + double freq; + uint8_t ruler; + bool day_ruler; + bool no_location; + sunrise_sunset_state_t sunstate; + watch_date_time scratch; +} planetary_time_state_t; + +void planetary_time_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void planetary_time_face_activate(movement_settings_t *settings, void *context); +bool planetary_time_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void planetary_time_face_resign(movement_settings_t *settings, void *context); + +#define planetary_time_face ((const watch_face_t){ \ + planetary_time_face_setup, \ + planetary_time_face_activate, \ + planetary_time_face_loop, \ + planetary_time_face_resign, \ + NULL, \ +}) + +#endif // planetary_time_face_H_ + diff --git a/movement/watch_faces/complication/randonaut_face.c b/movement/watch_faces/complication/randonaut_face.c new file mode 100644 index 00000000..1a3eb21d --- /dev/null +++ b/movement/watch_faces/complication/randonaut_face.c @@ -0,0 +1,414 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 +#else +#include "saml22j18a.h" +#endif + +#include +#include +#include +#include "filesystem.h" +#include "randonaut_face.h" + +#define R 6371 // Earth's radius in km +#define PI 3.14159265358979323846 + +static void _get_location_from_file(randonaut_state_t *state); +static void _save_point_to_file(randonaut_state_t *state); +static void _get_entropy(randonaut_state_t *state); +static void _generate_blindspot(randonaut_state_t *state); +static void _randonaut_face_display(randonaut_state_t *state); +static void _generate_blindspot(randonaut_state_t *state); +static uint32_t _get_pseudo_entropy(uint32_t max); +static uint32_t _get_true_entropy(void); +static void _get_entropy(randonaut_state_t *state); + +// MOVEMENT WATCH FACE FUNCTIONS ////////////////////////////////////////////// + +void randonaut_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(randonaut_state_t)); + memset(*context_ptr, 0, sizeof(randonaut_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. +} + +void randonaut_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + randonaut_state_t *state = (randonaut_state_t *)context; + _get_location_from_file(state); + state->face.mode = 0; + state->radius = 1000; + _get_entropy(state); + state->chance = true; + // Handle any tasks related to your watch face coming on screen. +} + +bool randonaut_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + randonaut_state_t *state = (randonaut_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + // Show your initial UI here. + break; + case EVENT_TICK: + // If needed, update your display here. + break; + case EVENT_LIGHT_BUTTON_DOWN: + break; + case EVENT_LIGHT_BUTTON_UP: + switch ( state->face.mode ) { + case 0: // home + state->face.mode = 2; //point + state->face.location_format = 0; // title + break; + case 1: // generate + state->face.mode = 0; //home + break; + case 2: // point + state->face.mode = 0; //home + break; + case 3: // setup radius + state->face.mode = 4; // toggle to RNG + break; + case 4: // setup RNG + state->face.mode = 3; // toggle to Radius + break; + case 5: // data processing + break; + } + break; + case EVENT_LIGHT_LONG_PRESS: + switch ( state->face.mode ) { + case 3: // setup + case 4: + state->face.mode = 0; //home + break; + default: + state->face.mode = 3; //setup + watch_clear_display(); + } + break; + case EVENT_ALARM_BUTTON_UP: + switch ( state->face.mode ) { + case 0: //home + state->face.mode = 1; // generate + break; + case 2: // point + state->face.location_format = (( state->face.location_format + 1) % (7)); + if ( state->face.location_format == 0 ) + state->face.location_format++; + break; + case 3: //setup radius + state->radius += 500; + if ( state->radius > 10000 ) + state->radius = 1000; + break; + case 4: //setup RNG + state->face.rng = (state->face.rng + 1) % 3; + switch ( state->face.rng ) { + case 0: + state->chance = true; + break; + case 1: + state->chance = false; + state->quantum = true; + break; + case 2: + state->chance = false; + state->quantum = false; + break; + } + break; + case 5: // data processing + _save_point_to_file(state); + break; + default: + break; + } + break; + case EVENT_ALARM_LONG_PRESS: + if ( state->face.mode == 5 ) + state->face.mode = 0; // home + else + state->face.mode = 5; // data processing + break; + case EVENT_TIMEOUT: + // Your watch face will receive this event after a period of inactivity. If it makes sense to resign, + // you may uncomment this line to move back to the first watch face in the list: + // 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); + } + + _randonaut_face_display(state); + + // return true if the watch can enter standby mode. Generally speaking, you should always return true. + // Exceptions: + // * If you are displaying a color using the low-level watch_set_led_color function, you should return false. + // * If you are sounding the buzzer using the low-level watch_set_buzzer_on function, you should return false. + // Note that if you are driving the LED or buzzer using Movement functions like movement_illuminate_led or + // movement_play_alarm, you can still return true. This guidance only applies to the low-level watch_ functions. + return true; +} + +void randonaut_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + + // handle any cleanup before your watch face goes off-screen. +} + +// PRIVATE STATIC FUNCTIONS /////////////////////////////////////////////////// + +/** @brief display handler + */ +static void _randonaut_face_display(randonaut_state_t *state) { + char buf[12]; + watch_clear_colon(); + switch ( state->face.mode ) { + case 0: //home + sprintf(buf, "RA Rando"); + break; + case 1: //generate + if ( state->quantum ) + // All Hail Steve /;[;[/.;]/[.;[/;/;/;/;.;.];.]]--=/ + for ( uint8_t c = 100; c > 0; c--) { + watch_set_pixel(_get_pseudo_entropy(0x2),_get_pseudo_entropy(0x33-0x1C)); + watch_set_pixel(_get_pseudo_entropy(0x2),_get_pseudo_entropy(3432-3409)); + watch_set_pixel(_get_pseudo_entropy(002),_get_pseudo_entropy(0xE +9)); + watch_set_pixel(_get_pseudo_entropy(0x2),_get_pseudo_entropy(23)); + watch_set_pixel(_get_pseudo_entropy(002),_get_pseudo_entropy(12+7+11)); + if( c < 70 ) { + watch_clear_pixel(_get_pseudo_entropy(2),_get_pseudo_entropy(12+7+11)); + } + if ( c < 60 ) { + watch_clear_pixel(_get_pseudo_entropy(002),_get_pseudo_entropy(0xD68-0xD4A)); + } + if ( c < 50 ) { + watch_clear_pixel(_get_pseudo_entropy(0x2),_get_pseudo_entropy(14+9)); + } + delay_ms(_get_pseudo_entropy(c)+20); + if ( c < 30 ) { + watch_display_string(" ",_get_pseudo_entropy(10)); + } + watch_clear_pixel(_get_pseudo_entropy(02),_get_pseudo_entropy(3432-3409)); + watch_clear_pixel(_get_pseudo_entropy(002),_get_pseudo_entropy(51-28)); + watch_clear_pixel(_get_pseudo_entropy(0x2),_get_pseudo_entropy(23)); + if ( c < 20 ) { + watch_clear_pixel(_get_pseudo_entropy(02),_get_pseudo_entropy(51-28)); + watch_clear_pixel(_get_pseudo_entropy(2),_get_pseudo_entropy(14+9)); + watch_clear_pixel(_get_pseudo_entropy(0x2),_get_pseudo_entropy(0xD68-0xD4A)); + watch_clear_pixel(_get_pseudo_entropy(0x2),_get_pseudo_entropy(3432-3409)); + watch_clear_pixel(_get_pseudo_entropy(002),_get_pseudo_entropy(12+7+11)); + watch_clear_pixel(_get_pseudo_entropy(2),_get_pseudo_entropy(51-28)); + } + } + else + for ( uint8_t c = 30; c > 0; c--) { + watch_display_string("1", _get_pseudo_entropy(10)); + watch_display_string("0", _get_pseudo_entropy(10)); + watch_display_string("11", _get_pseudo_entropy(10)); + watch_display_string("00", _get_pseudo_entropy(10)); + delay_ms(50); + watch_display_string(" ", _get_pseudo_entropy(10)); + watch_display_string(" ", _get_pseudo_entropy(10)); + watch_display_string(" ", _get_pseudo_entropy(10)); + watch_display_string(" ", _get_pseudo_entropy(10)); + } + _generate_blindspot(state); + watch_clear_display(); + state->face.mode = 2; // point + state->face.location_format = 1; // distance + watch_display_string("RA Found", 0); + delay_ms(500); + sprintf(buf, "RA Found"); + break; + case 2: //point + switch ( state->face.location_format ) { + case 0: + sprintf(buf, "RA Point"); + break; + case 1: // distance to point + watch_clear_display(); + sprintf(buf, "DI m %d", state->point.distance ); + break; + case 2: // bearing relative to point + watch_clear_display(); + sprintf(buf, "BE # %d", state->point.bearing ); + break; + case 3: // latitude DD._____ + sprintf(state->scratchpad, "%07d", abs(state->point.latitude)); + sprintf(buf, "LA #%c %c%c ", state->point.latitude < 0 ? '-' : '+', state->scratchpad[0], state->scratchpad[1]); + break; + case 4: // latitude __.DDDDD + sprintf(buf, "LA , %c%c%c%c%c", state->scratchpad[2], state->scratchpad[3],state->scratchpad[4], state->scratchpad[5],state->scratchpad[6]); + break; + case 5: // longitude DD._____ + sprintf(state->scratchpad, "%08d", abs(state->point.longitude)); + sprintf(buf, "LO #%c%c%c%c ", state->point.longitude < 0 ? '-' : '+',state->scratchpad[0], state->scratchpad[1], state->scratchpad[2]); + break; + case 6: // longitude __.DDDDD + sprintf(buf, "LO , %c%c%c%c%c", state->scratchpad[3], state->scratchpad[4],state->scratchpad[5], state->scratchpad[6],state->scratchpad[7]); + break; + } + break; + case 3: // setup radius + watch_set_colon(); + if ( state->radius < 10000 ) + sprintf(buf, "RA m %d ", state->radius); + else + sprintf(buf, "RA m%d ", state->radius); + break; + case 4: // setup RNG + sprintf(buf, "RN G %s ", state->chance ? "Chnce" : (state->quantum ? "True" : "Psudo")); + break; + case 5: // data processing + sprintf(buf, "WR File "); + } + watch_display_string(buf, 0); +} + +/** @brief Official Randonautica Blindspot Algorithm + */ +static void _generate_blindspot(randonaut_state_t *state) { + + _get_entropy(state); + + double lat = (double)state->location.latitude / 100000; + double lon = (double)state->location.longitude / 100000; + uint16_t radius = state->radius; + + const double random_distance = radius * sqrt( (double)state->entropy / INT32_MAX ) / 1000.0; + const double random_bearing = 2.0 * PI * (double)state->entropy / INT32_MAX; + + const double phi = lat * PI / 180; + const double lambda = lon * PI / 180; + const double alpha = random_distance / R; + + lat = asin( sin(phi) * cos(alpha) + cos(phi) * sin(alpha) * cos(random_bearing) ); + lon = lambda + atan2( sin(random_bearing) * sin(alpha) * cos(phi), cos(alpha) - sin(phi) * sin( lat )); + + state->point.latitude = (int)round(lat * (180 / PI) * 100000); + state->point.longitude = (int)round(lon * (180 / PI) * 100000); + state->point.distance = random_distance * 1000; + state->point.bearing = (uint16_t)round(random_bearing * (180 / PI) < 0 ? random_bearing * (180 / PI) + 360 : random_bearing * (180 / PI)); +} + + +/** @brief pseudo random number generator + */ +static uint32_t _get_pseudo_entropy(uint32_t max) { + #if __EMSCRIPTEN__ + return rand() % max; + #else + return arc4random_uniform(max); + #endif +} + +/** @brief true random number generator + */ +static uint32_t _get_true_entropy(void) { + #if __EMSCRIPTEN__ + return rand() % INT32_MAX; + #else + hri_mclk_set_APBCMASK_TRNG_bit(MCLK); + hri_trng_set_CTRLA_ENABLE_bit(TRNG); + + while (!hri_trng_get_INTFLAG_reg(TRNG, TRNG_INTFLAG_DATARDY)); // Wait for TRNG data to be ready + + hri_trng_clear_CTRLA_ENABLE_bit(TRNG); + hri_mclk_clear_APBCMASK_TRNG_bit(MCLK); + return hri_trng_read_DATA_reg(TRNG); // Read a single 32-bit word from TRNG and return it + #endif +} + +/** @brief get location from place.loc + */ +static void _get_location_from_file(randonaut_state_t *state) { + movement_location_t movement_location = (movement_location_t) watch_get_backup_data(1); + coordinate_t place; + if (filesystem_file_exists("place.loc")) { + if (filesystem_read_file("place.loc", (char*)&place, sizeof(place))) + state->location = place; + } else { + watch_set_indicator(WATCH_INDICATOR_BELL); + state->location.latitude = movement_location.bit.latitude * 1000; + state->location.longitude = movement_location.bit.longitude * 1000; + } +} + +/** @brief save generated point to place.loc + */ +static void _save_point_to_file(randonaut_state_t *state) { + watch_set_indicator(WATCH_INDICATOR_SIGNAL); + coordinate_t place; + place.latitude = state->point.latitude; + place.longitude = state->point.longitude; + if (filesystem_write_file("place.loc", (char*)&place, sizeof(place))) { + delay_ms(100); + watch_clear_indicator(WATCH_INDICATOR_SIGNAL); + } else { + watch_clear_indicator(WATCH_INDICATOR_SIGNAL); + watch_set_indicator(WATCH_INDICATOR_BELL); + delay_ms(500); + watch_clear_indicator(WATCH_INDICATOR_BELL); + + } +} + +/** @brief get pseudo/quantum entropy and filter modulo bias + */ +static void _get_entropy(randonaut_state_t *state) { + if ( state->chance ) { + state->quantum = (bool)(state->entropy % 2); + } + do { + if ( !state->quantum ) { + state->entropy = _get_pseudo_entropy(INT32_MAX); + } else { + state->entropy = _get_true_entropy(); + } + } while (state->entropy >= INT32_MAX || state->entropy <= 0); + state->entropy %= INT32_MAX; +} \ No newline at end of file diff --git a/movement/watch_faces/complication/randonaut_face.h b/movement/watch_faces/complication/randonaut_face.h new file mode 100644 index 00000000..fabde798 --- /dev/null +++ b/movement/watch_faces/complication/randonaut_face.h @@ -0,0 +1,113 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 RANDONAUT_FACE_H_ +#define RANDONAUT_FACE_H_ + +#include "movement.h" +#include "place_face.h" + +/* + * RANDONAUT FACE + * ============== + * + * Randonauting is a way to turn the world around you into an adventure and get the user outside + * of their day-to-day routine by using a random number generator to derive a coordinate to journey + * to. In Randonauts lore so-called "Blind Spots" are places you cannot reach methodologically. They + * may exist in your own backyard for your whole life and you will never even notice them, because + * you simply have no reason to go to that exact place or look in its direction. Since the very + * limitations of our behavioral algorithms are the reason for the existence of blindspots, they + * can only be found using a randomizer. + * + * This watch face generates a random location based on the watch's location and a set radius using + * the official Randonautica Blind Spot algorithm. + * + * The ALARM button starts the random location generation and then automatically displays the found + * Blind Spot. + * + * By pressing ALARM again the user can flip through different pieces of information about the Blind + * Spot: Distance (DI), Bearing Degree (BE), Latitude degrees and decimal digits (LA), Longitude + * degrees and decimal digits (LO). + * + * Pressing LIGHT switches between generating a new blind spot ("Rando") and displaying the info of + * the last generated one ("Point"). + * + * LONG PRESSING LIGHT toggles setup mode. Here pressing LIGHT switches between setting the desired + * radius (RA) and setting the random number generator (RNG) for generating the blind spot. + * + * ALARM changes the values respectively: + * + * - The radius can be set in 500 meter steps between 1000 and 10,000 meters + * + * - The RNG can be set to "true" which utilizes the SAML22J's internal True Random Number Generator + * - Setting it to "psudo" will use the pseudorandom number generation algorithm arc4random + * - Setting it to "chance" will randomly chose either of the RNGs for each generation (default) + * + * LONG PRESSING ALARM toggles DATA mode in which the currently generated Blind Spot coordinate can + * be written to the file on the watch (press ALARM) and set as active high precision + * location used by other watch faces. It does not overwrite the low precision location information + * in the watch register commonly used for astronomical watch faces. + * + */ + +typedef struct { + uint8_t mode :3; + uint8_t location_format :3; + uint8_t rng: 2; +} randonaut_face_mode_t; + +typedef struct { + int32_t latitude : 26; + int32_t longitude : 26; + uint16_t distance : 14; + uint16_t bearing : 9; +} randonaut_coordinate_t; + +typedef struct { + // Anything you need to keep track of, put it here! + coordinate_t location; + randonaut_coordinate_t point; + uint16_t radius : 14; + uint32_t entropy; + bool quantum; + bool chance; + randonaut_face_mode_t face; + char scratchpad[10]; +} randonaut_state_t; + +void randonaut_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void randonaut_face_activate(movement_settings_t *settings, void *context); +bool randonaut_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void randonaut_face_resign(movement_settings_t *settings, void *context); + +#define randonaut_face ((const watch_face_t){ \ + randonaut_face_setup, \ + randonaut_face_activate, \ + randonaut_face_loop, \ + randonaut_face_resign, \ + NULL, \ +}) + +#endif // RANDONAUT_FACE_H_ + diff --git a/movement/watch_faces/complication/time_left_face.c b/movement/watch_faces/complication/time_left_face.c new file mode 100644 index 00000000..cc1077aa --- /dev/null +++ b/movement/watch_faces/complication/time_left_face.c @@ -0,0 +1,357 @@ +/* + * MIT License + * + * Copyright (c) 2022 Andreas Nebinger, based on the work of 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 +#include +#include "time_left_face.h" +#include "watch.h" +#include "watch_private_display.h" + +const char _state_titles[][3] = {{'D', 'L', ' '}, {'D', 'L', ' '}, {'D', 'A', ' '}, {'D', 'A', ' '}, {'Y', 'R', 'b'}, {'M', 'O', 'b'}, {'D', 'A', 'b'}, + {'Y', 'R', 'd'}, {'M', 'O', 'd'}, {'D', 'A', 'd'}}; +const uint8_t TIME_LEFT_FACE_STATES = sizeof(_state_titles) / 3; // total number of state pages +#define TIME_LEFT_FACE_SETTINGS_STATE 4 // number of first settings state +const uint8_t _percentage_segdata[][2] = {{1, 2}, {2, 2}, {2, 3}, {1, 3}}; // segment data for drawing the percentage sign +const uint8_t _animation_segdata[][2] = {{2, 8}, {1, 8}, {2, 7}, {2, 6}}; // segment data for the ticking animation + +static bool _quick_ticks_running; + +static uint32_t _juliandaynum(uint16_t year, uint16_t month, uint16_t day) { + // from here: https://en.wikipedia.org/wiki/Julian_day#Julian_day_number_calculation + return (1461 * (year + 4800 + (month - 14) / 12)) / 4 + (367 * (month - 2 - 12 * ((month - 14) / 12))) / 12 - (3 * ((year + 4900 + (month - 14) / 12) / 100))/4 + day - 32075; +} + +/// @brief displays an integer value with or without using positions 8 and 9 +static void _display_integer(char *buf) { + if (buf[1] == ' ') { + // display at position 4 if the value is short enough, don't use positions 8 and 9 + watch_display_character(' ', 8); + watch_display_character(' ', 9); + watch_display_string((char *)buf + 2, 4); + } else { + // otherwise just display using position 8 and 9 + watch_display_string(buf, 4); + } + watch_clear_colon(); +} + +///@brief display a percentage value +static void _display_percentage(float percentage, char *buf) { + // always stay positive + if (percentage < 0) { + percentage *= -1; + // Switch display to days 'O'ver + watch_display_character('O', 1); + } + int32_t integral = percentage; + if (integral >= 100) { + // percentage equals 100 or more: don't do fractional part + sprintf(buf, " %3li o", integral); + watch_clear_colon(); + } else { + // display percentage with two decimal places + uint8_t fraction = (int)(percentage * (float)100) % 100; + sprintf(buf, "%2li%02u o", integral, fraction); + watch_set_colon(); + } + watch_display_string(buf, 4); + // draw (parts of) percentage symbol + for (uint8_t i = 0; i < sizeof(_percentage_segdata) / 2; i++) + watch_set_pixel(_percentage_segdata[i][0], _percentage_segdata[i][1]); +} + +/// @brief draw the current state to the display +static void _draw(time_left_state_t *state, uint8_t subsecond) { + char buf[17]; + watch_display_character(_state_titles[state->current_page][0], 0); + watch_display_character(_state_titles[state->current_page][1], 1); + watch_display_character(' ', 2); + watch_display_character(_state_titles[state->current_page][2], 3); + if (state->current_page < TIME_LEFT_FACE_SETTINGS_STATE) { + // we are displaying days left or days from birth + watch_date_time date_time = watch_rtc_get_date_time(); + uint32_t julian_current_day = _juliandaynum(date_time.unit.year + WATCH_RTC_REFERENCE_YEAR, date_time.unit.month, date_time.unit.day); + uint32_t julian_target_day = _juliandaynum(state->target_date.bit.year, state->target_date.bit.month, state->target_date.bit.day); + int32_t days_left = julian_target_day - julian_current_day; + if (state->current_page == 0) { + // display number of days left + sprintf(buf, "%6li", days_left); + _display_integer(buf); + } else { + // calculate starting date + uint32_t julian_start_day = _juliandaynum(state->birth_date.bit.year, state->birth_date.bit.month, state->birth_date.bit.day); + if ((state->current_page & 1) == 1) { + float percentage_left; + if (julian_start_day == julian_target_day) { + // failsafe + percentage_left = 0; + } else { + // display correct percentages + percentage_left = (float)days_left * (float)100 / (float)(julian_target_day - julian_start_day); + } + _display_percentage(state->current_page == 1 ? percentage_left : 100 - percentage_left, buf); + } else { + // display days from birth + sprintf(buf, "%6li", (int32_t)julian_current_day - julian_start_day); + _display_integer(buf); + } + } + } else { + // we are in settings mode + switch (state->current_page) { + case TIME_LEFT_FACE_SETTINGS_STATE: + // birth year + sprintf(buf, "%04u ", state->birth_date.bit.year); + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 1: + // birth month + sprintf(buf, " %02u", state->birth_date.bit.month); + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 2: + // birth day of month + sprintf(buf, " %02u", state->birth_date.bit.day); + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 3: + // target year + sprintf(buf, "%04u", state->target_date.bit.year); + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 4: + // target month + sprintf(buf, " %02u", state->target_date.bit.month); + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 5: + // target day of month + sprintf(buf, " %02u", state->target_date.bit.day); + break; + default: + break; + } + // blink current settings position or display value + if ((subsecond & 1) == 1) + watch_display_string(" ", 4); + else + watch_display_string(buf, 4); + } +} + +/// @brief handle short or long pressing the alarm button +static void _handle_alarm_button(time_left_state_t *state) { + + const uint8_t days_in_month[12] = {31, 28, 31, 30, 31, 30, 30, 31, 30, 31, 30, 31}; + uint32_t tmp_day; + switch (state->current_page) { + case TIME_LEFT_FACE_SETTINGS_STATE: // birth year + state->birth_date.bit.year++; + if (state->birth_date.bit.year > state->current_year + 10) state->birth_date.bit.year = 1959; + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 1: // birth month + state->birth_date.bit.month = (state->birth_date.bit.month % 12) + 1; + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 2: // birth day + tmp_day = state->birth_date.bit.day; // use a temporary variable to avoid messing up the months + tmp_day++; + // handle February 29th on a leap year + if (((tmp_day > days_in_month[state->birth_date.bit.month - 1]) && (state->birth_date.bit.month != 2 || (state->birth_date.bit.year % 4) != 0)) + || (state->birth_date.bit.month == 2 && (state->birth_date.bit.year % 4) == 0 && tmp_day > 29)) { + tmp_day = 1; + } + state->birth_date.bit.day = tmp_day; + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 3: // target year + state->target_date.bit.year++; + if (state->target_date.bit.year >2083) state->target_date.bit.year = state->current_year - 10; + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 4: // target month + state->target_date.bit.month = (state->target_date.bit.month % 12) + 1; + break; + case TIME_LEFT_FACE_SETTINGS_STATE + 5: // target day + tmp_day = state->target_date.bit.day; + tmp_day++; + // handle February 29th on a leap year + if (((tmp_day > days_in_month[state->target_date.bit.month - 1]) && (state->target_date.bit.month != 2 || (state->target_date.bit.year % 4) != 0)) + || (state->target_date.bit.month == 2 && (state->target_date.bit.year % 4) == 0 && tmp_day > 29)) { + tmp_day = 1; + } + state->target_date.bit.day = tmp_day; + break; + } +} + +static void _initiate_setting(time_left_state_t *state) { + state->current_page = TIME_LEFT_FACE_SETTINGS_STATE; + watch_clear_colon(); + movement_request_tick_frequency(4); +} + +static void _resume_setting(time_left_state_t *state) { + state->current_page = 0; + movement_request_tick_frequency(1); +} + +static void _abort_quick_ticks() { + if (_quick_ticks_running) { + _quick_ticks_running = false; + movement_request_tick_frequency(4); + } +} + +void time_left_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(time_left_state_t)); + memset(*context_ptr, 0, sizeof(time_left_state_t)); + time_left_state_t *state = (time_left_state_t *)*context_ptr; + state->birth_date.reg = watch_get_backup_data(2); + if (state->birth_date.reg == 0) { + // if birth date is totally blank, set a reasonable starting date. this works well for anyone under 63, but + // you can keep pressing to go back to 1900; just pass the current year. also picked this date because if you + // set it to 1959-01-02, it counts up from the launch of Luna-1, the first spacecraft to leave the well. + state->birth_date.bit.year = 1959; + state->birth_date.bit.month = 1; + state->birth_date.bit.day = 1; + watch_store_backup_data(state->birth_date.reg, 2); + // set target date to today + 10 years (just to have any value) + watch_date_time date_time = watch_rtc_get_date_time(); + state->target_date.bit.year = date_time.unit.year + WATCH_RTC_REFERENCE_YEAR + 10; + state->target_date.bit.month = date_time.unit.month; + state->target_date.bit.day = date_time.unit.day; + } + } +} + +void time_left_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + time_left_state_t *state = (time_left_state_t *)context; + + // stash the current year, useful in birthday setting mode + watch_date_time date_time = watch_rtc_get_date_time(); + state->current_year = date_time.unit.year + WATCH_RTC_REFERENCE_YEAR; + _quick_ticks_running = false; + // fetch the user's birth date from the birthday register + state->birth_date.reg = watch_get_backup_data(2); + // store original value of the birthdate to be able to detect changes on resigning + state->birth_date_when_activated.reg = state->birth_date.reg; +} + +bool time_left_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + (void) settings; + time_left_state_t *state = (time_left_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + _draw(state, event.subsecond); + break; + case EVENT_LOW_ENERGY_UPDATE: + case EVENT_TICK: { + uint8_t subsecond = event.subsecond; + if (_quick_ticks_running) { + if (watch_get_pin_level(BTN_ALARM)) { + _handle_alarm_button(state); + subsecond = 0; + } else _abort_quick_ticks(); + } + if (state->current_page >= TIME_LEFT_FACE_SETTINGS_STATE) { + // we are in settings mode. Draw to blink + _draw(state, subsecond); + } else { + // otherwise, check if we have to update. the display only needs to change at midnight + watch_date_time date_time = watch_rtc_get_date_time(); + if (date_time.unit.hour == 0 && date_time.unit.minute == 0 && date_time.unit.second == 0) { + _draw(state, subsecond); + } + // handle the ticking animation + uint8_t animation_step = date_time.unit.second % (sizeof(_animation_segdata) / 2); + watch_set_pixel(_animation_segdata[animation_step][0], _animation_segdata[animation_step][1]); + if (animation_step == 0) animation_step = (sizeof(_animation_segdata) / 2) - 1; + else animation_step--; + watch_clear_pixel(_animation_segdata[animation_step][0], _animation_segdata[animation_step][1]); + } + break; + } + case EVENT_LIGHT_BUTTON_DOWN: + // do not illuminate here (this is done when releasing the button) + break; + case EVENT_LIGHT_BUTTON_UP: + if (state->current_page < TIME_LEFT_FACE_SETTINGS_STATE) movement_illuminate_led(); + else { + // cycle through the settings pages + state->current_page++; + if (state->current_page >= TIME_LEFT_FACE_STATES) { + // we have done a full settings cycle, so resume to normal + _resume_setting(state); + _draw(state, event.subsecond); + } + } + break; + case EVENT_LIGHT_LONG_PRESS: + if (state->current_page >= TIME_LEFT_FACE_SETTINGS_STATE) { + _resume_setting(state); + } else { + _initiate_setting(state); + } + _draw(state, event.subsecond); + break; + case EVENT_ALARM_BUTTON_UP: + _abort_quick_ticks(); + if (state->current_page < TIME_LEFT_FACE_SETTINGS_STATE) { + // alternate between days left and percentage left + state->current_page = (state->current_page + 1) % TIME_LEFT_FACE_SETTINGS_STATE; + } else { + // we are in settings mode, so increment the current settings value + _handle_alarm_button(state); + } + _draw(state, 0); + break; + case EVENT_ALARM_LONG_PRESS: + if (state->current_page >= TIME_LEFT_FACE_SETTINGS_STATE) { + // initiate fast cycling for settings values + movement_request_tick_frequency(8); + _quick_ticks_running = true; + _handle_alarm_button(state); + _draw(state, 0); + } + break; + case EVENT_TIMEOUT: + movement_move_to_face(0); + break; + default: + movement_default_loop_handler(event, settings); + break; + } + + return true; +} + +void time_left_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + time_left_state_t *state = (time_left_state_t *)context; + + if (state->current_page >= TIME_LEFT_FACE_SETTINGS_STATE) _resume_setting(state); + + // if the user changed their birth date, store it to the birth date register + if (state->birth_date_when_activated.reg != state->birth_date.reg) { + watch_store_backup_data(state->birth_date.reg, 2); + } +} diff --git a/movement/watch_faces/complication/time_left_face.h b/movement/watch_faces/complication/time_left_face.h new file mode 100644 index 00000000..0ed7fd28 --- /dev/null +++ b/movement/watch_faces/complication/time_left_face.h @@ -0,0 +1,89 @@ +/* + * MIT License + * + * Copyright (c) 2022 Andreas Nebinger, based on the work of 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 TIME_LEFT_FACE_H_ +#define TIME_LEFT_FACE_H_ + +#include "movement.h" + +/* + * The Time Left Face helps you to visualize how far you have proceeded in a certain + * time span. Much like the Day One Face, you can set your beginning date. In addition + * to that, you also set your target or destination date. You can then use the face + * to display your progress in different ways. + * + * Usage: + * + * - Long pressing of the light button starts the settings mode: + * - First, you set the beginning date (indicated by a 'b' in the upper right corner). + * - Start by setting the year (indicated by the letter 'YR'). Use the alarm button + * to cycle the value. Short pressing the light button brings you to the next + * settings page. + * - Set the values in this order: + * a. beginning date (indicated by a 'b'): year - month - day + * b. destination date (indicated by a 'd'): year - month - day + * - After cycling through all settings pages, the face resumes to display mode. + * + * - In display mode, use the alarm button (short press) to cycle through these four + * types of display: + * a. number of days left ('DL') until the destination date is reached. + * b. remaining days expressed as percentage of total time span. The value is shown + * with two decimals, using the colon as decimal point. + * c. number of days passed ('DA') since the beginning date. + * d. number of days passed expressed as percentage of total time span. (Two decimal + * points.) + * + * What is this for? + * + * You can use this watch face to be reminded of any kind of progess between a set + * start and end date. The brave among us can use it as a kind of memento mori + * visualization. Set your date of birth and look up the average life expectancy of + * your age cohort based on publicly available mortality tables. Then, set the + * statistically expected day of death as the target date and you will be able to + * see how much of your time has passed and how much is still to come. + * + */ + +typedef struct { + uint8_t current_page; + uint16_t current_year; + movement_birthdate_t birth_date; + movement_birthdate_t birth_date_when_activated; + movement_birthdate_t target_date; +} time_left_state_t; + +void time_left_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void time_left_face_activate(movement_settings_t *settings, void *context); +bool time_left_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void time_left_face_resign(movement_settings_t *settings, void *context); + +#define time_left_face ((const watch_face_t){ \ + time_left_face_setup, \ + time_left_face_activate, \ + time_left_face_loop, \ + time_left_face_resign, \ + NULL, \ +}) + +#endif // TIME_LEFT_FACE_H_ diff --git a/movement/watch_faces/complication/toss_up_face.c b/movement/watch_faces/complication/toss_up_face.c new file mode 100644 index 00000000..08dd0052 --- /dev/null +++ b/movement/watch_faces/complication/toss_up_face.c @@ -0,0 +1,793 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 +#include +#include "toss_up_face.h" +#if __EMSCRIPTEN__ +#include +#else +#include "saml22j18a.h" +#endif + +static const char heads[] = { '8', 'h', '4', 'E', '(' }; +static const char tails[] = { '0', '+', 'N', '3', ')' }; +static const uint8_t dd[] = {2, 4, 6, 8, 10,12,20,24,30,32,36,48,99}; + +static void _roll_dice_multiple(char* result, uint8_t* dice, uint8_t num_dice); +static void _sort_coins(char* token, uint8_t num_bits, uint8_t bits, char* heads, char* tails); +void _display_coins(char* token, bool* bit_array, uint8_t length, toss_up_state_t *state); +static void _toss_up_face_display(toss_up_state_t *state); +static void _dice_animation(toss_up_state_t *state); +static void _coin_animation(toss_up_state_t *state); + +// PUBLIC FUNCTIONS /////////////////////////////////////////////////////////// + +void toss_up_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(toss_up_state_t)); + memset(*context_ptr, 0, sizeof(toss_up_state_t)); + toss_up_state_t *state = (toss_up_state_t *)*context_ptr; + + // defaults + state->coin_num = 1; + state->dice_num = 1; + state->dice_sides[0] = 6; + state->dice_sides[1] = 6; + state->dice_sides[2] = 6; + state->coin_style[0] = '8'; + state->coin_style[1] = '0'; + } +} + +void toss_up_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; +} + +bool toss_up_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + toss_up_state_t *state = (toss_up_state_t *)context; + uint8_t i = 0; + switch (event.event_type) { + case EVENT_ACTIVATE: + watch_display_string(" Coins ", 0); + break; + case EVENT_TICK: + if ( state->animate ) { + state->animation = (state->animation + 1); + _toss_up_face_display(state); + } + break; + case EVENT_LIGHT_BUTTON_DOWN: + break; + case EVENT_LIGHT_BUTTON_UP: + if ( state->animate ) break; + // change between coins and dice + if ( state->mode <= 1 ) state->mode = 2; + else if ( state->mode >= 2 ) state->mode = 0; + _toss_up_face_display(state); + break; + case EVENT_ALARM_BUTTON_UP: + // toss + if ( state->animate ) break; + switch (state->mode) { + case 0: + state->mode++; + // fall through + case 1: + state->animate = true; + for (i = 0; i < state->coin_num; i++) { + state->coins[i] = divine_bit(); + } + break; + case 2: + state->mode++; + // fall through + case 3: + state->animate = true; + for (i = 0; i < state->dice_num; i++) { + state->dice[i] = roll_dice(state->dice_sides[i]); + } + break; + default: + break; + } + _toss_up_face_display(state); + break; + case EVENT_LIGHT_LONG_PRESS: + if ( state->animate ) break; + state->animate = false; + switch (state->mode) { + case 0: // change to default coin style + state->coin_style[0] = heads[0]; + state->coin_style[1] = tails[0]; + state->coinface = 0; + break; + case 1: // change the coin style + state->coinface = (state->coinface + 1) % 5; + state->coin_style[0] = heads[state->coinface]; + state->coin_style[1] = tails[state->coinface]; + break; + case 2: // change to default dice sides + state->dice_sides[0] = 6; + state->dice_sides[1] = 6; + state->dice_sides[2] = 6; + state->dd = 0; + break; + case 3: // change the sides of the dice + state->dd = (state->dd + 1) % 13; + state->dice_sides[state->dice_num-1] = dd[state->dd]; + state->dice[state->dice_num-1] = dd[state->dd]; + break; + default: + break; + } + _toss_up_face_display(state); + break; + case EVENT_ALARM_LONG_PRESS: + if ( state->animate ) break; + state->animate = false; + switch (state->mode) { + case 0: // back to one coin + state->coin_num = 1; + break; + case 1: // up to 6 coins total + state->coin_num = (state->coin_num % 6) + 1; + break; + case 2: // back to one dice + state->dice_num = 1; + break; + case 3: // add up to 3 dice total + state->dice_num = (state->dice_num % 3) + 1; + state->dd = 0; + break; + default: + break; + } + _toss_up_face_display(state); + break; + default: + return movement_default_loop_handler(event, settings); + } + + return true; +} + +void toss_up_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; +} + +// STATIC FUNCTIONS /////////////////////////////////////////////////////////// + +/** @brief handles the display + */ +static void _toss_up_face_display(toss_up_state_t *state) { + char buf[11] = {0}; + char token[7] = {0}; + switch ( state->mode ) { + case 0: // coins title + sprintf(buf, " Coins "); + break; + case 1: // coins divination + _coin_animation(state); + if ( !state->animate ) { + watch_clear_display(); + _display_coins(token, state->coins, state->coin_num, state); + sprintf(buf, " %s", token); + } + break; + case 2: // dice title + sprintf(buf, " Dice "); + break; + case 3: // dice divination + _dice_animation(state); + if ( !state->animate ) { + _roll_dice_multiple(token, state->dice, state->dice_num + 1); + sprintf(buf, " %s", token); + } + break; + default: + break; + } + watch_display_string(buf, 0); +} + +/** @brief divination method to derive a bit from 32 TRNG bits + */ +uint8_t divine_bit(void) { + uint32_t stalks; + do { // modulo bias filter + stalks = get_true_entropy(); // get 32 TRNG bits as stalks + } while (stalks >= INT32_MAX || stalks <= 0); + + uint8_t pile1_xor = 0; + uint8_t pile2_xor = 0; + // Divide the stalks into two piles, alternating ends + for (uint8_t i = 0; i < 16; i++) { + uint8_t left_bit = (stalks >> (31 - 2*i)) & 1; + uint8_t right_bit = (stalks >> (30 - 2*i)) & 1; + if (i % 2 == 0) { + pile1_xor ^= left_bit; + pile2_xor ^= right_bit; + } else { + pile1_xor ^= right_bit; + pile2_xor ^= left_bit; + } + } + // Take the XOR of the pile results + uint8_t result_xor = pile1_xor ^ pile2_xor; + // Output 1 if result_xor is 1, 0 otherwise + return result_xor; +} + +/** @brief get 32 True Random Number bits + */ +uint32_t get_true_entropy(void) { + #if __EMSCRIPTEN__ + return rand() % INT32_MAX; + #else + hri_mclk_set_APBCMASK_TRNG_bit(MCLK); + hri_trng_set_CTRLA_ENABLE_bit(TRNG); + + while (!hri_trng_get_INTFLAG_reg(TRNG, TRNG_INTFLAG_DATARDY)); // Wait for TRNG data to be ready + + hri_trng_clear_CTRLA_ENABLE_bit(TRNG); + hri_mclk_clear_APBCMASK_TRNG_bit(MCLK); + return hri_trng_read_DATA_reg(TRNG); // Read a single 32-bit word from TRNG and return it + #endif +} + +// COIN FUNCTIONS ///////////////////////////////////////////////////////////// + +/** @brief sort tossed coins into a pile of heads and a pile of tails + */ +static void _sort_coins(char* token, uint8_t num_bits, uint8_t bits, char* heads, char* tails) { + uint8_t num_ones = 0; + for (uint8_t i = 0; i < num_bits; i++) { + if ((bits >> i) & 1) { + *token++ = *heads; + num_ones++; + } + } + if ( num_bits < 6 ) { + for (uint8_t i = 0; i < (6 - num_bits); i++) { + *token++ = ' '; + } + } + for (uint8_t i = 0; i < (num_bits - num_ones); i++) { + + *token++ = *tails; + } +} + +/** @brief convert bool array of coinflips to integer for sorting + */ +void _display_coins(char* token, bool* bit_array, uint8_t length, toss_up_state_t *state) { + uint8_t bits = 0; + for (uint8_t i = 0; i < length; i++) { + if (bit_array[i]) { + bits |= (1 << (length - 1 - i)); + } + } + _sort_coins(token, length, bits, &state->coin_style[0], &state->coin_style[1]); +} + +/** @brief coin animation + */ +static void _coin_animation(toss_up_state_t *state) { + bool heads = false; + bool tails = false; + for (uint8_t i = 0; i < state->coin_num; i++) { + if (state->coins[i] == true) { + heads = true; + } else { + tails = true; + } + } + movement_request_tick_frequency(32); + switch ( state->animation ) { + case 0: + watch_display_string(" ", 4); + if ( heads ) { + watch_set_pixel(0, 18); + watch_set_pixel(2, 18); + } else { + state->animation = 12; + } + break; + case 1: + if ( heads ) { + watch_set_pixel(1, 18); + } + break; + case 2: + if ( heads ) { + watch_set_pixel(0, 19); + watch_set_pixel(2, 19); + } + break; + case 3: + if ( heads ) { + watch_clear_pixel(0, 18); + watch_clear_pixel(2, 18); + } + break; + case 4: + if ( heads ) { + watch_clear_pixel(1, 18); + } + break; + case 5: + if ( heads ) { + watch_clear_pixel(0, 19); + watch_clear_pixel(2, 19); + watch_set_pixel(1, 17); + watch_set_pixel(0, 20); + } + break; + case 6: + if ( heads ) { + watch_set_pixel(2, 20); + watch_set_pixel(0, 21); + } + break; + case 7: + if ( heads ) { + watch_set_pixel(1, 21); + watch_set_pixel(2, 21); + } + break; + case 8: + if ( heads ) { + watch_clear_pixel(1, 17); + watch_clear_pixel(0, 20); + } + break; + case 9: + if ( heads ) { + watch_clear_pixel(2, 20); + watch_clear_pixel(0, 21); + } + break; + case 10: + if ( heads ) { + watch_clear_pixel(1, 21); + watch_clear_pixel(2, 21); + watch_set_pixel(1, 22); + watch_set_pixel(2, 22); + } + break; + case 11: + if ( heads ) { + watch_set_pixel(0, 22); + } + break; + case 12: + if ( heads ) { + watch_set_pixel(2, 23); + watch_set_pixel(0, 23); + } + if ( tails ) { + watch_set_pixel(0, 18); + watch_set_pixel(2, 18); + } + break; + case 13: + if ( heads ) { + watch_clear_pixel(1, 22); + watch_clear_pixel(2, 22); + } + if ( tails ) { + watch_set_pixel(1, 18); + } + break; + case 14: + if ( heads ) { + watch_clear_pixel(0, 22); + } + if ( tails ) { + watch_set_pixel(0, 19); + watch_set_pixel(2, 19); + } + break; + case 15: + if ( heads ) { + watch_clear_pixel(2, 23); + watch_clear_pixel(0, 23); + watch_set_pixel(2, 0); + watch_set_pixel(1, 0); + } + if ( tails ) { + watch_clear_pixel(0, 18); + watch_clear_pixel(2, 18); + } + break; + case 16: + if ( heads ) { + watch_set_pixel(2, 1); + watch_set_pixel(0, 0); + } + if ( tails ) { + watch_clear_pixel(1, 18); + } + break; + case 17: + if ( heads ) { + watch_set_pixel(2, 10); + watch_set_pixel(0, 1); + } + if ( tails ) { + watch_clear_pixel(0, 19); + watch_clear_pixel(2, 19); + watch_set_pixel(1, 17); + watch_set_pixel(0, 20); + } + break; + case 18: + if ( heads ) { + watch_clear_pixel(2, 0); + watch_clear_pixel(1, 0); + } + if ( tails ) { + watch_set_pixel(2, 20); + watch_set_pixel(0, 21); + } + break; + case 19: + if ( heads ) { + watch_clear_pixel(2, 1); + watch_clear_pixel(0, 0); + } + if ( tails ) { + watch_set_pixel(1, 21); + watch_set_pixel(2, 21); + } + break; + case 20: + if ( heads ) { + watch_set_pixel(2, 1); + watch_set_pixel(0, 0); + } + if ( tails ) { + watch_clear_pixel(1, 17); + watch_clear_pixel(0, 20); + } + break; + case 21: + if ( heads ) { + watch_set_pixel(2, 0); + watch_set_pixel(1, 0); + } + if ( tails ) { + watch_clear_pixel(2, 20); + watch_clear_pixel(0, 21); + } + break; + case 22: + if ( heads ) { + watch_clear_pixel(2, 10); + watch_clear_pixel(0, 1); + } + if ( tails ) { + watch_clear_pixel(1, 21); + watch_clear_pixel(2, 21); + watch_set_pixel(1, 22); + watch_set_pixel(2, 22); + } + break; + case 23: + if ( heads ) { + watch_clear_pixel(2, 1); + watch_clear_pixel(0, 0); + } + if ( tails ) { + watch_set_pixel(0, 22); + } + break; + case 24: + if ( heads ) { + watch_set_pixel(2, 23); + watch_set_pixel(0, 23); + watch_clear_pixel(2, 0); + watch_clear_pixel(1, 0); + } + if ( tails ) { + watch_set_pixel(2, 23); + watch_set_pixel(0, 23); + } + break; + case 25: + if ( heads ) { + watch_set_pixel(0, 22); + } + if ( tails ) { + watch_clear_pixel(1, 22); + watch_clear_pixel(2, 22); + } + break; + case 26: + if ( heads ) { + watch_set_pixel(1, 22); + watch_set_pixel(2, 22); + } + if ( tails ) { + watch_clear_pixel(0, 22); + } + break; + case 27: + if ( heads ) { + watch_clear_pixel(2, 23); + watch_clear_pixel(0, 23); + } + if ( tails ) { + watch_clear_pixel(2, 23); + watch_clear_pixel(0, 23); + watch_set_pixel(2, 0); + watch_set_pixel(1, 0); + } + break; + case 28: + if ( heads ) { + watch_clear_pixel(0, 22); + } + if ( tails ) { + watch_set_pixel(2, 1); + watch_set_pixel(0, 0); + } + break; + case 29: + if ( heads ) { + watch_set_pixel(1, 21); + watch_set_pixel(2, 21); + watch_clear_pixel(1, 22); + watch_clear_pixel(2, 22); + } + if ( tails ) { + watch_set_pixel(2, 10); + watch_set_pixel(0, 1); + } + break; + case 30: + if ( heads ) { + watch_set_pixel(2, 20); + watch_set_pixel(0, 21); + } + if ( tails ) { + watch_clear_pixel(1, 0); + watch_clear_pixel(2, 0); + } + break; + case 31: + if ( heads ) { + watch_set_pixel(1, 17); + watch_set_pixel(0, 20); + } + if ( tails ) { + watch_clear_pixel(2, 1); + watch_clear_pixel(0, 0); + } + break; + case 32: + if ( heads ) { + watch_clear_pixel(1, 21); + watch_clear_pixel(2, 21); + } + if ( tails ) { + watch_clear_pixel(2, 10); + watch_clear_pixel(0, 1); + watch_set_pixel(0, 2); + watch_set_pixel(1, 2); + } + break; + case 33: + if ( heads ) { + watch_clear_pixel(2, 20); + watch_clear_pixel(0, 21); + } + if ( tails ) { + watch_set_pixel(2, 2); + watch_set_pixel(0, 3); + } + break; + case 34: + if ( heads ) { + watch_set_pixel(0, 19); + watch_set_pixel(2, 19); + watch_clear_pixel(1, 17); + watch_clear_pixel(0, 20); + } + if ( tails ) { + watch_set_pixel(2, 3); + watch_set_pixel(0, 4); + } + break; + case 35: + if ( heads ) { + watch_set_pixel(1, 18); + } + if ( tails ) { + watch_clear_pixel(1, 2); + watch_clear_pixel(0, 2); + } + break; + case 36: + if ( heads ) { + watch_set_pixel(0, 18); + watch_set_pixel(2, 18); + } + if ( tails ) { + watch_clear_pixel(2, 2); + watch_clear_pixel(0, 3); + } + break; + case 37: + if ( heads ) { + watch_clear_pixel(0, 19); + watch_clear_pixel(2, 19); + } + if ( tails ) { + watch_clear_pixel(2, 3); + watch_clear_pixel(0, 4); + watch_set_pixel(1, 4); + watch_set_pixel(0, 5); + } + break; + case 38: + if ( heads ) { + watch_clear_pixel(1, 18); + } + if ( tails ) { + watch_set_pixel(2, 4); + watch_set_pixel(0, 6); + } + break; + case 39: + if ( heads ) { + watch_clear_pixel(0, 18); + watch_clear_pixel(2, 18); + } + if ( tails ) { + watch_set_pixel(1, 6); + watch_set_pixel(2, 5); + } + state->animate = false; + state->animation = 0; + movement_request_tick_frequency(1); + } +} + +// DICE FUNCTIONS ///////////////////////////////////////////////////////////// + +/** @brief rolls a dice + */ +uint8_t roll_dice(uint8_t sides) { + uint8_t bits_needed = 0; + uint8_t temp_sides = sides - 1; + uint8_t result = 0; + while (temp_sides > 0) { + bits_needed++; // how many bits do we need to represent this number? + temp_sides >>= 1; // Shift right to check the next bit + } + do { + result = 0; + for (int i = 0; i < bits_needed; i++) { + result <<= 1; // Shift left to make room for the next bit + result |= divine_bit(); // Add the next bit to the result + } + } while ( result > sides -1 ); + return result + 1; // Add 1 to convert the range from 0 to sides-1 to 1 to sides +} + +/** @brief roll multiple dice and print a char array for displaying them + */ +static void _roll_dice_multiple(char* result, uint8_t* dice, uint8_t num_dice) { + // initialize the result array to all spaces + memset(result, ' ', 6); + + // roll the dice and write the result to the result array + for (uint8_t i = 0; i < num_dice-1; i++) { + uint8_t dice_result = dice[i]; + uint8_t tens_digit = dice_result / 10; + uint8_t ones_digit = dice_result % 10; + result[(i * 2)] = tens_digit == 0 ? ' ' : (char)('0' + tens_digit); + result[(i * 2) + 1] = (char)('0' + ones_digit); + } +} + +/** @brief dice animation + */ +static void _dice_animation(toss_up_state_t *state) { + watch_display_string(" ", 4); + for (uint8_t i = 0; i < state->dice_num; i++) { + watch_display_string("0",i*2 + 5); + } + movement_request_tick_frequency(16); + switch ( state->animation ) { + case 0: + watch_clear_pixel(1, 17); + watch_clear_pixel(0, 0); + watch_clear_pixel(1, 6); + break; + case 1: + watch_clear_pixel(2, 20); + watch_clear_pixel(1, 0); + watch_clear_pixel(0, 6); + break; + case 2: + watch_clear_pixel(2, 21); + watch_clear_pixel(2, 0); + watch_clear_pixel(0, 5); + break; + case 3: + watch_clear_pixel(1, 21); + watch_clear_pixel(2, 1); + watch_clear_pixel(1, 4); + break; + case 4: + watch_clear_pixel(0, 21); + watch_clear_pixel(2, 10); + watch_clear_pixel(2, 4); + break; + case 5: + watch_clear_pixel(0, 20); + watch_clear_pixel(0, 1); + watch_clear_pixel(2, 5); + break; + case 6: + watch_clear_pixel(1, 17); + watch_clear_pixel(0, 0); + watch_clear_pixel(1, 6); + break; + case 7: + watch_clear_pixel(2, 20); + watch_clear_pixel(1, 0); + watch_clear_pixel(0, 6); + break; + case 8: + watch_clear_pixel(2, 21); + watch_clear_pixel(2, 0); + watch_clear_pixel(0, 5); + break; + case 9: + watch_clear_pixel(1, 21); + watch_clear_pixel(2, 1); + watch_clear_pixel(1, 4); + break; + case 10: + watch_clear_pixel(0, 21); + watch_clear_pixel(2, 10); + watch_clear_pixel(2, 4); + break; + case 11: + watch_clear_pixel(0, 20); + watch_clear_pixel(0, 1); + watch_clear_pixel(2, 5); + state->animate = false; + state->animation = 0; + movement_request_tick_frequency(1); + } +} \ No newline at end of file diff --git a/movement/watch_faces/complication/toss_up_face.h b/movement/watch_faces/complication/toss_up_face.h new file mode 100644 index 00000000..ca6136a7 --- /dev/null +++ b/movement/watch_faces/complication/toss_up_face.h @@ -0,0 +1,112 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 TOSS_UP_FACE_H_ +#define TOSS_UP_FACE_H_ + +#include "movement.h" + +/* + * TOSS UP FACE + * ============ + * + * Playful watch face for games of chance or divination using coins or dice. + * + * LIGHT switches between Coins and Dice mode + * + * COINS + * ===== + * + * ALARM tosses a coin. If it lands on heads it gets sorted to the left side of the + * display, if it lands on tails then sorted to the right side. + * + * LONG PRESSING ALARM adds up to 5 more coins to the toss for more nuance in the decision + * making (e.g. three heads vs two tails could be read as "yes, but with serious doubts"). + * + * LONG PRESSING LIGHT flips through additional style for the coins from the default Ө/O + * to H/T (heads/tails), Y/N (yes/no), E/Ǝ, C/Ↄ + * + * LONG PRESSING ALARM on the "Coins" title page resets to one coin. + * LONG PRESSING LIGHT on the "Coins" title page resets the style to Ө/O + * + * DICE + * ==== + * + * ALARM rolls a six sided dice. + * + * LONG PRESSING ALARM adds up to 2 more dice to the roll. + * + * LONG PRESSING LIGHT flips through other available polyhedral dice types with less or more + * than the default 6 sides. The options are D2, D4, D6, D8, D10, D12, D20, D24, D30, D32, D36, + * D48, and a hypothetical D99. + * + * When more than one dice is used for a roll this changes only the last added dice. (see Note + * below) + * + * LONG PRESSING ALARM on the "Dice" title page resets to one dice. + * LONG PRESSING LIGHT on the "Dice" title page resets the dice to D6. + * + * Please Note: If you need let's say a D8, D12, and D20 for your rolls then the procedure to + * set this up would be as follows: from the default screen where you can roll the one D6 dice + * you would LONG PRESS LIGHT a few times to change the D6 to a D8, then LONG PRESS ALARM to add + * a second dice, LONG PRESS LIGHT again until the second dice changes to D12, then LONG PRESS + * ALARM to add the third dice and LONG PRESS LIGHT again a few times until it becomes a D20. + * + */ + +typedef struct { + // Anything you need to keep track of, put it here! + uint32_t entropy; + uint8_t mode : 4; // 1 coin, 2 coins, 3 coins, 4 coins, dice, iching, geomnc + bool setup; + bool coins[6]; + uint8_t coin_num : 3; + char coin_style[2]; + uint8_t coinface : 3; + uint8_t dice[3]; + uint8_t dice_num : 2; + uint8_t dd : 6; + uint8_t dice_sides[3]; + uint8_t animation; + bool animate; +} toss_up_state_t; + +uint32_t get_true_entropy(void); +uint8_t divine_bit(void); +uint8_t roll_dice(uint8_t sides); +void toss_up_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void toss_up_face_activate(movement_settings_t *settings, void *context); +bool toss_up_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void toss_up_face_resign(movement_settings_t *settings, void *context); + +#define toss_up_face ((const watch_face_t){ \ + toss_up_face_setup, \ + toss_up_face_activate, \ + toss_up_face_loop, \ + toss_up_face_resign, \ + NULL, \ +}) + +#endif // TOSS_UP_FACE_H_ + diff --git a/movement/watch_faces/demo/chirpy_demo_face.c b/movement/watch_faces/demo/chirpy_demo_face.c new file mode 100644 index 00000000..ee3e5b41 --- /dev/null +++ b/movement/watch_faces/demo/chirpy_demo_face.c @@ -0,0 +1,335 @@ +/* + * MIT License + * + * Copyright (c) 2023 Gabor L Ugray + * + * 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 +#include +#include "chirpy_demo_face.h" +#include "chirpy_tx.h" +#include "filesystem.h" + +typedef enum { + CDM_CHOOSE = 0, + CDM_CHIRPING, +} chirpy_demo_mode_t; + +typedef enum { + CDP_SCALE = 0, + CDP_INFO_SHORT, + CDP_INFO_LONG, + CDP_INFO_NANOSEC, +} chirpy_demo_program_t; + +typedef struct { + // Current mode + chirpy_demo_mode_t mode; + + // Selected program + chirpy_demo_program_t program; + + // Helps us handle 1/64 ticks during transmission; including countdown timer + chirpy_tick_state_t tick_state; + + // Used by chirpy encoder during transmission + chirpy_encoder_state_t encoder_state; + +} chirpy_demo_state_t; + +static uint8_t long_data_str[] = + "There once was a ship that put to sea\n" + "The name of the ship was the Billy of Tea\n" + "The winds blew up, her bow dipped down\n" + "O blow, my bully boys, blow (huh)\n" + "\n" + "Soon may the Wellerman come\n" + "To bring us sugar and tea and rum\n" + "One day, when the tonguin' is done\n" + "We'll take our leave and go\n"; + +static uint16_t short_data_len = 20; + +static uint8_t short_data[] = { + 0x27, + 0x00, + 0x0c, + 0x42, + 0xa3, + 0xd4, + 0x06, + 0x54, + 0x00, + 0x00, + 0x02, + 0x0c, + 0x6b, + 0x05, + 0x5a, + 0x09, + 0xd8, + 0x00, + 0xf5, + 0x00, +}; + +#define NANOSEC_INI_FILE_NAME "nanosec.ini" + +static uint8_t *nanosec_buffer = 0; +static uint16_t nanosec_buffer_size = 0; + +void chirpy_demo_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(chirpy_demo_state_t)); + memset(*context_ptr, 0, sizeof(chirpy_demo_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. +} + +void chirpy_demo_face_activate(movement_settings_t *settings, void *context) { + (void)settings; + chirpy_demo_state_t *state = (chirpy_demo_state_t *)context; + + memset(context, 0, sizeof(chirpy_demo_state_t)); + state->mode = CDM_CHOOSE; + state->program = CDP_SCALE; + + // Do we have nanosec data? Load it. + int32_t sz = filesystem_get_file_size(NANOSEC_INI_FILE_NAME); + if (sz > 0) { + // We will free this in resign. + // I don't like any kind of dynamic allocation in long-running embedded software... + // But there's no way around it here; I don't want to hard-wire (and squat) any fixed size structure + // Nanosec data may change in the future too + nanosec_buffer_size = sz + 2; + nanosec_buffer = malloc(nanosec_buffer_size); + // First two bytes of prefix, so Chirpy RX can recognize this data type + nanosec_buffer[0] = 0xc0; + nanosec_buffer[1] = 0x00; + // Read file + filesystem_read_file(NANOSEC_INI_FILE_NAME, (char*)&nanosec_buffer[2], sz); + } +} + +// To create / check test file in emulator: +// echo TestData > nanosec.ini +// cat nanosec.ini + +static void _cdf_update_lcd(chirpy_demo_state_t *state) { + watch_display_string("CH", 0); + if (state->program == CDP_SCALE) + watch_display_string(" SCALE", 4); + else if (state->program == CDP_INFO_SHORT) + watch_display_string("SHORT ", 4); + else if (state->program == CDP_INFO_LONG) + watch_display_string(" LOng ", 4); + else if (state->program == CDP_INFO_NANOSEC) + watch_display_string("nAnO ", 4); + else + watch_display_string("---- ", 4); +} + +static void _cdf_quit_chirping(chirpy_demo_state_t *state) { + state->mode = CDM_CHOOSE; + watch_set_buzzer_off(); + watch_clear_indicator(WATCH_INDICATOR_BELL); + movement_request_tick_frequency(1); +} + +static void _cdf_scale_tick(void *context) { + chirpy_demo_state_t *state = (chirpy_demo_state_t *)context; + chirpy_tick_state_t *tick_state = &state->tick_state; + + // Scale goes in 200Hz increments from 700 Hz to 12.3 kHz -> 58 steps + if (tick_state->seq_pos == 58) { + _cdf_quit_chirping(state); + return; + } + uint32_t freq = 700 + tick_state->seq_pos * 200; + uint32_t period = 1000000 / freq; + watch_set_buzzer_period(period); + watch_set_buzzer_on(); + ++tick_state->seq_pos; +} + +static void _cdf_data_tick(void *context) { + chirpy_demo_state_t *state = (chirpy_demo_state_t *)context; + + uint8_t tone = chirpy_get_next_tone(&state->encoder_state); + // Transmission over? + if (tone == 255) { + _cdf_quit_chirping(state); + return; + } + uint16_t period = chirpy_get_tone_period(tone); + watch_set_buzzer_period(period); + watch_set_buzzer_on(); +} + +static uint8_t *curr_data_ptr; +static uint16_t curr_data_ix; +static uint16_t curr_data_len; + +static uint8_t _cdf_get_next_byte(uint8_t *next_byte) { + if (curr_data_ix == curr_data_len) + return 0; + *next_byte = curr_data_ptr[curr_data_ix]; + ++curr_data_ix; + return 1; +} + +static void _cdf_countdown_tick(void *context) { + chirpy_demo_state_t *state = (chirpy_demo_state_t *)context; + chirpy_tick_state_t *tick_state = &state->tick_state; + + // Countdown over: start actual broadcast + if (tick_state->seq_pos == 8 * 3) { + tick_state->tick_compare = 3; + tick_state->tick_count = -1; + tick_state->seq_pos = 0; + // We'll be chirping out a scale + if (state->program == CDP_SCALE) { + tick_state->tick_fun = _cdf_scale_tick; + } + // We'll be chirping out data + else { + // Set up the encoder + chirpy_init_encoder(&state->encoder_state, _cdf_get_next_byte); + tick_state->tick_fun = _cdf_data_tick; + // Set up the data + curr_data_ix = 0; + if (state->program == CDP_INFO_SHORT) { + curr_data_ptr = short_data; + curr_data_len = short_data_len; + } else if (state->program == CDP_INFO_LONG) { + curr_data_ptr = long_data_str; + curr_data_len = strlen((const char *)long_data_str); + } else if (state->program == CDP_INFO_NANOSEC) { + curr_data_ptr = nanosec_buffer; + curr_data_len = nanosec_buffer_size; + } + } + return; + } + // Sound or turn off buzzer + if ((tick_state->seq_pos % 8) == 0) { + watch_set_buzzer_period(NotePeriods[BUZZER_NOTE_A5]); + watch_set_buzzer_on(); + } else if ((tick_state->seq_pos % 8) == 1) { + watch_set_buzzer_off(); + } + ++tick_state->seq_pos; +} + +static void _cdm_setup_chirp(chirpy_demo_state_t *state) { + // We want frequent callbacks from now on + movement_request_tick_frequency(64); + watch_set_indicator(WATCH_INDICATOR_BELL); + state->mode = CDM_CHIRPING; + // Set up tick state; start with countdown + state->tick_state.tick_count = -1; + state->tick_state.tick_compare = 8; + state->tick_state.seq_pos = 0; + state->tick_state.tick_fun = _cdf_countdown_tick; +} + +bool chirpy_demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + (void)settings; + chirpy_demo_state_t *state = (chirpy_demo_state_t *)context; + + switch (event.event_type) { + case EVENT_ACTIVATE: + _cdf_update_lcd(state); + break; + case EVENT_MODE_BUTTON_UP: + // Do not exit face while we're chirping + if (state->mode != CDM_CHIRPING) { + movement_move_to_next_face(); + } + break; + case EVENT_LIGHT_BUTTON_UP: + // We don't do light. + break; + case EVENT_ALARM_BUTTON_UP: + // If in choose mode: select next program + if (state->mode == CDM_CHOOSE) { + if (state->program == CDP_SCALE) + state->program = CDP_INFO_SHORT; + else if (state->program == CDP_INFO_SHORT) + state->program = CDP_INFO_LONG; + else if (state->program == CDP_INFO_LONG) { + if (nanosec_buffer_size > 0) + state->program = CDP_INFO_NANOSEC; + else + state->program = CDP_SCALE; + } else if (state->program == CDP_INFO_NANOSEC) + state->program = CDP_SCALE; + _cdf_update_lcd(state); + } + // If chirping: stoppit + else if (state->mode == CDM_CHIRPING) { + _cdf_quit_chirping(state); + } + break; + case EVENT_ALARM_LONG_PRESS: + // If in choose mode: start chirping + if (state->mode == CDM_CHOOSE) { + _cdm_setup_chirp(state); + } + break; + case EVENT_TICK: + if (state->mode == CDM_CHIRPING) { + ++state->tick_state.tick_count; + if (state->tick_state.tick_count == state->tick_state.tick_compare) { + state->tick_state.tick_count = 0; + state->tick_state.tick_fun(context); + } + } + break; + case EVENT_TIMEOUT: + // Do not time out while we're chirping + if (state->mode != CDM_CHIRPING) { + movement_move_to_face(0); + } + default: + break; + } + + // Return true if the watch can enter standby mode. False needed when chirping. + if (state->mode == CDM_CHIRPING) + return false; + else + return true; +} + +void chirpy_demo_face_resign(movement_settings_t *settings, void *context) { + (void)settings; + (void)context; + + if (nanosec_buffer != 0) { + free(nanosec_buffer); + nanosec_buffer = 0; + nanosec_buffer_size = 0; + } +} diff --git a/movement/watch_faces/demo/chirpy_demo_face.h b/movement/watch_faces/demo/chirpy_demo_face.h new file mode 100644 index 00000000..2d34107a --- /dev/null +++ b/movement/watch_faces/demo/chirpy_demo_face.h @@ -0,0 +1,70 @@ +/* + * MIT License + * + * Copyright (c) 2023 <#author_name#> + * + * 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 CHIRPY_DEMO_FACE_H_ +#define CHIRPY_DEMO_FACE_H_ + +#include "movement.h" + +/* + * CHIRPY DEMO FACE + * + * This face demonstrates the chirpy-tx library. It is intended to help you + * include chirpy-tx in your own watch faces that need to transmit data out + * of the watch. + * + * The face's first screen lets you select from a few built-in transmissions: + * + * SCALE cycles through frequencies in fixed increments. This is intended to + * collect and analyze audio samples from different watches. With this info + * it may be possible to improve chirpy-tx's parameters like the frequencies + * it uses to make the method more robust. + * + * SHORT is a small transmission that contains data taked from the activity_face. + * + * LONG is a longer transmission that contains the first two strophes of a + * famous sea shanty. + * + * Select the transmission you want with ALARM, the press LONG ALARM to chirp. + * + * To record and decode a chirpy transmission on your computer, you can use the web app here: + * https://jealousmarkup.xyz/off/chirpy/rx/ + * + */ + +void chirpy_demo_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void chirpy_demo_face_activate(movement_settings_t *settings, void *context); +bool chirpy_demo_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void chirpy_demo_face_resign(movement_settings_t *settings, void *context); + +#define chirpy_demo_face ((const watch_face_t){ \ + chirpy_demo_face_setup, \ + chirpy_demo_face_activate, \ + chirpy_demo_face_loop, \ + chirpy_demo_face_resign, \ + NULL, \ +}) + +#endif // CHIRPY_DEMO_FACE_H_ + diff --git a/movement/watch_faces/sensor/lightmeter_face.c b/movement/watch_faces/sensor/lightmeter_face.c new file mode 100644 index 00000000..861e28d8 --- /dev/null +++ b/movement/watch_faces/sensor/lightmeter_face.c @@ -0,0 +1,206 @@ +/* + * MIT License + * + * Copyright (c) 2022 CC + * + * 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. + */ + +/* Aperture-priority Light Meter Face + * + * Tested with the "Q3Q-SWAB-A1-00 Temperature + Test Points + OPT3001" flexboard. + * This flexboard could use a revision: + * + * - The thermistor components should be moved west a mm or flipped to the backside + * to avoid stressing the flexboard against the processor so much. + * - The 'no connect' pad falls off easily. + * + * Controls: + * + * - Trigger a measurement by long-pressing Alarm. + * Sensor integration is happening when the Signal indicator is on. + * + * - ISO setting can be cycled by long-pressing Light. + * During integration the current ISO setting will be displayed. + * + * - EV measurement in the top right: "LAP" indicates "half stop". + * So "LAP -1" means EV = -1.5. Likewise "LAP 13" means EV = +13.5 + * + * - Aperture in the bottom right: the last 3 main digits are the f-stop. + * Adjust this number in half-stop increments using Alarm = +1/2 and Light = -1/2. + * + * - Best shutter speed in the bottom left: the first 3 digits are the shutter speed. + * Some special chars are needed here: "-" = seconds, "h" = extra half second, "K" = thousands. + * "HI" or "LO" if there's no shutter in the dictionary within 0.5 stops of correct exposure. + * + * - Mode long-press changes the main digits to show raw sensor lux measurements. + * + */ + +#include +#include +#include +#include "lightmeter_face.h" +#include "watch_utility.h" +#include "watch_slcd.h" + +uint16_t lightmeter_mod(uint16_t m, uint16_t n) { return (m%n + n)%n; } + +void lightmeter_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(lightmeter_state_t)); + lightmeter_state_t *state = (lightmeter_state_t*) *context_ptr; + state->waiting_for_conversion = 0; + state->lux = 0.0; + state->mode = 0; + state->iso = LIGHTMETER_ISO_100; + state->ap = LIGHTMETER_AP_4P0; + } +} + +void lightmeter_face_activate(movement_settings_t *settings, void *context) { + (void) settings; + lightmeter_state_t *state = (lightmeter_state_t*) context; + state->waiting_for_conversion = 0; + lightmeter_show_ev(state); // Print most current reading + watch_enable_i2c(); + return; +} + +void lightmeter_show_ev(lightmeter_state_t *state) { + + float ev = max(min( + log2(state->lux) + + lightmeter_isos[state->iso].ev + + LIGHTMETER_CALIBRATION, + 99), -9); + int evt = round(2*ev); // Truncated EV + + // Print EV + char strbuff[7]; + watch_clear_all_indicators(); + watch_display_string("EV ", 0); + + sprintf(strbuff, "%2i", (uint16_t) abs(evt/2)); // Print whole part of EV + watch_display_string(strbuff, 2); + if(evt%2) watch_set_indicator(WATCH_INDICATOR_LAP); // Indicate half stop + if(ev<0) watch_set_pixel(1,9); // Indicate negative EV + + // Handle lux mode + if(state->mode == 1) { + sprintf(strbuff, "%6.0f", min(state->lux, 999999.0)); + watch_display_string(strbuff, 4); + return; + } + + // Find and print best shutter speed + uint16_t bestsh = 0; + float besterr = 1.0/0.0; + float errbuf = 1.0/0.0; + float comp_ev = ev + lightmeter_aps[state->ap].ev; + for(uint16_t ind = 2; ind < LIGHTMETER_N_SHS; ind++) { + errbuf = comp_ev + lightmeter_shs[ind].ev; + if( fabs(errbuf) < fabs(besterr)) { + besterr = errbuf; + bestsh = ind; + } + } + if(besterr >= 0.5) watch_display_string(lightmeter_shs[LIGHTMETER_SH_HIGH].str, 4); + else if(besterr <= -0.5) watch_display_string(lightmeter_shs[LIGHTMETER_SH_LOW].str, 4); + else watch_display_string(lightmeter_shs[bestsh].str, 4); + + // Print aperture + watch_display_string(lightmeter_aps[state->ap].str, 7); + return; +} + +bool lightmeter_face_loop(movement_event_t event, movement_settings_t *settings, void *context) { + (void) settings; + lightmeter_state_t *state = (lightmeter_state_t*) context; + + opt3001_Config_t c; + switch (event.event_type) { + case EVENT_TICK: + if(state->waiting_for_conversion) { // Check if measurement is ready... + c = opt3001_readConfig(lightmeter_addr); + if(c.ConversionReady) { + state->waiting_for_conversion = 0; + opt3001_t result = opt3001_readResult(lightmeter_addr); + state->lux = result.lux; + lightmeter_show_ev(state); + } + } + break; + + case EVENT_ALARM_BUTTON_UP: // Increment aperture + state->ap = lightmeter_mod(state->ap+1, LIGHTMETER_N_APS); + + lightmeter_show_ev(state); + break; + + case EVENT_LIGHT_BUTTON_UP: // Decrement aperture + if(state->ap == 0) state->ap = LIGHTMETER_N_APS-1; + else state->ap = lightmeter_mod(state->ap-1, LIGHTMETER_N_APS); + + lightmeter_show_ev(state); + break; + + case EVENT_LIGHT_LONG_PRESS: // Cycle ISO + state->iso = lightmeter_mod(state->iso+1, LIGHTMETER_N_ISOS); + + watch_clear_all_indicators(); + watch_display_string("EV ", 0); + watch_display_string(lightmeter_isos[state->iso].str, 4); + break; + + case EVENT_ALARM_LONG_PRESS: // Take measurement + opt3001_writeConfig(lightmeter_addr, lightmeter_takeNewReading); + state->waiting_for_conversion = 1; + + watch_clear_all_indicators(); + watch_display_string("EV ", 0); + watch_display_string(lightmeter_isos[state->iso].str, 4); + watch_set_indicator(WATCH_INDICATOR_SIGNAL); + break; + + case EVENT_MODE_LONG_PRESS: // Toggle mode + state->mode = !state->mode; + lightmeter_show_ev(state); + break; + + case EVENT_TIMEOUT: + movement_move_to_face(0); + break; + + default: + movement_default_loop_handler(event, settings); + break; + } + return true; +} + +void lightmeter_face_resign(movement_settings_t *settings, void *context) { + (void) settings; + (void) context; + opt3001_writeConfig(lightmeter_addr, lightmeter_off); + watch_disable_i2c(); + return; +} diff --git a/movement/watch_faces/sensor/lightmeter_face.h b/movement/watch_faces/sensor/lightmeter_face.h new file mode 100644 index 00000000..2f8813f4 --- /dev/null +++ b/movement/watch_faces/sensor/lightmeter_face.h @@ -0,0 +1,160 @@ +/* + * MIT License + * + * Copyright (c) 2023 CC + * + * 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 LIGHTMETER_FACE_H_ +#define LIGHTMETER_FACE_H_ + +#include "movement.h" +#include "opt3001.h" + +#define LIGHTMETER_CALIBRATION 2.58 +typedef struct { + char * str; + float ev; +} lightmeter_ev_t; + +static const lightmeter_ev_t lightmeter_isos[] = { + {" i 25", -2}, + {" i 50", -1}, + {" i 100", 0}, + {" i 160", 0.68}, + {" i 200", 1}, + {" i 400", 2}, + {" i 800", 3}, + {" i1600", 4}}; +typedef enum { + LIGHTMETER_ISO_25, LIGHTMETER_ISO_50, LIGHTMETER_ISO_100, LIGHTMETER_ISO_160, LIGHTMETER_ISO_200, LIGHTMETER_ISO_400, LIGHTMETER_ISO_800, LIGHTMETER_ISO_1600, + LIGHTMETER_N_ISOS +} lightmeter_iso_t; + +static const lightmeter_ev_t lightmeter_aps[] = { + {"1.4", 0}, + {"1.8", -0.5}, + {"2.0", -1}, + {"2.4", -1.5}, + {"2.8", -2}, + {"3.3", -2.5}, + {"4.0", -3}, + {"4.8", -3.5}, + {"5.6", -4}, + {"6.7", -4.5}, + {"8.0", -5}, + {"9.5", -5.5}, + {"11.", -6}, + {"13.", -6.5}, + {"16.", -7}, + {"19.", -7.5}, + {"22.", -8}}; +typedef enum { + LIGHTMETER_AP_1P4, LIGHTMETER_AP_1P8, LIGHTMETER_AP_2P0, LIGHTMETER_AP_2P4, LIGHTMETER_AP_2P8, LIGHTMETER_AP_3P3, LIGHTMETER_AP_4P0, LIGHTMETER_AP_4P8, LIGHTMETER_AP_5P6, LIGHTMETER_AP_6P7, LIGHTMETER_AP_8P0, LIGHTMETER_AP_9P5, + LIGHTMETER_AP_11, LIGHTMETER_AP_13, LIGHTMETER_AP_16, LIGHTMETER_AP_19, LIGHTMETER_AP_22, + LIGHTMETER_N_APS +} lightmeter_ap_t; + +static const lightmeter_ev_t lightmeter_shs[] = { + {"LO-", 99}, + {"HI ", -99}, + {"30-", 5.0}, + {"20-", 4.5}, + {"15-", 4.0}, + {"11-", 3.5}, + {"8- ", 3.0}, + {"6- ", 2.5}, + {"4- ", 2.0}, + {"3- ", 1.5}, + {"2- ", 1.0}, + {"1h-", 0.5}, + {"1 ", 0.0}, + {"1h ", -0.5}, + {"2 ", -1.0}, + {"3 ", -1.5}, + {"4 ", -2.0}, + {"6 ", -2.5}, + {"8 ", -3.0}, + {"12 ", -3.5}, + {"15 ", -4.0}, + {"20 ", -4.5}, + {"30 ", -5.0}, + {"45 ", -5.5}, + {"60 ", -6.0}, + {"90 ", -6.5}, + {"125", -7.0}, + {"180", -7.5}, + {"250", -8.0}, + {"350", -8.5}, + {"500", -9.0}, + {"750", -9.5}, + {"1K ", -10.0}, + {"1K5", -10.5}, + {"2K ", -11.0}, + {"3K ", -11.5}, + {"4K ", -12.0}, + {"6K ", -12.5}, + {"8K ", -13.0}}; +typedef enum { + LIGHTMETER_SH_LOW, LIGHTMETER_SH_HIGH, + LIGHTMETER_SH_30S, LIGHTMETER_SH_20S, LIGHTMETER_SH_15S, LIGHTMETER_SH_11S, LIGHTMETER_SH_8S, LIGHTMETER_SH_6S, LIGHTMETER_SH_3S, LIGHTMETER_SH_4S, LIGHTMETER_SH_2S, LIGHTMETER_SH_1HS, + LIGHTMETER_SH_1, LIGHTMETER_SH_1H, LIGHTMETER_SH_2, LIGHTMETER_SH_3, LIGHTMETER_SH_4, LIGHTMETER_SH_6, LIGHTMETER_SH_8, LIGHTMETER_SH_12, LIGHTMETER_SH_15, LIGHTMETER_SH_20, LIGHTMETER_SH_30, LIGHTMETER_SH_45, LIGHTMETER_SH_60, LIGHTMETER_SH_90, LIGHTMETER_SH_125, LIGHTMETER_SH_180, LIGHTMETER_SH_250, LIGHTMETER_SH_350, LIGHTMETER_SH_500, LIGHTMETER_SH_750, + LIGHTMETER_SH_1K, LIGHTMETER_SH_1K5, LIGHTMETER_SH_2K, LIGHTMETER_SH_3K, LIGHTMETER_SH_4K, LIGHTMETER_SH_6K, LIGHTMETER_SH_8K, + LIGHTMETER_N_SHS +} lightmeter_sh_t; + +typedef struct { + lightmeter_iso_t iso; + lightmeter_ap_t ap; + bool waiting_for_conversion; + float lux; + int mode; +} lightmeter_state_t; + +static const opt3001_Config_t lightmeter_takeNewReading = { + .RangeNumber = 0B1100, + .ConversionTime = 0B1, + .Latch = 0B1, + .ModeOfConversionOperation = 0B01 +}; + +static const opt3001_Config_t lightmeter_off = { + .ModeOfConversionOperation = 0B00 +}; + +uint16_t lightmeter_mod(uint16_t m, uint16_t n); + +void lightmeter_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void lightmeter_face_activate(movement_settings_t *settings, void *context); +void lightmeter_show_ev(lightmeter_state_t *state); +bool lightmeter_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void lightmeter_face_resign(movement_settings_t *settings, void *context); + +static const uint8_t lightmeter_addr = 0x44; + +#define lightmeter_face ((const watch_face_t){ \ + lightmeter_face_setup, \ + lightmeter_face_activate, \ + lightmeter_face_loop, \ + lightmeter_face_resign, \ + NULL, \ +}) + +#endif // LIGHTMETER_FACE_H_ diff --git a/movement/watch_faces/settings/place_face.h b/movement/watch_faces/settings/place_face.h new file mode 100644 index 00000000..a98c2642 --- /dev/null +++ b/movement/watch_faces/settings/place_face.h @@ -0,0 +1,231 @@ +/* + * MIT License + * + * Copyright (c) 2023 Tobias Raayoni Last / @randogoth + * + * 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 place_FACE_H_ +#define place_FACE_H_ + +#include "movement.h" + +/* + * PLACE FACE + * ========== + * + * Based on and expanded from the Sunrise/Sunset face. Outsourced the location setting functionality to + * its own face. Also serves as a converter between different coordinate notation formats. + * + * With the LIGHT button each place coordinate can be shown and edited in 4 different display modes: + * + * 1) Decimal Latitude and Longitude (WGS84) up to 5 decimal points + * 2) Latitude and Longitude (WGS84) in traditional DD°MM'SS" notation + * 3) Ten digit Open Location Code (aka. PlusCode) format + * 4) Ten digit Geohash format + * + * Using the ALARM button the user can flip through 2 pages of coordinate info to see the first and + * second sets of digits. + * + * (please also refer to the notes on precision below) + * + * Editing Mode + * ============ + * + * A LONG PRESS of the LIGHT button toggles editing mode for each of the selected notations. + * + * In this mode LIGHT moves the cursor and ALARM changes the letter cycling through the available + * alphabet or numbers. + * + * When OLC or Geohash display are edited, Digit Info mode is activated. It serves as a workaround + * for the limitation of how ambiguously alphanumeric characters are displayed on the main seven segment + * digits of the watch face ( S or 5, I or 1, U or W?). + * + * The selected letter is also shown in the much easier to read alphanumeric 8 segment weekday digit above. + * In addition the '24H' indicator is active when the selected digit represents a number and the 'PM' + * indicator for a letter. + * + * A LONG PRESS of LIGHT saves the changes. + * + * Coordinates are read or stored to both the traditional internal location register and a file on + * the LFS file system ("place.loc"). By default the Watch Face loads the coordinates from file + * when activated. If no file is present, the coordinates are loaded from the register. + * (please also see the notes on precision below) + * + * Auxiliary Mode: Digit Info + * ========================== + * + * A LONG PRESS of the ALARM button toggles Digit Info mode when OLC or Geohash display is active. + * (LAP indicator is on) It is a means of being able to see the detailed Digit Info as described above + * but without the risk of accidentally editing any of digits. + * + * Both ALARM and LIGHT buttons can be used to flip through the letters. + * + * Notes on Coordinate Precision + * ============================= + * + * The common WGS84 Latitude and Longitude degrees naturally do not represent meters in distance + * on the ground. 1° Longitude on the equatorial line equals a width of 111.32 kilometers, but + * at 40° latitude further North or South it is approximately 85 kilometers wide. The closer to + * the poles the narrower (and more precise) the latitude degrees get. + * + * The Sensor Watch's traditional 16bit location register only stores latitudes and longitudes + * with two decimal points. That equals a longitudal precision of 36 arc seconds, or ~1111 meters + * at the equator - precise enough for astronomical calculations, but not if you want to store the + * location of let's say a building. + * + * Hence we propose the file that serves the same purpose, but with a precision of + * five decimal digits. That equals 0.04 arc seconds or 1.11 meters at the equator. + * + * Please also note that the different notations of this watch face also have varying magnitudes + * of precision: + * + * | Format | Notation | Precision at Equator | Precision at 67° N/S | + * | ------------------ | ---------------------- | -------------------- | -------------------- | + * | 2d. Decimal LatLon | 29.98, 31.13 | 1111.320 m | 435.125 m | + * | 5d. Decimal LatLon | 29.97916, 31.13417 | 1.111 m | 0.435 m | + * | DMS LatLon | N 29°58′45″, E 31°8′3″ | 30.833 m | 12.083 m | + * | Open Location Code | 7GXHX4HM+MM | 13.875 m | 13.875 m | + * | Geohash | stq4s3x1qu | 1.189 m | 0.596 m | + * + * Since all notations are internally converted into degrees with 5 decimal points, expect some + * rounding errors when editing or loading the coordinates in other notation formats. + * + */ + +static const char olc_alphabet[20] = "23456789CFGHJMPQRUWX"; +static const char geohash_alphabet[32] = "0123456789bCdEfGhjkmnpqrstuVwxyz"; + +typedef struct { + uint8_t sign: 1; // 0-1 + uint8_t hundreds: 1; // 0-1 + uint8_t tens: 4; // 0-9 + uint8_t ones: 4; // 0-9 + uint8_t d01: 4; // 0-9 + uint8_t d02: 4; // 0-9 + uint8_t d03: 4; // 0-9 + uint8_t d04: 4; // 0-9 + uint8_t d05: 4; // 0-9 +} place_format_decimal_latlon_t; + +typedef struct { + uint8_t sign: 1; // 0-1 + uint8_t hundreds: 1; // 0-1 + uint8_t tens: 4; // 0-9 + uint8_t ones: 4; // 0-9 + uint8_t mins_tens: 3; // 0-5 + uint8_t mins_ones: 4; // 0-9 + uint8_t secs_tens: 3; // 0-5 + uint8_t secs_ones: 4; // 0-9 +} place_format_dms_latlon_t; + +typedef struct { + uint8_t lat1: 5; // 2-X + uint8_t lon1: 5; // 2-X + uint8_t lat2: 5; // 2-X + uint8_t lon2: 5; // 2-X + uint8_t lat3: 5; // 2-X + uint8_t lon3: 5; // 2-X + uint8_t lat4: 5; // 2-X + uint8_t lon4: 5; // 2-X + uint8_t lat5: 5; // 2-X + uint8_t lon5: 5; // 2-X +} place_format_olc_t; + +typedef struct { + int32_t latitude : 25; + int32_t longitude : 26; +} coordinate_t; + +typedef struct { + place_format_decimal_latlon_t latitude; + place_format_decimal_latlon_t longitude; +} place_coordinate_t; + +typedef struct { + uint8_t d01: 6; // 0-z + uint8_t d02: 6; // 0-z + uint8_t d03: 6; // 0-z + uint8_t d04: 6; // 0-z + uint8_t d05: 6; // 0-z + uint8_t d06: 6; // 0-z + uint8_t d07: 6; // 0-z + uint8_t d08: 6; // 0-z + uint8_t d09: 6; // 0-z + uint8_t d10: 6; // 0-z +} place_format_geohash_t; + +typedef struct { + double max; + double min; +} place_format_geohash_interval; + +typedef struct { + uint8_t min_digit : 1; + uint8_t max_digit : 3; +} place_mode_schema_page_t; + +typedef struct { + uint8_t max_page : 3; + place_mode_schema_page_t page[4]; +} place_mode_schema_mode_t; + +enum place_modes_e { + MODE_DECIMAL = 0, + MODE_DMS, + MODE_OLC, + MODE_GEOHASH +}; + +typedef struct { + enum place_modes_e mode; + uint8_t page : 3; + int8_t active_digit: 4; + bool edit; + bool digit_info; + place_format_decimal_latlon_t working_latitude; + place_format_decimal_latlon_t working_longitude; + place_format_dms_latlon_t working_dms_latitude; + place_format_dms_latlon_t working_dms_longitude; + place_format_olc_t working_pluscode; + place_format_geohash_t working_geohash; + place_mode_schema_mode_t modes[4]; +} place_state_t; + +// PUBLIC WATCH FACE FUNCTIONS //////////////////////////////////////////////// + +void place_face_setup(movement_settings_t *settings, uint8_t watch_face_index, void ** context_ptr); +void place_face_activate(movement_settings_t *settings, void *context); +bool place_face_loop(movement_event_t event, movement_settings_t *settings, void *context); +void place_face_resign(movement_settings_t *settings, void *context); + +void place_latlon_to_olc(char *pluscode, double latitude, double longitude); +void place_latlon_to_geohash(char *geohash, double latitude, double longitude); + +#define place_face ((const watch_face_t){ \ + place_face_setup, \ + place_face_activate, \ + place_face_loop, \ + place_face_resign, \ + NULL, \ +}) + +#endif // place_FACE_H_ + diff --git a/watch-library/shared/driver/opt3001.c b/watch-library/shared/driver/opt3001.c new file mode 100644 index 00000000..d2f4e8ce --- /dev/null +++ b/watch-library/shared/driver/opt3001.c @@ -0,0 +1,91 @@ +/* + +Arduino library for Texas Instruments opt3001_t Digital Ambient Light Sensor +Written by AA for ClosedCube +Adapted to Sensor-Watch interface by CC +--- + +The MIT License (MIT) + +Copyright (c) 2015 ClosedCube Limited + +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 + +#include "opt3001.h" +#include "watch_utility.h" + +uint16_t opt3001_readManufacturerID(uint8_t devaddr) { + uint8_t buf[2]; + buf[0] = (uint8_t) OPT3001_MANUFACTURER_ID; + watch_i2c_send(devaddr, buf, 1); + watch_i2c_receive(devaddr, buf, 2); + return ((uint16_t) buf[0] << 8) | ((uint16_t) buf[1]); +} + +uint16_t opt3001_readDeviceID(uint8_t devaddr) { + uint8_t buf[2]; + buf[0] = (uint8_t) OPT3001_DEVICE_ID; + watch_i2c_send(devaddr, buf, 1); + watch_i2c_receive(devaddr, buf, 2); + return ((uint16_t) buf[0] << 8) | ((uint16_t) buf[1]); +} + +opt3001_Config_t opt3001_readConfig(uint8_t devaddr) { + opt3001_Config_t config; + uint8_t buf[2]; + buf[0] = (uint8_t) OPT3001_CONFIG; + watch_i2c_send(devaddr, buf, 1); + watch_i2c_receive(devaddr, buf, 2); + config.rawData = ((uint16_t) buf[0] << 8) | ((uint16_t) buf[1]); + return config; +} + +void opt3001_writeConfig(uint8_t devaddr, opt3001_Config_t config) { + uint8_t buf[3] = {OPT3001_CONFIG, (uint8_t)(config.rawData >> 8), (uint8_t)(config.rawData & 0x00FF)}; + watch_i2c_send(devaddr, buf, 3); + return; +} + +opt3001_t opt3001_readResult(uint8_t devaddr) { + return opt3001_readRegister(devaddr, OPT3001_RESULT); +} + +opt3001_t opt3001_readHighLimit(uint8_t devaddr) { + return opt3001_readRegister(devaddr, OPT3001_HIGH_LIMIT); +} + +opt3001_t opt3001_readLowLimit(uint8_t devaddr) { + return opt3001_readRegister(devaddr, OPT3001_LOW_LIMIT); +} + +opt3001_t opt3001_readRegister(uint8_t devaddr, opt3001_Command_t command) { + opt3001_t result; + opt3001_ER_t er; + uint8_t buf[2]; + buf[0] = (uint8_t) command; + watch_i2c_send(devaddr, buf, 1); + watch_i2c_receive(devaddr, buf, 2); + er.rawData = ((uint16_t) buf[0] << 8) | ((uint16_t) buf[1]); + result.raw = er; + result.lux = 0.01*pow(2, er.Exponent)*er.Result; + return result; +} diff --git a/watch-library/shared/driver/opt3001.h b/watch-library/shared/driver/opt3001.h new file mode 100644 index 00000000..1ed8eea9 --- /dev/null +++ b/watch-library/shared/driver/opt3001.h @@ -0,0 +1,87 @@ +/* + +Arduino library for Texas Instruments OPT3001 Digital Ambient Light Sensor +Adapted to Sensor-Watch interface by CC +--- + +The MIT License (MIT) + +Copyright (c) 2015 ClosedCube Limited + +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 OPT3001_ +#define OPT3001_ +#include + +typedef enum { + OPT3001_RESULT = 0x00, + OPT3001_CONFIG = 0x01, + OPT3001_LOW_LIMIT = 0x02, + OPT3001_HIGH_LIMIT = 0x03, + + OPT3001_MANUFACTURER_ID = 0x7E, + OPT3001_DEVICE_ID = 0x7F, +} opt3001_Command_t; + +typedef union { + uint16_t rawData; + struct { + uint16_t Result : 12; + uint8_t Exponent : 4; + }; +} opt3001_ER_t; + + +typedef union { + struct { + uint8_t FaultCount : 2; + uint8_t MaskExponent : 1; + uint8_t Polarity : 1; + uint8_t Latch : 1; + uint8_t FlagLow : 1; + uint8_t FlagHigh : 1; + uint8_t ConversionReady : 1; + uint8_t OverflowFlag : 1; + uint8_t ModeOfConversionOperation : 2; + uint8_t ConversionTime : 1; + uint8_t RangeNumber : 4; + }; + uint16_t rawData; +} opt3001_Config_t; + +typedef struct { + float lux; + opt3001_ER_t raw; +} opt3001_t; + +uint16_t opt3001_readManufacturerID(uint8_t devaddr); +uint16_t opt3001_readDeviceID(uint8_t devaddr); + +opt3001_t opt3001_readResult(uint8_t devaddr); +opt3001_t opt3001_readHighLimit(uint8_t devaddr); +opt3001_t opt3001_readLowLimit(uint8_t devaddr); + +opt3001_Config_t opt3001_readConfig(uint8_t devaddr); +void opt3001_writeConfig(uint8_t devaddr, opt3001_Config_t config); +opt3001_t opt3001_readRegister(uint8_t devaddr, opt3001_Command_t command); + +#endif // OPT3001_ diff --git a/watch-library/simulator/shell.html b/watch-library/simulator/shell.html index 8d371cd6..335b9534 100644 --- a/watch-library/simulator/shell.html +++ b/watch-library/simulator/shell.html @@ -842,6 +842,7 @@ +