aboutsummaryrefslogtreecommitdiffhomepage
path: root/source/Core/Drivers
diff options
context:
space:
mode:
Diffstat (limited to 'source/Core/Drivers')
-rw-r--r--source/Core/Drivers/FUSB302/fusb302b.cpp52
-rw-r--r--source/Core/Drivers/FUSB302/fusb302b.h4
-rw-r--r--source/Core/Drivers/FUSB302/fusb_user.h30
-rw-r--r--source/Core/Drivers/FUSB302/fusbpd.cpp2
-rw-r--r--source/Core/Drivers/FUSB302/fusbpd.h3
-rw-r--r--source/Core/Drivers/FUSB302/int_n.cpp78
-rw-r--r--source/Core/Drivers/FUSB302/policy_engine.cpp79
-rw-r--r--source/Core/Drivers/FUSB302/policy_engine.h44
-rw-r--r--source/Core/Drivers/FUSB302/policy_engine_user.cpp24
-rw-r--r--source/Core/Drivers/FUSB302/protocol_tx.cpp276
-rw-r--r--source/Core/Drivers/FUSB302/protocol_tx.h85
-rw-r--r--source/Core/Drivers/I2CBB.cpp18
-rw-r--r--source/Core/Drivers/I2CBB.hpp16
-rw-r--r--source/Core/Drivers/MSA301.cpp2
-rw-r--r--source/Core/Drivers/OLED.cpp10
-rw-r--r--source/Core/Drivers/OLED.hpp13
-rw-r--r--source/Core/Drivers/TipThermoModel.cpp158
-rw-r--r--source/Core/Drivers/Utils.cpp23
-rw-r--r--source/Core/Drivers/Utils.h17
-rw-r--r--source/Core/Drivers/WS2812.h124
20 files changed, 439 insertions, 619 deletions
diff --git a/source/Core/Drivers/FUSB302/fusb302b.cpp b/source/Core/Drivers/FUSB302/fusb302b.cpp
index 63ef5baf..83bab9c7 100644
--- a/source/Core/Drivers/FUSB302/fusb302b.cpp
+++ b/source/Core/Drivers/FUSB302/fusb302b.cpp
@@ -21,7 +21,9 @@
#include "fusb_user.h"
#include "int_n.h"
#include <pd.h>
-void fusb_send_message(const union pd_msg *msg) {
+uint8_t fusb_read_byte(uint8_t addr);
+bool fusb_write_byte(uint8_t addr, uint8_t byte);
+void fusb_send_message(const union pd_msg *msg) {
/* Token sequences for the FUSB302B */
static uint8_t sop_seq[5] = {FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP1, FUSB_FIFO_TX_SOP2, FUSB_FIFO_TX_PACKSYM};
@@ -41,6 +43,8 @@ void fusb_send_message(const union pd_msg *msg) {
fusb_write_buf(FUSB_FIFOS, 4, eop_seq);
}
+bool fusb_rx_pending() { return (fusb_read_byte(FUSB_STATUS1) & FUSB_STATUS1_RX_EMPTY) != FUSB_STATUS1_RX_EMPTY; }
+
uint8_t fusb_read_message(union pd_msg *msg) {
static uint8_t garbage[4];
@@ -48,7 +52,11 @@ uint8_t fusb_read_message(union pd_msg *msg) {
// Read the header. If its not a SOP we dont actually want it at all
// But on some revisions of the fusb if you dont both pick them up and read them out of the fifo, it gets stuck
- fusb_read_byte(FUSB_FIFOS);
+ if ((fusb_read_byte(FUSB_FIFOS) & FUSB_FIFO_RX_TOKEN_BITS) != FUSB_FIFO_RX_SOP) {
+ return 1;
+ }
+
+ // fusb_read_byte(FUSB_FIFOS);
/* Read the message header into msg */
fusb_read_buf(FUSB_FIFOS, 2, msg->bytes);
/* Get the number of data objects */
@@ -111,11 +119,11 @@ bool fusb_setup() {
/* Select the correct CC line for BMC signaling; also enable AUTO_CRC */
if (cc1 > cc2) {
- fusb_write_byte(FUSB_SWITCHES1, 0x25);
- fusb_write_byte(FUSB_SWITCHES0, 0x07);
+ fusb_write_byte(FUSB_SWITCHES1, 0x25); // TX_CC1|AUTO_CRC|SPECREV0
+ fusb_write_byte(FUSB_SWITCHES0, 0x07); // PWDN1|PWDN2|MEAS_CC1
} else {
- fusb_write_byte(FUSB_SWITCHES1, 0x26);
- fusb_write_byte(FUSB_SWITCHES0, 0x0B);
+ fusb_write_byte(FUSB_SWITCHES1, 0x26); // TX_CC2|AUTO_CRC|SPECREV0
+ fusb_write_byte(FUSB_SWITCHES0, 0x0B); // PWDN1|PWDN2|MEAS_CC2
}
fusb_reset();
@@ -123,10 +131,10 @@ bool fusb_setup() {
return true;
}
-void fusb_get_status(union fusb_status *status) {
+bool fusb_get_status(union fusb_status *status) {
/* Read the interrupt and status flags into status */
- fusb_read_buf(FUSB_STATUS0A, 7, status->bytes);
+ return fusb_read_buf(FUSB_STATUS0A, 7, status->bytes);
}
enum fusb_typec_current fusb_get_typec_current() {
@@ -144,7 +152,7 @@ void fusb_reset() {
/* Flush the RX buffer */
fusb_write_byte(FUSB_CONTROL1, FUSB_CONTROL1_RX_FLUSH);
/* Reset the PD logic */
- // fusb_write_byte( FUSB_RESET, FUSB_RESET_PD_RESET);
+ fusb_write_byte(FUSB_RESET, FUSB_RESET_PD_RESET);
}
bool fusb_read_id() {
@@ -154,4 +162,28 @@ bool fusb_read_id() {
if (version == 0 || version == 0xFF)
return false;
return true;
-} \ No newline at end of file
+}
+/*
+ * Read a single byte from the FUSB302B
+ *
+ * cfg: The FUSB302B to communicate with
+ * addr: The memory address from which to read
+ *
+ * Returns the value read from addr.
+ */
+uint8_t fusb_read_byte(uint8_t addr) {
+ uint8_t data[1];
+ if (!fusb_read_buf(addr, 1, (uint8_t *)data)) {
+ return 0;
+ }
+ return data[0];
+}
+
+/*
+ * Write a single byte to the FUSB302B
+ *
+ * cfg: The FUSB302B to communicate with
+ * addr: The memory address to which we will write
+ * byte: The value to write
+ */
+bool fusb_write_byte(uint8_t addr, uint8_t byte) { return fusb_write_buf(addr, 1, (uint8_t *)&byte); }
diff --git a/source/Core/Drivers/FUSB302/fusb302b.h b/source/Core/Drivers/FUSB302/fusb302b.h
index 43910a4d..72736250 100644
--- a/source/Core/Drivers/FUSB302/fusb302b.h
+++ b/source/Core/Drivers/FUSB302/fusb302b.h
@@ -269,7 +269,7 @@ union fusb_status {
* Send a USB Power Delivery message to the FUSB302B
*/
void fusb_send_message(const union pd_msg *msg);
-
+bool fusb_rx_pending();
/*
* Read a USB Power Delivery message from the FUSB302B
*/
@@ -283,7 +283,7 @@ void fusb_send_hardrst();
/*
* Read the FUSB302B status and interrupt flags into *status
*/
-void fusb_get_status(union fusb_status *status);
+bool fusb_get_status(union fusb_status *status);
/*
* Read the FUSB302B BC_LVL as an enum fusb_typec_current
diff --git a/source/Core/Drivers/FUSB302/fusb_user.h b/source/Core/Drivers/FUSB302/fusb_user.h
index 9a81c611..55a27ebf 100644
--- a/source/Core/Drivers/FUSB302/fusb_user.h
+++ b/source/Core/Drivers/FUSB302/fusb_user.h
@@ -19,11 +19,29 @@
#define PDB_FUSB_USER_H
#include <stdint.h>
-uint8_t fusb_read_byte(uint8_t addr);
-bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf);
-bool fusb_write_byte(uint8_t addr, uint8_t byte);
-bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf);
-uint8_t fusb302_detect();
-void setupFUSBIRQ();
+/*
+ * Read multiple bytes from the FUSB302B
+ *
+ * cfg: The FUSB302B to communicate with
+ * addr: The memory address from which to read
+ * size: The number of bytes to read
+ * buf: The buffer into which data will be read
+ */
+bool fusb_read_buf(uint8_t addr, uint8_t size, uint8_t *buf);
+/*
+ * Write multiple bytes to the FUSB302B
+ *
+ * cfg: The FUSB302B to communicate with
+ * addr: The memory address to which we will write
+ * size: The number of bytes to write
+ * buf: The buffer to write
+ */
+bool fusb_write_buf(uint8_t addr, uint8_t size, const uint8_t *buf);
+// Used to poll for the device existing on the I2C bus. This should return non-zero if the device is responding on the bus
+bool fusb302_detect();
+// Once this is called IRQ's should be enabled and routed to the IRQ handler thread
+void setupFUSBIRQ();
+// This should return true if the IRQ line for the FUSB302 is still held low
+bool getFUS302IRQLow();
#endif /* PDB_FUSB302B_H */
diff --git a/source/Core/Drivers/FUSB302/fusbpd.cpp b/source/Core/Drivers/FUSB302/fusbpd.cpp
index 54f026c0..f8a74155 100644
--- a/source/Core/Drivers/FUSB302/fusbpd.cpp
+++ b/source/Core/Drivers/FUSB302/fusbpd.cpp
@@ -12,7 +12,6 @@
#include "int_n.h"
#include "policy_engine.h"
-#include "protocol_tx.h"
#include <fusbpd.h>
#include <pd.h>
@@ -20,7 +19,6 @@ void fusb302_start_processing() {
/* Initialize the FUSB302B */
if (fusb_setup()) {
PolicyEngine::init();
- ProtocolTransmit::init();
InterruptHandler::init();
}
}
diff --git a/source/Core/Drivers/FUSB302/fusbpd.h b/source/Core/Drivers/FUSB302/fusbpd.h
index 353bb338..1f3a80fb 100644
--- a/source/Core/Drivers/FUSB302/fusbpd.h
+++ b/source/Core/Drivers/FUSB302/fusbpd.h
@@ -11,8 +11,5 @@
extern struct pdb_config pdb_config_data;
#include <stdint.h>
-// returns 1 if the FUSB302 is on the I2C bus
-uint8_t fusb302_detect();
-
void fusb302_start_processing();
#endif /* DRIVERS_FUSB302_FUSBPD_H_ */
diff --git a/source/Core/Drivers/FUSB302/int_n.cpp b/source/Core/Drivers/FUSB302/int_n.cpp
index 1ca67894..7c00b651 100644
--- a/source/Core/Drivers/FUSB302/int_n.cpp
+++ b/source/Core/Drivers/FUSB302/int_n.cpp
@@ -16,13 +16,11 @@
*/
#include "int_n.h"
-#include "BSP.h"
-#include "BSP_PD.h"
+#include "Defines.h"
#include "fusb302b.h"
+#include "fusb_user.h"
#include "fusbpd.h"
#include "policy_engine.h"
-
-#include "protocol_tx.h"
#include "task.h"
#include <pd.h>
#include <string.h>
@@ -37,23 +35,28 @@ void InterruptHandler::init() {
osThreadStaticDef(intTask, Thread, PDB_PRIO_PRL_INT_N, 0, TaskStackSize, TaskBuffer, &TaskControlBlock);
TaskHandle = osThreadCreate(osThread(intTask), NULL);
}
-
-void InterruptHandler::readPendingMessage() {
- /* Get a buffer to read the message into. Guaranteed to not fail
- * because we have a big enough pool and are careful. */
+volatile uint32_t msgCounter = 0;
+volatile uint32_t msgCounter1 = 0;
+void InterruptHandler::readPendingMessage() {
memset(&tempMessage, 0, sizeof(tempMessage));
- /* Read the message */
- fusb_read_message(&tempMessage);
- /* If it's a Soft_Reset, go to the soft reset state */
- if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(&tempMessage) == 0) {
- /* TX transitions to its reset state */
- ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_RESET);
- } else {
- /* Tell ProtocolTX to discard the message being transmitted */
- ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_DISCARD);
+ while (fusb_rx_pending()) {
+ msgCounter++;
+ /* Read the message */
+ if (fusb_read_message(&tempMessage) == 0) {
+ /* If it's a Soft_Reset, go to the soft reset state */
+ if (PD_MSGTYPE_GET(&tempMessage) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(&tempMessage) == 0) {
+ /* TX transitions to its reset state */
+ PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_RESET);
+ } else {
+ /* Tell PolicyEngine to discard the message being transmitted */
+ PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_TX_DISCARD);
- /* Pass the message to the policy engine. */
- PolicyEngine::handleMessage(&tempMessage);
+ /* Pass the message to the policy engine. */
+ PolicyEngine::handleMessage(&tempMessage);
+ }
+ } else {
+ msgCounter1++;
+ }
}
}
@@ -66,27 +69,28 @@ void InterruptHandler::Thread(const void *arg) {
xTaskNotifyWait(0x00, 0x0F, NULL, TICKS_SECOND * 30);
}
/* Read the FUSB302B status and interrupt registers */
- fusb_get_status(&status);
+ if (fusb_get_status(&status)) {
- /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */
- // This means a message was recieved with a good CRC
- if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) {
- readPendingMessage();
- }
+ /* If the I_GCRCSENT flag is set, tell the Protocol RX thread */
+ // This means a message was received with a good CRC
+ if (status.interruptb & FUSB_INTERRUPTB_I_GCRCSENT) {
+ readPendingMessage();
+ }
- /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX
- * thread */
- if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) {
- ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_TXSENT);
- }
- if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) {
- ProtocolTransmit::notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
- }
+ /* If the I_TXSENT or I_RETRYFAIL flag is set, tell the Protocol TX
+ * thread */
+ if (status.interrupta & FUSB_INTERRUPTA_I_TXSENT) {
+ PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_TX_I_TXSENT);
+ }
+ if (status.interrupta & FUSB_INTERRUPTA_I_RETRYFAIL) {
+ PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_TX_I_RETRYFAIL);
+ }
- /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy
- * Engine thread */
- if ((status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP) && (status.status1 & FUSB_STATUS1_OVRTEMP)) {
- PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_I_OVRTEMP);
+ /* If the I_OCP_TEMP and OVRTEMP flags are set, tell the Policy
+ * Engine thread */
+ if ((status.interrupta & FUSB_INTERRUPTA_I_OCP_TEMP) && (status.status1 & FUSB_STATUS1_OVRTEMP)) {
+ PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_I_OVRTEMP);
+ }
}
}
}
diff --git a/source/Core/Drivers/FUSB302/policy_engine.cpp b/source/Core/Drivers/FUSB302/policy_engine.cpp
index d1ebaba0..23ee8810 100644
--- a/source/Core/Drivers/FUSB302/policy_engine.cpp
+++ b/source/Core/Drivers/FUSB302/policy_engine.cpp
@@ -19,7 +19,6 @@
#include "Defines.h"
#include "fusb302b.h"
#include "int_n.h"
-#include "protocol_tx.h"
#include <pd.h>
#include <stdbool.h>
bool PolicyEngine::pdNegotiationComplete;
@@ -43,8 +42,9 @@ uint8_t PolicyEngine::ucQueueStorageArea[PDB_MSG_POOL_
QueueHandle_t PolicyEngine::messagesWaiting = NULL;
EventGroupHandle_t PolicyEngine::xEventGroupHandle = NULL;
StaticEventGroup_t PolicyEngine::xCreatedEventGroup;
-bool PolicyEngine::PPSTimerEnabled = false;
-TickType_t PolicyEngine::PPSTimeLastEvent = 0;
+bool PolicyEngine::PPSTimerEnabled = false;
+TickType_t PolicyEngine::PPSTimeLastEvent = 0;
+uint8_t PolicyEngine::_tx_messageidcounter = 0;
void PolicyEngine::init() {
messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
// Create static thread at PDB_PRIO_PE priority
@@ -238,9 +238,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_select_cap() {
/* Transmit the request */
waitForEvent((uint32_t)Notifications::PDB_EVT_PE_ALL, 0); // clear pending
- ProtocolTransmit::pushMessage(&_last_dpm_request);
- // Send indication that there is a message pending
- EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
+ EventBits_t evt = pushMessage(&_last_dpm_request);
/* If we got reset signaling, transition to default */
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET || evt == 0) {
return PESinkTransitionDefault;
@@ -410,8 +408,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_get_source_cap() {
/* Make a Get_Source_Cap message */
get_source_cap->hdr = hdr_template | PD_MSGTYPE_GET_SOURCE_CAP | PD_NUMOBJ(0);
/* Transmit the Get_Source_Cap */
- ProtocolTransmit::pushMessage(get_source_cap);
- EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
+ EventBits_t evt = pushMessage(get_source_cap);
/* Free the sent message */
/* If we got reset signaling, transition to default */
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET) {
@@ -432,8 +429,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_give_sink_cap() {
pdbs_dpm_get_sink_capability(snk_cap);
/* Transmit our capabilities */
- ProtocolTransmit::pushMessage(snk_cap);
- EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
+ EventBits_t evt = pushMessage(snk_cap);
/* Free the Sink_Capabilities message */
@@ -485,8 +481,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_soft_reset() {
/* Make an Accept message */
accept.hdr = hdr_template | PD_MSGTYPE_ACCEPT | PD_NUMOBJ(0);
/* Transmit the Accept */
- ProtocolTransmit::pushMessage(&accept);
- EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
+ EventBits_t evt = pushMessage(&accept);
/* Free the sent message */
/* If we got reset signaling, transition to default */
@@ -510,8 +505,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_soft_reset() {
/* Make a Soft_Reset message */
softrst->hdr = hdr_template | PD_MSGTYPE_SOFT_RESET | PD_NUMOBJ(0);
/* Transmit the soft reset */
- ProtocolTransmit::pushMessage(softrst);
- EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
+ EventBits_t evt = pushMessage(softrst);
/* If we got reset signaling, transition to default */
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET) {
return PESinkTransitionDefault;
@@ -564,8 +558,7 @@ PolicyEngine::policy_engine_state PolicyEngine::pe_sink_send_not_supported() {
}
/* Transmit the message */
- ProtocolTransmit::pushMessage(&tempMessage);
- EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_TX_DONE | (uint32_t)Notifications::PDB_EVT_PE_TX_ERR | (uint32_t)Notifications::PDB_EVT_PE_RESET);
+ EventBits_t evt = pushMessage(&tempMessage);
/* If we got reset signaling, transition to default */
if (evt & (uint32_t)Notifications::PDB_EVT_PE_RESET) {
@@ -625,3 +618,57 @@ void PolicyEngine::PPSTimerCallback() {
}
}
}
+
+EventBits_t PolicyEngine::pushMessage(union pd_msg *msg) {
+ if (PD_MSGTYPE_GET(msg) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(msg) == 0) {
+ /* Clear MessageIDCounter */
+ _tx_messageidcounter = 0;
+ return (EventBits_t)Notifications::PDB_EVT_PE_TX_DONE;
+ }
+ msg->hdr &= ~PD_HDR_MESSAGEID;
+ msg->hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT;
+
+ /* PD 3.0 collision avoidance */
+ if (PolicyEngine::isPD3_0()) {
+ /* If we're starting an AMS, wait for permission to transmit */
+ // while (fusb_get_typec_current() != fusb_sink_tx_ok) {
+ // vTaskDelay(TICKS_10MS);
+ // }
+ }
+ /* Send the message to the PHY */
+ fusb_send_message(msg);
+ /* Waiting for response*/
+ EventBits_t evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PE_RESET | (uint32_t)Notifications::PDB_EVT_TX_DISCARD | (uint32_t)Notifications::PDB_EVT_TX_I_TXSENT
+ | (uint32_t)Notifications::PDB_EVT_TX_I_RETRYFAIL);
+
+ if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_TX_DISCARD) {
+ // increment the counter
+ _tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
+ return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR; //
+ }
+
+ /* If the message was sent successfully */
+ if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_TX_I_TXSENT) {
+ union pd_msg goodcrc;
+
+ /* Read the GoodCRC */
+ fusb_read_message(&goodcrc);
+
+ /* Check that the message is correct */
+ if (PD_MSGTYPE_GET(&goodcrc) == PD_MSGTYPE_GOODCRC && PD_NUMOBJ_GET(&goodcrc) == 0 && PD_MESSAGEID_GET(&goodcrc) == _tx_messageidcounter) {
+ /* Increment MessageIDCounter */
+ _tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
+
+ return (EventBits_t)Notifications::PDB_EVT_PE_TX_DONE;
+ } else {
+ return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR;
+ }
+ }
+ /* If the message failed to be sent */
+ if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_TX_I_RETRYFAIL) {
+ return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR;
+ }
+
+ /* Silence the compiler warning */
+ return (EventBits_t)Notifications::PDB_EVT_PE_TX_ERR;
+}
diff --git a/source/Core/Drivers/FUSB302/policy_engine.h b/source/Core/Drivers/FUSB302/policy_engine.h
index 489b7a50..447d17c6 100644
--- a/source/Core/Drivers/FUSB302/policy_engine.h
+++ b/source/Core/Drivers/FUSB302/policy_engine.h
@@ -61,7 +61,10 @@ public:
PDB_EVT_PE_PPS_REQUEST = EVENT_MASK(6),
PDB_EVT_PE_GET_SOURCE_CAP = EVENT_MASK(7),
PDB_EVT_PE_NEW_POWER = EVENT_MASK(8),
- PDB_EVT_PE_ALL = (EVENT_MASK(9) - 1),
+ PDB_EVT_TX_I_TXSENT = EVENT_MASK(9),
+ PDB_EVT_TX_I_RETRYFAIL = EVENT_MASK(10),
+ PDB_EVT_TX_DISCARD = EVENT_MASK(11),
+ PDB_EVT_PE_ALL = (EVENT_MASK(12) - 1),
};
// Send a notification
static void notify(Notifications notification);
@@ -86,25 +89,28 @@ private:
/* The index of the first PPS APDO */
static uint8_t _pps_index;
- static void pe_task(const void *arg);
+ static void pe_task(const void *arg);
+ static EventBits_t pushMessage(union pd_msg *msg);
+ static uint8_t _tx_messageidcounter;
enum policy_engine_state {
- PESinkStartup,
- PESinkDiscovery,
- PESinkWaitCap,
- PESinkEvalCap,
- PESinkSelectCap, // 4
- PESinkTransitionSink, // 5
- PESinkReady, // 6
- PESinkGetSourceCap,
- PESinkGiveSinkCap,
- PESinkHardReset,
- PESinkTransitionDefault,
- PESinkSoftReset,
- PESinkSendSoftReset,
- PESinkSendNotSupported,
- PESinkChunkReceived,
- PESinkNotSupportedReceived,
- PESinkSourceUnresponsive
+ PESinkStartup, // 0
+ PESinkDiscovery, // 1
+ PESinkWaitCap, // 2
+ PESinkEvalCap, // 3
+ PESinkSelectCap, // 4
+ PESinkTransitionSink, // 5
+ PESinkReady, // 6
+ PESinkGetSourceCap, // 7
+ PESinkGiveSinkCap, // 8
+ PESinkHardReset, // 9
+ PESinkTransitionDefault, // 10
+ PESinkSoftReset, // 11
+ PESinkSendSoftReset, // 12
+ PESinkSendNotSupported, // 13
+ PESinkChunkReceived, // 14
+ PESinkNotSupportedReceived, // 15
+ PESinkSourceUnresponsive // 16
+
};
static enum policy_engine_state pe_sink_startup();
static enum policy_engine_state pe_sink_discovery();
diff --git a/source/Core/Drivers/FUSB302/policy_engine_user.cpp b/source/Core/Drivers/FUSB302/policy_engine_user.cpp
index 89f72c3e..b97584aa 100644
--- a/source/Core/Drivers/FUSB302/policy_engine_user.cpp
+++ b/source/Core/Drivers/FUSB302/policy_engine_user.cpp
@@ -6,6 +6,7 @@
*/
#include "BSP_PD.h"
#include "configuration.h"
+#include "main.hpp"
#include "pd.h"
#include "policy_engine.h"
@@ -60,6 +61,7 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability(const union pd_msg *capabilities
int bestIndexVoltage = 0;
int bestIndexCurrent = 0;
bool bestIsPPS = false;
+ powerSupplyWattageLimit = 0;
for (uint8_t i = 0; i < numobj; i++) {
/* If we have a fixed PDO, its V equals our desired V, and its I is
* at least our desired I */
@@ -72,7 +74,15 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability(const union pd_msg *capabilities
int current_a_x100 = PD_PDO_SRC_FIXED_CURRENT_GET(capabilities->obj[i]); // current in 10mA units
int min_resistance_ohmsx10 = voltage_mv / current_a_x100;
if (voltage_mv <= (USB_PD_VMAX * 1000)) {
- if (min_resistance_ohmsx10 <= tipResistance) {
+#ifdef MODEL_HAS_DCDC
+ // If this device has step down DC/DC inductor to smooth out current spikes
+ // We can instead ignore resistance and go for max voltage we can accept
+ if (voltage_mv <= (USB_PD_VMAX * 1000)) {
+ min_resistance_ohmsx10 = tipResistance;
+ }
+#endif
+ // Fudge of 0.5 ohms to round up a little to account for other losses
+ if (min_resistance_ohmsx10 <= (tipResistance + 5)) {
// This is a valid power source we can select as
if (voltage_mv > bestIndexVoltage || bestIndex == 0xFF) {
// Higher voltage and valid, select this instead
@@ -80,12 +90,14 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability(const union pd_msg *capabilities
bestIndexVoltage = voltage_mv;
bestIndexCurrent = current_a_x100;
bestIsPPS = false;
+#ifdef MODEL_HAS_DCDC
+ // set limiter for wattage
+ powerSupplyWattageLimit = ((voltage_mv * current_a_x100) / 100 / 1000);
+#endif
}
}
}
- } else
-
- if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED && (capabilities->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) {
+ } else if ((capabilities->obj[i] & PD_PDO_TYPE) == PD_PDO_TYPE_AUGMENTED && (capabilities->obj[i] & PD_APDO_TYPE) == PD_APDO_TYPE_PPS) {
// If this is a PPS slot, calculate the max voltage in the PPS range that can we be used and maintain
uint16_t max_voltage = PD_PAV2MV(PD_APDO_PPS_MAX_VOLTAGE_GET(capabilities->obj[i]));
// uint16_t min_voltage = PD_PAV2MV(PD_APDO_PPS_MIN_VOLTAGE_GET(capabilities->obj[i]));
@@ -105,6 +117,10 @@ bool PolicyEngine::pdbs_dpm_evaluate_capability(const union pd_msg *capabilities
bestIndexVoltage = ideal_voltage_mv;
bestIndexCurrent = max_current;
bestIsPPS = true;
+#ifdef MODEL_HAS_DCDC
+ // set limiter for wattage
+ powerSupplyWattageLimit = ((ideal_voltage_mv * max_current) / 100 / 1000);
+#endif
}
}
}
diff --git a/source/Core/Drivers/FUSB302/protocol_tx.cpp b/source/Core/Drivers/FUSB302/protocol_tx.cpp
deleted file mode 100644
index ca9410b5..00000000
--- a/source/Core/Drivers/FUSB302/protocol_tx.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/*
- * PD Buddy Firmware Library - USB Power Delivery for everyone
- * Copyright 2017-2018 Clayton G. Hobbs
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "protocol_tx.h"
-#include "Defines.h"
-#include "fusb302b.h"
-#include "fusbpd.h"
-#include "policy_engine.h"
-#include <pd.h>
-
-osThreadId ProtocolTransmit::TaskHandle = NULL;
-uint32_t ProtocolTransmit::TaskBuffer[ProtocolTransmit::TaskStackSize];
-osStaticThreadDef_t ProtocolTransmit::TaskControlBlock;
-StaticQueue_t ProtocolTransmit::xStaticQueue;
-bool ProtocolTransmit::messageSending = false;
-uint8_t ProtocolTransmit::ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)];
-QueueHandle_t ProtocolTransmit::messagesWaiting = NULL;
-uint8_t ProtocolTransmit::_tx_messageidcounter;
-union pd_msg ProtocolTransmit::temp_msg;
-EventGroupHandle_t ProtocolTransmit::xEventGroupHandle = NULL;
-StaticEventGroup_t ProtocolTransmit::xCreatedEventGroup;
-/*
- * PRL_Tx_PHY_Layer_Reset state
- */
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_phy_reset() {
- /* Reset the PHY */
- fusb_reset();
-
- /* If a message was pending when we got here, tell the policy engine that
- * we failed to send it */
- if (messagePending()) {
- /* Tell the policy engine that we failed */
- PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_TX_ERR);
- /* Finish failing to send the message */
- while (messagePending()) {
- getMessage(); // Discard
- }
- }
-
- /* Wait for a message request */
- return PRLTxWaitMessage;
-}
-
-/*
- * PRL_Tx_Wait_for_Message_Request state
- */
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_message() {
- /* Wait for an event */
- ProtocolTransmit::Notifications evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PRLTX_RESET | (uint32_t)Notifications::PDB_EVT_PRLTX_DISCARD | (uint32_t)Notifications::PDB_EVT_PRLTX_MSG_TX);
-
- if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_RESET) {
- return PRLTxPHYReset;
- }
-
- /* If the policy engine is trying to send a message */
- if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_MSG_TX) {
- /* Get the message */
- getMessage();
-
- /* If it's a Soft_Reset, reset the TX layer first */
- if (PD_MSGTYPE_GET(&temp_msg) == PD_MSGTYPE_SOFT_RESET && PD_NUMOBJ_GET(&(temp_msg)) == 0) {
- return PRLTxReset;
- /* Otherwise, just send the message */
- } else {
- return PRLTxConstructMessage;
- }
- }
-
- /* Silence the compiler warning */
- return PRLTxWaitMessage;
-}
-
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_reset() {
- /* Clear MessageIDCounter */
- _tx_messageidcounter = 0;
-
- return PRLTxConstructMessage;
-}
-
-/*
- * PRL_Tx_Construct_Message state
- */
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_construct_message() {
- /* Set the correct MessageID in the message */
- temp_msg.hdr &= ~PD_HDR_MESSAGEID;
- temp_msg.hdr |= (_tx_messageidcounter % 8) << PD_HDR_MESSAGEID_SHIFT;
-
- /* PD 3.0 collision avoidance */
- if (PolicyEngine::isPD3_0()) {
- /* If we're starting an AMS, wait for permission to transmit */
- while (fusb_get_typec_current() != fusb_sink_tx_ok) {
- vTaskDelay(TICKS_10MS);
- }
- }
- messageSending = true;
- /* Send the message to the PHY */
- fusb_send_message(&temp_msg);
-
- return PRLTxWaitResponse;
-}
-
-/*
- * PRL_Tx_Wait_for_PHY_Response state
- */
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_wait_response() {
- /* Wait for an event. There is no need to run CRCReceiveTimer, since the
- * FUSB302B handles that as part of its retry mechanism. */
- ProtocolTransmit::Notifications evt = waitForEvent((uint32_t)Notifications::PDB_EVT_PRLTX_RESET | (uint32_t)Notifications::PDB_EVT_PRLTX_DISCARD | (uint32_t)Notifications::PDB_EVT_PRLTX_I_TXSENT
- | (uint32_t)Notifications::PDB_EVT_PRLTX_I_RETRYFAIL);
-
- if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_RESET) {
- return PRLTxPHYReset;
- }
- if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_DISCARD) {
- return PRLTxDiscardMessage;
- }
-
- /* If the message was sent successfully */
- if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_I_TXSENT) {
- return PRLTxMatchMessageID;
- }
- /* If the message failed to be sent */
- if ((uint32_t)evt & (uint32_t)Notifications::PDB_EVT_PRLTX_I_RETRYFAIL) {
- return PRLTxTransmissionError;
- }
-
- /* Silence the compiler warning */
- return PRLTxDiscardMessage;
-}
-
-/*
- * PRL_Tx_Match_MessageID state
- */
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_match_messageid() {
- union pd_msg goodcrc;
-
- /* Read the GoodCRC */
- fusb_read_message(&goodcrc);
-
- /* Check that the message is correct */
- if (PD_MSGTYPE_GET(&goodcrc) == PD_MSGTYPE_GOODCRC && PD_NUMOBJ_GET(&goodcrc) == 0 && PD_MESSAGEID_GET(&goodcrc) == _tx_messageidcounter) {
- return PRLTxMessageSent;
- } else {
- return PRLTxTransmissionError;
- }
-}
-
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_transmission_error() {
- /* Increment MessageIDCounter */
- _tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
-
- /* Tell the policy engine that we failed */
- PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_TX_ERR);
-
- return PRLTxWaitMessage;
-}
-
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_message_sent() {
- messageSending = false;
- /* Increment MessageIDCounter */
- _tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
-
- /* Tell the policy engine that we succeeded */
- PolicyEngine::notify(PolicyEngine::Notifications::PDB_EVT_PE_TX_DONE);
-
- return PRLTxWaitMessage;
-}
-
-ProtocolTransmit::protocol_tx_state ProtocolTransmit::protocol_tx_discard_message() {
- /* If we were working on sending a message, increment MessageIDCounter */
- if (messageSending) {
- _tx_messageidcounter = (_tx_messageidcounter + 1) % 8;
-
- return PRLTxPHYReset;
- } else {
- return PRLTxWaitMessage;
- }
-}
-void ProtocolTransmit::thread(const void *args) {
- (void)args;
- ProtocolTransmit::protocol_tx_state state = PRLTxPHYReset;
-
- // Init the incoming message queue
-
- while (true) {
- switch (state) {
- case PRLTxPHYReset:
- state = protocol_tx_phy_reset();
- break;
- case PRLTxWaitMessage:
- state = protocol_tx_wait_message();
- break;
- case PRLTxReset:
- state = protocol_tx_reset();
- break;
- case PRLTxConstructMessage:
- state = protocol_tx_construct_message();
- break;
- case PRLTxWaitResponse:
- state = protocol_tx_wait_response();
- break;
- case PRLTxMatchMessageID:
- state = protocol_tx_match_messageid();
- break;
- case PRLTxTransmissionError:
- state = protocol_tx_transmission_error();
- break;
- case PRLTxMessageSent:
- state = protocol_tx_message_sent();
- break;
- case PRLTxDiscardMessage:
- state = protocol_tx_discard_message();
- break;
- default:
- state = PRLTxPHYReset;
- break;
- }
- }
-}
-
-void ProtocolTransmit::notify(ProtocolTransmit::Notifications notification) {
- if (xEventGroupHandle != NULL) {
- xEventGroupSetBits(xEventGroupHandle, (uint32_t)notification);
- }
-}
-
-void ProtocolTransmit::init() {
- messagesWaiting = xQueueCreateStatic(PDB_MSG_POOL_SIZE, sizeof(union pd_msg), ucQueueStorageArea, &xStaticQueue);
-
- osThreadStaticDef(pd_txTask, thread, PDB_PRIO_PRL, 0, TaskStackSize, TaskBuffer, &TaskControlBlock);
- TaskHandle = osThreadCreate(osThread(pd_txTask), NULL);
- xEventGroupHandle = xEventGroupCreateStatic(&xCreatedEventGroup);
-}
-
-void ProtocolTransmit::pushMessage(union pd_msg *msg) {
- if (messagesWaiting) {
- if (xQueueSend(messagesWaiting, msg, 100) == pdTRUE) {
- notify(ProtocolTransmit::Notifications::PDB_EVT_PRLTX_MSG_TX);
- }
- }
-}
-
-bool ProtocolTransmit::messagePending() {
- if (messagesWaiting) {
- return uxQueueMessagesWaiting(messagesWaiting) > 0;
- }
- return false;
-}
-
-void ProtocolTransmit::getMessage() {
- // Loads the pending message into the buffer
- if (messagesWaiting) {
- xQueueReceive(messagesWaiting, &temp_msg, 1);
- }
-}
-
-ProtocolTransmit::Notifications ProtocolTransmit::waitForEvent(uint32_t mask, TickType_t ticksToWait) {
- if (xEventGroupHandle) {
- return (Notifications)xEventGroupWaitBits(xEventGroupHandle, mask, mask, pdFALSE, ticksToWait);
- }
- return (Notifications)0;
-}
diff --git a/source/Core/Drivers/FUSB302/protocol_tx.h b/source/Core/Drivers/FUSB302/protocol_tx.h
deleted file mode 100644
index 0231f455..00000000
--- a/source/Core/Drivers/FUSB302/protocol_tx.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * PD Buddy Firmware Library - USB Power Delivery for everyone
- * Copyright 2017-2018 Clayton G. Hobbs
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef PDB_PROTOCOL_TX_H
-#define PDB_PROTOCOL_TX_H
-
-#include "policy_engine.h"
-
-#include <pd.h>
-#include <stdint.h>
-
-/* Events for the Protocol TX thread */
-
-class ProtocolTransmit {
-public:
- static void init();
- // Push a message to the queue to be sent out the pd comms bus
- static void pushMessage(union pd_msg *msg);
-
- enum class Notifications {
-
- PDB_EVT_PRLTX_RESET = EVENT_MASK(0), //
- PDB_EVT_PRLTX_I_TXSENT = EVENT_MASK(1), //
- PDB_EVT_PRLTX_I_RETRYFAIL = EVENT_MASK(2), //
- PDB_EVT_PRLTX_DISCARD = EVENT_MASK(3), //
- PDB_EVT_PRLTX_MSG_TX = EVENT_MASK(4), //
- };
- static void notify(Notifications notification);
-
-private:
- static void thread(const void *args);
- static EventGroupHandle_t xEventGroupHandle;
- static StaticEventGroup_t xCreatedEventGroup;
- static osThreadId TaskHandle;
- static const size_t TaskStackSize = 1024 / 4;
- static uint32_t TaskBuffer[TaskStackSize];
- static osStaticThreadDef_t TaskControlBlock;
- static bool messageSending;
- /*
- * Protocol TX machine states
- *
- * Because the PHY can automatically send retries, the Check_RetryCounter state
- * has been removed, transitions relating to it are modified appropriately, and
- * we don't even keep a RetryCounter.
- */
- enum protocol_tx_state { PRLTxPHYReset, PRLTxWaitMessage, PRLTxReset, PRLTxConstructMessage, PRLTxWaitResponse, PRLTxMatchMessageID, PRLTxTransmissionError, PRLTxMessageSent, PRLTxDiscardMessage };
- // Internal states
- static protocol_tx_state protocol_tx_discard_message();
- static protocol_tx_state protocol_tx_message_sent();
- static protocol_tx_state protocol_tx_transmission_error();
- static protocol_tx_state protocol_tx_match_messageid();
- static protocol_tx_state protocol_tx_wait_response();
- static protocol_tx_state protocol_tx_construct_message();
- static protocol_tx_state protocol_tx_reset();
- static protocol_tx_state protocol_tx_wait_message();
- static protocol_tx_state protocol_tx_phy_reset();
- // queue of up to PDB_MSG_POOL_SIZE messages to send
- static StaticQueue_t xStaticQueue;
- /* The array to use as the queue's storage area. This must be at least
- uxQueueLength * uxItemSize bytes. */
- static uint8_t ucQueueStorageArea[PDB_MSG_POOL_SIZE * sizeof(union pd_msg)];
- static QueueHandle_t messagesWaiting;
- static uint8_t _tx_messageidcounter;
- static bool messagePending();
- // Reads a message off the queue into the temp message
- static void getMessage();
- static union pd_msg temp_msg;
- static Notifications waitForEvent(uint32_t mask, TickType_t ticksToWait = portMAX_DELAY);
-};
-
-#endif /* PDB_PROTOCOL_TX_H */
diff --git a/source/Core/Drivers/I2CBB.cpp b/source/Core/Drivers/I2CBB.cpp
index b55435d7..f90b09fc 100644
--- a/source/Core/Drivers/I2CBB.cpp
+++ b/source/Core/Drivers/I2CBB.cpp
@@ -274,6 +274,14 @@ bool I2CBB::lock() {
return a;
}
+bool I2CBB::I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data) { return Mem_Write(address, reg, &data, 1); }
+
+uint8_t I2CBB::I2C_RegisterRead(uint8_t address, uint8_t reg) {
+ uint8_t temp = 0;
+ Mem_Read(address, reg, &temp, 1);
+ return temp;
+}
+
void I2CBB::write_bit(uint8_t val) {
if (val) {
SOFT_SDA_HIGH();
@@ -287,4 +295,14 @@ void I2CBB::write_bit(uint8_t val) {
SOFT_SCL_LOW();
}
+bool I2CBB::writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength) {
+ for (int index = 0; index < registersLength; index++) {
+ if (!I2C_RegisterWrite(address, registers[index].reg, registers[index].val)) {
+ return false;
+ }
+ if (registers[index].pause_ms)
+ delay_ms(registers[index].pause_ms);
+ }
+ return true;
+}
#endif
diff --git a/source/Core/Drivers/I2CBB.hpp b/source/Core/Drivers/I2CBB.hpp
index 7b580b07..cf2e4df1 100644
--- a/source/Core/Drivers/I2CBB.hpp
+++ b/source/Core/Drivers/I2CBB.hpp
@@ -24,10 +24,18 @@ public:
// Issues a complete 8bit register read
static bool Mem_Read(uint16_t DevAddress, uint16_t MemAddress, uint8_t *pData, uint16_t Size);
// Implements a register write
- static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, const uint8_t *pData, uint16_t Size);
- static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
- static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
- static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx);
+ static bool Mem_Write(uint16_t DevAddress, uint16_t MemAddress, const uint8_t *pData, uint16_t Size);
+ static void Transmit(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
+ static void Receive(uint16_t DevAddress, uint8_t *pData, uint16_t Size);
+ static void TransmitReceive(uint16_t DevAddress, uint8_t *pData_tx, uint16_t Size_tx, uint8_t *pData_rx, uint16_t Size_rx);
+ static bool I2C_RegisterWrite(uint8_t address, uint8_t reg, uint8_t data);
+ static uint8_t I2C_RegisterRead(uint8_t address, uint8_t reg);
+ typedef struct {
+ const uint8_t reg; // The register to write to
+ uint8_t val; // The value to write to this register
+ const uint8_t pause_ms; // How many ms to pause _after_ writing this reg
+ } I2C_REG;
+ static bool writeRegistersBulk(const uint8_t address, const I2C_REG *registers, const uint8_t registersLength);
private:
static SemaphoreHandle_t I2CSemaphore;
diff --git a/source/Core/Drivers/MSA301.cpp b/source/Core/Drivers/MSA301.cpp
index a3d64de8..3e1b9e46 100644
--- a/source/Core/Drivers/MSA301.cpp
+++ b/source/Core/Drivers/MSA301.cpp
@@ -7,7 +7,7 @@
#include "MSA301_defines.h"
#include <MSA301.h>
-#define MSA301_I2C_ADDRESS 0x4C
+#define MSA301_I2C_ADDRESS 0x26 << 1
bool MSA301::detect() { return FRToSI2C::probe(MSA301_I2C_ADDRESS); }
static const FRToSI2C::I2C_REG i2c_registers[] = {
diff --git a/source/Core/Drivers/OLED.cpp b/source/Core/Drivers/OLED.cpp
index fc8ef266..b3559360 100644
--- a/source/Core/Drivers/OLED.cpp
+++ b/source/Core/Drivers/OLED.cpp
@@ -29,7 +29,7 @@ uint8_t OLED::secondFrameBuffer[OLED_WIDTH * 2];
/*http://www.displayfuture.com/Display/datasheet/controller/SSD1307.pdf*/
/*All commands are prefixed with 0x80*/
/*Data packets are prefixed with 0x40*/
-FRToSI2C::I2C_REG OLED_Setup_Array[] = {
+I2C_CLASS::I2C_REG OLED_Setup_Array[] = {
/**/
{0x80, 0xAE, 0}, /*Display off*/
{0x80, 0xD5, 0}, /*Set display clock divide ratio / osc freq*/
@@ -120,7 +120,7 @@ void OLED::initialize() {
// initialisation data to the OLED.
for (int tries = 0; tries < 10; tries++) {
- if (FRToSI2C::writeRegistersBulk(DEVICEADDR_OLED, OLED_Setup_Array, sizeof(OLED_Setup_Array) / sizeof(OLED_Setup_Array[0]))) {
+ if (I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, OLED_Setup_Array, sizeof(OLED_Setup_Array) / sizeof(OLED_Setup_Array[0]))) {
return;
}
}
@@ -238,7 +238,7 @@ void OLED::maskScrollIndicatorOnOLED() {
0x00,
0x00,
};
- FRToSI2C::Transmit(DEVICEADDR_OLED, maskCommands, sizeof(maskCommands));
+ I2C_CLASS::Transmit(DEVICEADDR_OLED, maskCommands, sizeof(maskCommands));
}
/**
@@ -331,7 +331,7 @@ void OLED::transitionScrollDown() {
// Also update setup command for "set display start line":
OLED_Setup_Array[8].val = scrollCommandByte;
- FRToSI2C::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, scrollCommandByte);
+ I2C_CLASS::I2C_RegisterWrite(DEVICEADDR_OLED, 0x80, scrollCommandByte);
osDelay(TICKS_100MS / 5);
}
}
@@ -352,7 +352,7 @@ void OLED::setRotation(bool leftHanded) {
OLED_Setup_Array[5].val = 0xC0;
OLED_Setup_Array[9].val = 0xA0;
}
- FRToSI2C::writeRegistersBulk(DEVICEADDR_OLED, OLED_Setup_Array, sizeof(OLED_Setup_Array) / sizeof(OLED_Setup_Array[0]));
+ I2C_CLASS::writeRegistersBulk(DEVICEADDR_OLED, OLED_Setup_Array, sizeof(OLED_Setup_Array) / sizeof(OLED_Setup_Array[0]));
inLeftHandedMode = leftHanded;
diff --git a/source/Core/Drivers/OLED.hpp b/source/Core/Drivers/OLED.hpp
index c108dcf7..83e8914d 100644
--- a/source/Core/Drivers/OLED.hpp
+++ b/source/Core/Drivers/OLED.hpp
@@ -10,7 +10,7 @@
#ifndef OLED_HPP_
#define OLED_HPP_
#include "Font.h"
-#include "I2C_Wrapper.hpp"
+#include "Model_Config.h"
#include <BSP.h>
#include <stdbool.h>
#include <string.h>
@@ -21,6 +21,15 @@ extern "C" {
#ifdef __cplusplus
}
#endif
+
+#ifdef OLED_I2CBB
+#include "I2CBB.hpp"
+#define I2C_CLASS I2CBB
+#else
+#define I2C_CLASS FRToSI2C
+#include "I2C_Wrapper.hpp"
+#endif
+
#define DEVICEADDR_OLED (0x3c << 1)
#define OLED_WIDTH 96
#define OLED_HEIGHT 16
@@ -40,7 +49,7 @@ public:
static bool isInitDone();
// Draw the buffer out to the LCD using the DMA Channel
static void refresh() {
- FRToSI2C::Transmit(DEVICEADDR_OLED, screenBuffer, FRAMEBUFFER_START + (OLED_WIDTH * 2));
+ I2C_CLASS::Transmit(DEVICEADDR_OLED, screenBuffer, FRAMEBUFFER_START + (OLED_WIDTH * 2));
// DMA tx time is ~ 20mS Ensure after calling this you delay for at least 25ms
// or we need to goto double buffering
}
diff --git a/source/Core/Drivers/TipThermoModel.cpp b/source/Core/Drivers/TipThermoModel.cpp
index edf97fbc..813bba11 100644
--- a/source/Core/Drivers/TipThermoModel.cpp
+++ b/source/Core/Drivers/TipThermoModel.cpp
@@ -8,7 +8,7 @@
#include "TipThermoModel.h"
#include "BSP.h"
#include "Settings.h"
-#include "configuration.h"
+#include "Utils.h"
#include "main.hpp"
#include "power.hpp"
/*
@@ -27,8 +27,8 @@
*
* This was bought to my attention by <Kuba Sztandera>
*/
-
-uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC, bool skipCalOffset) {
+volatile uint32_t lastuv = 0;
+uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC, bool skipCalOffset) {
// This takes the raw ADC samples, converts these to uV
// Then divides this down by the gain to convert to the uV on the input to the op-amp (A+B terminals)
// Then remove the calibration value that is stored as a tip offset
@@ -48,152 +48,13 @@ uint32_t TipThermoModel::convertTipRawADCTouV(uint16_t rawADC, bool skipCalOffse
else
valueuV = 0;
}
-
+ lastuv = valueuV;
return valueuV;
}
uint32_t TipThermoModel::convertTipRawADCToDegC(uint16_t rawADC) { return convertuVToDegC(convertTipRawADCTouV(rawADC)); }
uint32_t TipThermoModel::convertTipRawADCToDegF(uint16_t rawADC) { return convertuVToDegF(convertTipRawADCTouV(rawADC)); }
-// Table that is designed to be walked to find the best sample for the lookup
-
-// Extrapolate between two points
-// [x1, y1] = point 1
-// [x2, y2] = point 2
-// x = input value
-// output is x's interpolated y value
-int32_t LinearInterpolate(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x) { return y1 + (((((x - x1) * 1000) / (x2 - x1)) * (y2 - y1))) / 1000; }
-#ifdef TEMP_uV_LOOKUP_HAKKO
-const uint16_t uVtoDegC[] = {
- //
- //
- 0, 0, //
- 266, 10, //
- 522, 20, //
- 770, 30, //
- 1010, 40, //
- 1244, 50, //
- 1473, 60, //
- 1697, 70, //
- 1917, 80, //
- 2135, 90, //
- 2351, 100, //
- 2566, 110, //
- 2780, 120, //
- 2994, 130, //
- 3209, 140, //
- 3426, 150, //
- 3644, 160, //
- 3865, 170, //
- 4088, 180, //
- 4314, 190, //
- 4544, 200, //
- 4777, 210, //
- 5014, 220, //
- 5255, 230, //
- 5500, 240, //
- 5750, 250, //
- 6003, 260, //
- 6261, 270, //
- 6523, 280, //
- 6789, 290, //
- 7059, 300, //
- 7332, 310, //
- 7609, 320, //
- 7889, 330, //
- 8171, 340, //
- 8456, 350, //
- 8742, 360, //
- 9030, 370, //
- 9319, 380, //
- 9607, 390, //
- 9896, 400, //
- 10183, 410, //
- 10468, 420, //
- 10750, 430, //
- 11029, 440, //
- 11304, 450, //
- 11573, 460, //
- 11835, 470, //
- 12091, 480, //
- 12337, 490, //
- 12575, 500, //
-
-};
-#endif
-
-#ifdef TEMP_uV_LOOKUP_TS80
-
-const uint16_t uVtoDegC[] = {
- //
- //
- 530, 0, //
- 1282, 10, //
- 2034, 20, //
- 2786, 30, //
- 3538, 40, //
- 4290, 50, //
- 5043, 60, //
- 5795, 70, //
- 6547, 80, //
- 7299, 90, //
- 8051, 100, //
- 8803, 110, //
- 9555, 120, //
- 10308, 130, //
- 11060, 140, //
- 11812, 150, //
- 12564, 160, //
- 13316, 170, //
- 14068, 180, //
- 14820, 190, //
- 15573, 200, //
- 16325, 210, //
- 17077, 220, //
- 17829, 230, //
- 18581, 240, //
- 19333, 250, //
- 20085, 260, //
- 20838, 270, //
- 21590, 280, //
- 22342, 290, //
- 23094, 300, //
- 23846, 310, //
- 24598, 320, //
- 25350, 330, //
- 26103, 340, //
- 26855, 350, //
- 27607, 360, //
- 28359, 370, //
- 29111, 380, //
- 29863, 390, //
- 30615, 400, //
- 31368, 410, //
- 32120, 420, //
- 32872, 430, //
- 33624, 440, //
- 34376, 450, //
- 35128, 460, //
- 35880, 470, //
- 36632, 480, //
- 37385, 490, //
- 38137, 500, //
-};
-#endif
-uint32_t TipThermoModel::convertuVToDegC(uint32_t tipuVDelta) {
- if (tipuVDelta) {
- int noItems = sizeof(uVtoDegC) / (2 * sizeof(uint16_t));
- for (int i = 1; i < (noItems - 1); i++) {
- // If current tip temp is less than current lookup, then this current lookup is the higher point to interpolate
- if (tipuVDelta < uVtoDegC[i * 2]) {
- return LinearInterpolate(uVtoDegC[(i - 1) * 2], uVtoDegC[((i - 1) * 2) + 1], uVtoDegC[i * 2], uVtoDegC[(i * 2) + 1], tipuVDelta);
- }
- }
- return LinearInterpolate(uVtoDegC[(noItems - 2) * 2], uVtoDegC[((noItems - 2) * 2) + 1], uVtoDegC[(noItems - 1) * 2], uVtoDegC[((noItems - 1) * 2) + 1], tipuVDelta);
- }
- return 0;
-}
-
uint32_t TipThermoModel::convertuVToDegF(uint32_t tipuVDelta) { return convertCtoF(convertuVToDegC(tipuVDelta)); }
uint32_t TipThermoModel::convertCtoF(uint32_t degC) {
@@ -208,14 +69,17 @@ uint32_t TipThermoModel::convertFtoC(uint32_t degF) {
}
return ((degF - 32) * 5) / 9;
}
-
uint32_t TipThermoModel::getTipInC(bool sampleNow) {
int32_t currentTipTempInC = TipThermoModel::convertTipRawADCToDegC(getTipRawTemp(sampleNow));
currentTipTempInC += getHandleTemperature() / 10; // Add handle offset
- // Power usage indicates that our tip temp is lower than our thermocouple temp.
- // I found a number that doesn't unbalance the existing PID, causing overshoot.
- // This could be tuned in concert with PID parameters...
+ // Power usage indicates that our tip temp is lower than our thermocouple temp.
+ // I found a number that doesn't unbalance the existing PID, causing overshoot.
+ // This could be tuned in concert with PID parameters...
+#ifdef THERMAL_MASS_OVERSHOOTS
+ currentTipTempInC += x10WattHistory.average() / 25;
+#else
currentTipTempInC -= x10WattHistory.average() / 25;
+#endif
if (currentTipTempInC < 0)
return 0;
return currentTipTempInC;
diff --git a/source/Core/Drivers/Utils.cpp b/source/Core/Drivers/Utils.cpp
new file mode 100644
index 00000000..9d85ef38
--- /dev/null
+++ b/source/Core/Drivers/Utils.cpp
@@ -0,0 +1,23 @@
+/*
+ * Utils.cpp
+ *
+ * Created on: 28 Apr 2021
+ * Author: Ralim
+ */
+
+#include <Utils.h>
+
+int32_t Utils::InterpolateLookupTable(const uint16_t *lookupTable, const int noItems, const uint16_t value) {
+ if (value) {
+ for (int i = 1; i < (noItems - 1); i++) {
+ // If current tip temp is less than current lookup, then this current lookup is the higher point to interpolate
+ if (value < lookupTable[i * 2]) {
+ return LinearInterpolate(lookupTable[(i - 1) * 2], lookupTable[((i - 1) * 2) + 1], lookupTable[i * 2], lookupTable[(i * 2) + 1], value);
+ }
+ }
+ return LinearInterpolate(lookupTable[(noItems - 2) * 2], lookupTable[((noItems - 2) * 2) + 1], lookupTable[(noItems - 1) * 2], lookupTable[((noItems - 1) * 2) + 1], value);
+ }
+ return 0;
+}
+
+int32_t Utils::LinearInterpolate(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x) { return y1 + (((((x - x1) * 1000) / (x2 - x1)) * (y2 - y1))) / 1000; }
diff --git a/source/Core/Drivers/Utils.h b/source/Core/Drivers/Utils.h
new file mode 100644
index 00000000..a4e2b07c
--- /dev/null
+++ b/source/Core/Drivers/Utils.h
@@ -0,0 +1,17 @@
+/*
+ * Utils.h
+ *
+ * Created on: 28 Apr 2021
+ * Author: Ralim
+ */
+
+#ifndef CORE_DRIVERS_UTILS_H_
+#define CORE_DRIVERS_UTILS_H_
+#include <stdint.h>
+class Utils {
+public:
+ static int32_t InterpolateLookupTable(const uint16_t *lookupTable, const int noItems, const uint16_t value);
+ static int32_t LinearInterpolate(int32_t x1, int32_t y1, int32_t x2, int32_t y2, int32_t x);
+};
+
+#endif /* CORE_DRIVERS_UTILS_H_ */
diff --git a/source/Core/Drivers/WS2812.h b/source/Core/Drivers/WS2812.h
new file mode 100644
index 00000000..d7eb4254
--- /dev/null
+++ b/source/Core/Drivers/WS2812.h
@@ -0,0 +1,124 @@
+/*
+ * WS2812.h
+ *
+ * Created on: 2 May 2021
+ * Author: Ralim
+ */
+#include "Pins.h"
+#include "Setup.h"
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#ifndef CORE_DRIVERS_WS2812_H_
+#define CORE_DRIVERS_WS2812_H_
+
+#ifndef WS2812_LED_CHANNEL_COUNT
+#define WS2812_LED_CHANNEL_COUNT 3
+#endif
+
+#define WS2812_RAW_BYTES_PER_LED (WS2812_LED_CHANNEL_COUNT * 8)
+
+template <uint32_t LED_GPIO, uint16_t LED_PIN, int LED_COUNT> class WS2812 {
+private:
+ uint8_t leds_colors[WS2812_LED_CHANNEL_COUNT * LED_COUNT];
+
+public:
+ void led_update() {
+ __disable_irq();
+ // Bitbang it out as our cpu irq latency is too high
+ for (unsigned int i = 0; i < sizeof(leds_colors); i++) {
+ // Shove out MSB first
+ for (int x = 0; x < 8; x++) {
+ ((GPIO_TypeDef *)WS2812_GPIO_Port)->BSRR = WS2812_Pin;
+ if ((leds_colors[i] & (1 << (7 - x))) == (1 << (7 - x))) {
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ } else {
+
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ }
+ ((GPIO_TypeDef *)WS2812_GPIO_Port)->BSRR = (uint32_t)WS2812_Pin << 16u;
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ __asm__ __volatile__("nop");
+ }
+ }
+ __enable_irq();
+ }
+
+ void init(void) { memset(leds_colors, 0, sizeof(leds_colors)); }
+
+ void led_set_color(size_t index, uint8_t r, uint8_t g, uint8_t b) {
+ leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = g;
+ leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = r;
+ leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b;
+ }
+
+ void led_set_color_all(uint8_t r, uint8_t g, uint8_t b) {
+ for (int index = 0; index < LED_COUNT; index++) {
+ leds_colors[index * WS2812_LED_CHANNEL_COUNT + 0] = g;
+ leds_colors[index * WS2812_LED_CHANNEL_COUNT + 1] = r;
+ leds_colors[index * WS2812_LED_CHANNEL_COUNT + 2] = b;
+ }
+ }
+};
+
+#endif /* CORE_DRIVERS_WS2812_H_ */