diff options
Diffstat (limited to 'source/Core/Drivers')
-rw-r--r-- | source/Core/Drivers/FUSB302/fusb302b.cpp | 52 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/fusb302b.h | 4 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/fusb_user.h | 30 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/fusbpd.cpp | 2 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/fusbpd.h | 3 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/int_n.cpp | 78 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/policy_engine.cpp | 79 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/policy_engine.h | 44 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/policy_engine_user.cpp | 24 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/protocol_tx.cpp | 276 | ||||
-rw-r--r-- | source/Core/Drivers/FUSB302/protocol_tx.h | 85 | ||||
-rw-r--r-- | source/Core/Drivers/I2CBB.cpp | 18 | ||||
-rw-r--r-- | source/Core/Drivers/I2CBB.hpp | 16 | ||||
-rw-r--r-- | source/Core/Drivers/MSA301.cpp | 2 | ||||
-rw-r--r-- | source/Core/Drivers/OLED.cpp | 10 | ||||
-rw-r--r-- | source/Core/Drivers/OLED.hpp | 13 | ||||
-rw-r--r-- | source/Core/Drivers/TipThermoModel.cpp | 158 | ||||
-rw-r--r-- | source/Core/Drivers/Utils.cpp | 23 | ||||
-rw-r--r-- | source/Core/Drivers/Utils.h | 17 | ||||
-rw-r--r-- | source/Core/Drivers/WS2812.h | 124 |
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_ */
|