mirror of
https://github.com/preble/libpinproc
synced 2026-02-24 18:25:23 +01:00
Fixed switch rule linking and completed DMD configuration
This commit is contained in:
@@ -85,11 +85,11 @@ void PRDevice::Reset()
|
|||||||
{
|
{
|
||||||
PRSwitchRuleInternal *switchRule = &switchRules[i];
|
PRSwitchRuleInternal *switchRule = &switchRules[i];
|
||||||
memset(switchRule, 0x00, sizeof(PRSwitchRule));
|
memset(switchRule, 0x00, sizeof(PRSwitchRule));
|
||||||
uint32_t addr = (i << P_ROC_SWITCH_RULE_ADDR_SWITCH_NUM_SHIFT);
|
uint16_t ruleIndex = i;
|
||||||
ParseSwitchAddress(addr, &switchRule->switchNum, &switchRule->eventType);
|
ParseSwitchRuleIndex(ruleIndex, &switchRule->switchNum, &switchRule->eventType);
|
||||||
switchRule->driver.polarity = defaultPolarity;
|
switchRule->driver.polarity = defaultPolarity;
|
||||||
if (switchRule->switchNum >= kPRSwitchVirtualFirst && switchRule->switchNum <= kPRSwitchVirtualLast)
|
if (switchRule->switchNum >= kPRSwitchVirtualFirst && switchRule->switchNum <= kPRSwitchVirtualLast)
|
||||||
freeSwitchRules.push(addr);
|
freeSwitchRuleIndexes.push(ruleIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
unrequestedDataQueue.empty();
|
unrequestedDataQueue.empty();
|
||||||
@@ -206,9 +206,9 @@ PRResult PRDevice::DriverWatchdogTickle()
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
PRSwitchRuleInternal *PRDevice::GetSwitchRuleByAddress(uint32_t addr)
|
PRSwitchRuleInternal *PRDevice::GetSwitchRuleByIndex(uint16_t index)
|
||||||
{
|
{
|
||||||
return &switchRules[addr>>P_ROC_SWITCH_RULE_ADDR_SWITCH_NUM_SHIFT];
|
return &switchRules[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
PRResult PRDevice::SwitchesUpdateRule(uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers)
|
PRResult PRDevice::SwitchesUpdateRule(uint8_t switchNum, PREventType eventType, PRSwitchRule *rule, PRDriverState *linkedDrivers, int numDrivers)
|
||||||
@@ -222,32 +222,38 @@ PRResult PRDevice::SwitchesUpdateRule(uint8_t switchNum, PREventType eventType,
|
|||||||
DEBUG(PRLog("Switch rule out of range 0-%d\n", kPRSwitchPhysicalLast));
|
DEBUG(PRLog("Switch rule out of range 0-%d\n", kPRSwitchPhysicalLast));
|
||||||
return kPRFailure;
|
return kPRFailure;
|
||||||
}
|
}
|
||||||
if (freeSwitchRules.size() < numDrivers-1) // -1 because the first switch rule holds the first driver.
|
|
||||||
|
// If more the base rule will link to others, ensure free indexes exists for
|
||||||
|
// the links.
|
||||||
|
if (numDrivers > 0 && freeSwitchRuleIndexes.size() < numDrivers-1) // -1 because the first switch rule holds the first driver.
|
||||||
{
|
{
|
||||||
DEBUG(PRLog("Not enough free switch rules: %d available, need %d\n", freeSwitchRules.size(), numDrivers));
|
DEBUG(PRLog("Not enough free switch rule indexes: %d available, need %d\n", freeSwitchRuleIndexes.size(), numDrivers));
|
||||||
return kPRFailure;
|
return kPRFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
PRResult res = kPRSuccess;
|
PRResult res = kPRSuccess;
|
||||||
uint32_t newRuleAddr = CreateSwitchRuleAddr(switchNum, eventType);
|
uint32_t newRuleIndex = CreateSwitchRuleIndex(switchNum, eventType);
|
||||||
|
|
||||||
// First we need to check the linked rule to see if the indicated switchNum has any rules that need to be freed:
|
// Because we're redefining the rule chain, we need to remove all previously existing links and return the indexes to the free list.
|
||||||
PRSwitchRuleInternal *oldRule = GetSwitchRuleByAddress(newRuleAddr);
|
PRSwitchRuleInternal *oldRule = GetSwitchRuleByIndex(newRuleIndex);
|
||||||
while (oldRule->linkActive)
|
while (oldRule->linkActive)
|
||||||
{
|
{
|
||||||
oldRule = GetSwitchRuleByAddress(oldRule->linkAddress);
|
oldRule = GetSwitchRuleByIndex(oldRule->linkIndex);
|
||||||
freeSwitchRules.push(oldRule->linkAddress);
|
freeSwitchRuleIndexes.push(oldRule->linkIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now let's setup the first actual rule:
|
// Now let's setup the first actual rule:
|
||||||
uint32_t firstRuleAddr = newRuleAddr;
|
uint16_t firstRuleIndex = newRuleIndex;
|
||||||
PRSwitchRuleInternal *newRule = GetSwitchRuleByAddress(newRuleAddr);
|
PRSwitchRuleInternal *newRule = GetSwitchRuleByIndex(newRuleIndex);
|
||||||
if (newRule->eventType != eventType)
|
if (newRule->eventType != eventType)
|
||||||
DEBUG(PRLog("Unexpected state: switch rule at 0x%x has event type 0x%x (expected 0x%x).\n", newRuleAddr, newRule->eventType, eventType));
|
DEBUG(PRLog("Unexpected state: switch rule at 0x%x has event type 0x%x (expected 0x%x).\n", newRuleIndex, newRule->eventType, eventType));
|
||||||
newRule->notifyHost = rule->notifyHost;
|
newRule->notifyHost = rule->notifyHost;
|
||||||
newRule->changeOutput = false;
|
newRule->changeOutput = false;
|
||||||
newRule->linkActive = false;
|
newRule->linkActive = false;
|
||||||
|
|
||||||
|
// Process each driver who's state should change in response to the switch event.
|
||||||
|
if (numDrivers > 0)
|
||||||
|
{
|
||||||
while (numDrivers > 0)
|
while (numDrivers > 0)
|
||||||
{
|
{
|
||||||
newRule->changeOutput = true;
|
newRule->changeOutput = true;
|
||||||
@@ -256,13 +262,13 @@ PRResult PRDevice::SwitchesUpdateRule(uint8_t switchNum, PREventType eventType,
|
|||||||
if (numDrivers > 1)
|
if (numDrivers > 1)
|
||||||
{
|
{
|
||||||
newRule->linkActive = true;
|
newRule->linkActive = true;
|
||||||
newRule->linkAddress = freeSwitchRules.front();
|
newRule->linkIndex = freeSwitchRuleIndexes.front();
|
||||||
freeSwitchRules.pop();
|
freeSwitchRuleIndexes.pop();
|
||||||
|
|
||||||
CreateSwitchesUpdateRulesBurst(burst, newRule);
|
CreateSwitchesUpdateRulesBurst(burst, newRule);
|
||||||
|
|
||||||
// Prepare for the next rule:
|
// Prepare for the next rule:
|
||||||
newRule = GetSwitchRuleByAddress(newRule->linkAddress);
|
newRule = GetSwitchRuleByIndex(newRule->linkIndex);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -270,12 +276,13 @@ PRResult PRDevice::SwitchesUpdateRule(uint8_t switchNum, PREventType eventType,
|
|||||||
CreateSwitchesUpdateRulesBurst(burst, newRule);
|
CreateSwitchesUpdateRulesBurst(burst, newRule);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write the actual rule:
|
DEBUG(PRLog("Rule Words: %x %x %x %x\n", burst[0],burst[1],burst[2],burst[3]));
|
||||||
|
// Write the rule:
|
||||||
res = WriteData(burst, burstSize);
|
res = WriteData(burst, burstSize);
|
||||||
if (res != kPRSuccess)
|
if (res != kPRSuccess)
|
||||||
{
|
{
|
||||||
DEBUG(PRLog("Error while writing switch update, attempting to revert switch rule to a safe state..."));
|
DEBUG(PRLog("Error while writing switch update, attempting to revert switch rule to a safe state..."));
|
||||||
newRule = GetSwitchRuleByAddress(firstRuleAddr);
|
newRule = GetSwitchRuleByIndex(firstRuleIndex);
|
||||||
newRule->changeOutput = false;
|
newRule->changeOutput = false;
|
||||||
newRule->linkActive = false;
|
newRule->linkActive = false;
|
||||||
CreateSwitchesUpdateRulesBurst(burst, newRule);
|
CreateSwitchesUpdateRulesBurst(burst, newRule);
|
||||||
@@ -289,34 +296,43 @@ PRResult PRDevice::SwitchesUpdateRule(uint8_t switchNum, PREventType eventType,
|
|||||||
linkedDrivers++;
|
linkedDrivers++;
|
||||||
numDrivers--;
|
numDrivers--;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CreateSwitchesUpdateRulesBurst(burst, newRule);
|
||||||
|
DEBUG(PRLog("Rule Words: %x %x %x %x\n", burst[0],burst[1],burst[2],burst[3]));
|
||||||
|
|
||||||
|
// Write the rule:
|
||||||
|
res = WriteData(burst, burstSize);
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t PRDevice::DMDUpdateGlobalConfig(PRDMDGlobalConfig *dmdGlobalConfig)
|
int32_t PRDevice::DMDUpdateConfig(PRDMDConfig *dmdConfig)
|
||||||
{
|
{
|
||||||
uint32_t rc;
|
uint32_t rc;
|
||||||
uint32_t burst[10];
|
const int burstWords = 7;
|
||||||
|
uint32_t burst[burstWords];
|
||||||
|
|
||||||
CreateDMDUpdateGlobalConfigBurst(burst, dmdGlobalConfig);
|
this->dmdConfig = *dmdConfig;
|
||||||
|
CreateDMDUpdateConfigBurst(burst, dmdConfig);
|
||||||
|
|
||||||
DEBUG(PRLog("DMD config packet: "));
|
DEBUG(PRLog("Configuring DMD"));
|
||||||
for (int i=0; i<10; i++) {
|
DEBUG(PRLog("Words: %x %x %x %x %x %x %x\n",burst[0],burst[1],burst[2],burst[3],
|
||||||
DEBUG(PRLog("%d ", burst[i]));
|
burst[4],burst[5],burst[6]));
|
||||||
}
|
|
||||||
DEBUG(PRLog("\n"));
|
|
||||||
|
|
||||||
rc = WriteData(burst, 9);
|
rc = WriteData(burst, burstWords);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
PRResult PRDevice::DMDDraw(uint8_t * dots, uint16_t columns, uint8_t rows, uint8_t numSubFrames)
|
PRResult PRDevice::DMDDraw(uint8_t * dots)
|
||||||
{
|
{
|
||||||
int32_t k; //i,x,y,j,k,m;
|
int32_t k; //i,x,y,j,k,m;
|
||||||
//uint8_t color;
|
//uint8_t color;
|
||||||
uint16_t words_per_sub_frame = (columns*rows) / 32;
|
uint16_t words_per_sub_frame = (dmdConfig.numColumns*dmdConfig.numRows) / 32;
|
||||||
uint16_t words_per_frame = words_per_sub_frame * numSubFrames;
|
uint16_t words_per_frame = words_per_sub_frame * dmdConfig.numSubFrames;
|
||||||
uint32_t dmd_command_buffer[1024];
|
uint32_t dmd_command_buffer[1024];
|
||||||
uint32_t * p_dmd_frame_buffer_words;
|
uint32_t * p_dmd_frame_buffer_words;
|
||||||
|
|
||||||
|
|||||||
@@ -139,23 +139,30 @@ int32_t CreateWatchdogConfigBurst ( uint32_t * burst, bool_t watchdogExpired,
|
|||||||
return kPRSuccess;
|
return kPRSuccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CreateSwitchRuleAddr(uint8_t switchNum, PREventType eventType)
|
int16_t CreateSwitchRuleIndex(uint8_t switchNum, PREventType eventType)
|
||||||
{
|
{
|
||||||
uint32_t debounce = (eventType == kPREventTypeSwitchOpenDebounced) || (eventType == kPREventTypeSwitchClosedDebounced) ? 1 : 0;
|
uint32_t debounce = (eventType == kPREventTypeSwitchOpenDebounced) || (eventType == kPREventTypeSwitchClosedDebounced) ? 1 : 0;
|
||||||
uint32_t state = (eventType == kPREventTypeSwitchOpenDebounced) || (eventType == kPREventTypeSwitchOpenNondebounced) ? 1 : 0;
|
uint32_t state = (eventType == kPREventTypeSwitchOpenDebounced) || (eventType == kPREventTypeSwitchOpenNondebounced) ? 1 : 0;
|
||||||
|
|
||||||
uint32_t addr = ((debounce << P_ROC_SWITCH_RULE_ADDR_DEBOUNCE_SHIFT) |
|
uint32_t index = ((debounce << P_ROC_SWITCH_RULE_NUM_DEBOUNCE_SHIFT) |
|
||||||
(state << P_ROC_SWITCH_RULE_ADDR_STATE_SHIFT) |
|
(state << P_ROC_SWITCH_RULE_NUM_STATE_SHIFT) |
|
||||||
(switchNum << P_ROC_SWITCH_RULE_ADDR_SWITCH_NUM_SHIFT) );
|
(switchNum << P_ROC_SWITCH_RULE_NUM_SWITCH_NUM_SHIFT) );
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t CreateSwitchRuleAddr(uint8_t switchNum, PREventType eventType)
|
||||||
|
{
|
||||||
|
uint16_t number = CreateSwitchRuleIndex( switchNum, eventType );
|
||||||
|
uint32_t addr = number << P_ROC_SWITCH_RULE_NUM_TO_ADDR_SHIFT;
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ParseSwitchAddress(uint32_t addr, uint8_t *switchNum, PREventType *eventType)
|
void ParseSwitchRuleIndex(uint16_t index, uint8_t *switchNum, PREventType *eventType)
|
||||||
{
|
{
|
||||||
*switchNum = (addr >> P_ROC_SWITCH_RULE_ADDR_SWITCH_NUM_SHIFT) & 0xff;
|
*switchNum = (index >> P_ROC_SWITCH_RULE_NUM_SWITCH_NUM_SHIFT) & 0xff;
|
||||||
|
|
||||||
bool open = ((addr >> P_ROC_SWITCH_RULE_ADDR_STATE_SHIFT) & 0x1) == 0x1;
|
bool open = ((index >> P_ROC_SWITCH_RULE_NUM_STATE_SHIFT) & 0x1) == 0x1;
|
||||||
bool debounce = ((addr >> P_ROC_SWITCH_RULE_ADDR_DEBOUNCE_SHIFT) & 0x1) == 0x1;
|
bool debounce = ((index >> P_ROC_SWITCH_RULE_NUM_DEBOUNCE_SHIFT) & 0x1) == 0x1;
|
||||||
if (open)
|
if (open)
|
||||||
*eventType = debounce ? kPREventTypeSwitchOpenDebounced : kPREventTypeSwitchOpenNondebounced;
|
*eventType = debounce ? kPREventTypeSwitchOpenDebounced : kPREventTypeSwitchOpenNondebounced;
|
||||||
else
|
else
|
||||||
@@ -175,23 +182,29 @@ int32_t CreateSwitchesUpdateRulesBurst ( uint32_t * burst, PRSwitchRuleInternal
|
|||||||
burst[3] = (rule_record->changeOutput << P_ROC_SWITCH_RULE_CHANGE_OUTPUT_SHIFT) |
|
burst[3] = (rule_record->changeOutput << P_ROC_SWITCH_RULE_CHANGE_OUTPUT_SHIFT) |
|
||||||
(rule_record->driver.driverNum << P_ROC_SWITCH_RULE_DRIVER_NUM_SHIFT) |
|
(rule_record->driver.driverNum << P_ROC_SWITCH_RULE_DRIVER_NUM_SHIFT) |
|
||||||
(rule_record->linkActive << P_ROC_SWITCH_RULE_LINK_ACTIVE_SHIFT) |
|
(rule_record->linkActive << P_ROC_SWITCH_RULE_LINK_ACTIVE_SHIFT) |
|
||||||
(rule_record->linkAddress << P_ROC_SWITCH_RULE_LINK_ADDRESS_SHIFT) |
|
(rule_record->linkIndex << P_ROC_SWITCH_RULE_LINK_ADDRESS_SHIFT) |
|
||||||
(rule_record->notifyHost << P_ROC_SWITCH_RULE_NOTIFY_HOST_SHIFT);
|
(rule_record->notifyHost << P_ROC_SWITCH_RULE_NOTIFY_HOST_SHIFT);
|
||||||
return kPRSuccess;
|
return kPRSuccess;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t CreateDMDUpdateGlobalConfigBurst ( uint32_t * burst, PRDMDConfig *dmd_config)
|
int32_t CreateDMDUpdateConfigBurst ( uint32_t * burst, PRDMDConfig *dmd_config)
|
||||||
{
|
{
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
|
|
||||||
addr = 8;
|
addr = 0;
|
||||||
burst[0] = CreateBurstCommand (P_ROC_BUS_DMD_SELECT, addr, 8 );
|
burst[0] = CreateBurstCommand (P_ROC_BUS_DMD_SELECT, addr, 1 );
|
||||||
|
burst[1] = (1 << P_ROC_DMD_ENABLE_SHIFT) |
|
||||||
|
(dmd_config->numSubFrames << P_ROC_DMD_NUM_SUB_FRAMES_SHIFT) |
|
||||||
|
(dmd_config->numRows << P_ROC_DMD_NUM_ROWS_SHIFT) |
|
||||||
|
(dmd_config->numColumns << P_ROC_DMD_NUM_COLUMNS_SHIFT);
|
||||||
|
|
||||||
for (i=0; i<8; i++) {
|
addr = 8;
|
||||||
burst[i+1] = 0;
|
burst[2] = CreateBurstCommand (P_ROC_BUS_DMD_SELECT, addr, 4 );
|
||||||
burst[i+1] = (dmd_config->rclkLowCycles[i] << P_ROC_DMD_RCLK_LOW_CYCLES_SHIFT) |
|
|
||||||
|
for (i=0; i<4; i++) {
|
||||||
|
burst[i+3] = (dmd_config->rclkLowCycles[i] << P_ROC_DMD_RCLK_LOW_CYCLES_SHIFT) |
|
||||||
(dmd_config->latchHighCycles[i] << P_ROC_DMD_LATCH_HIGH_CYCLES_SHIFT) |
|
(dmd_config->latchHighCycles[i] << P_ROC_DMD_LATCH_HIGH_CYCLES_SHIFT) |
|
||||||
(dmd_config->deHighCycles[i] << P_ROC_DMD_DE_HIGH_CYCLES_SHIFT) |
|
(dmd_config->deHighCycles[i] << P_ROC_DMD_DE_HIGH_CYCLES_SHIFT) |
|
||||||
(dmd_config->dotclkHalfPeriod[i] << P_ROC_DMD_DOTCLK_HALF_PERIOD_SHIFT);
|
(dmd_config->dotclkHalfPeriod[i] << P_ROC_DMD_DOTCLK_HALF_PERIOD_SHIFT);
|
||||||
|
|||||||
@@ -187,12 +187,12 @@ PR_EXPORT PRResult PRSwitchesUpdateRule(PRHandle handle, uint8_t switchNum, PREv
|
|||||||
return handleAsDevice->SwitchesUpdateRule(switchNum, eventType, rule, linkedDrivers, numDrivers);
|
return handleAsDevice->SwitchesUpdateRule(switchNum, eventType, rule, linkedDrivers, numDrivers);
|
||||||
}
|
}
|
||||||
|
|
||||||
PR_EXPORT int32_t PRDMDUpdateGlobalConfig(PRHandle handle, PRDMDGlobalConfig *dmdGlobalConfig)
|
PR_EXPORT int32_t PRDMDUpdateConfig(PRHandle handle, PRDMDConfig *dmdConfig)
|
||||||
{
|
{
|
||||||
return handleAsDevice->DMDUpdateGlobalConfig(dmdGlobalConfig);
|
return handleAsDevice->DMDUpdateConfig(dmdConfig);
|
||||||
}
|
}
|
||||||
PR_EXPORT PRResult PRDMDDraw(PRHandle handle, uint8_t * dots, uint16_t columns, uint8_t rows, uint8_t numSubFrames)
|
PR_EXPORT PRResult PRDMDDraw(PRHandle handle, uint8_t * dots)
|
||||||
{
|
{
|
||||||
return handleAsDevice->DMDDraw(dots, columns, rows, numSubFrames);
|
return handleAsDevice->DMDDraw(dots);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user