void printBuffer(volatile uint16_t *data, int start, int size) { int i; for (i = start; i < start + size; i++) { printChar('\t'); printInt32(data[i]); } printChar('\n'); }
static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O) { SStream_concat0(O, "["); printInt32(O, (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum))); SStream_concat0(O, "]"); if (MI->csh->detail) { MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].vector_index = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)); } }
// Shows a ScheduleParam void Macro_showScheduleParam( ScheduleParam *param, uint8_t analog ) { // Analog if ( analog ) { printInt8( param->analog ); } // Everything else else { Macro_showScheduleType( param->state ); } // Time print(":"); printInt32( param->time.ms ); print("."); printInt32( param->time.ticks ); }
void cliFunc_usbInitTime( char* args ) { // Calculate overall USB initialization time // XXX A protocol analyzer will be more accurate, however, this is built-in and easier to collect data print(NL); info_msg("USB Init Time: "); printInt32( USBInit_TimeEnd - USBInit_TimeStart ); print(" ms - "); printInt16( USBInit_Ticks ); print(" ticks"); }
void blockMatch(volatile uint16_t *now, volatile uint16_t *last, int size, int search_radius, int block_size, result_t *result) { /* tmp */ int min, diff; int s, x; int b = 0; int i = 0; /* output */ int aktShift = 0; int gshift_a[2*MAX_SEARCH_RADIUS+1] = {0}; int* gshift = &gshift_a[MAX_SEARCH_RADIUS]; /* calculate sector shift */ while (b <= size) { aktShift = 0; min = INT_MAX; for (s = -search_radius; s <= search_radius; ++s) { if ((b + s >= 0) && (b + block_size + s <= size)) { diff = 0; for (x = b; x < b + block_size; ++x) { diff += pow(now[x] - last[x + s], 2); } if (config.s.oflow_algo & DEBUG) { printInt32(diff); printChar('\t'); } if (diff < min) { min = diff; aktShift = s; } gshift[s] += diff; } } result->vector[i++] = aktShift; b += block_size; } /* calculate global shift */ min = INT_MAX; for (s = -search_radius; s <= search_radius; ++s) { if (gshift[s] < min) { min = gshift[s]; aktShift = s; } } result->global = aktShift;// / size; result->size = size; }
// Update external current (mA) // Triggers power change event void Output_update_external_current( unsigned int current ) { // Only signal if changed if ( current == Output_ExtCurrent_Available ) return; // Update external current Output_ExtCurrent_Available = current; unsigned int total_current = Output_current_available(); info_msg("External Available Current Changed. Total Available: "); printInt32( total_current ); print(" mA" NL); // Send new total current to the Scan Modules Scan_currentChange( Output_current_available() ); }
void cliFunc_ledFPS( char* args ) { print( NL ); // No \r\n by default after the command is entered char* curArgs; char* arg1Ptr; char* arg2Ptr = args; // Process speed argument if given curArgs = arg2Ptr; CLI_argumentIsolation( curArgs, &arg1Ptr, &arg2Ptr ); // Just toggling FPS display if ( *arg1Ptr == '\0' ) { info_msg("FPS Toggle"); LED_displayFPS = !LED_displayFPS; return; } // Check if f argument was given switch ( *arg1Ptr ) { case 'r': // Reset framerate case 'R': LED_framerate = ISSI_FrameRate_ms_define; break; default: // Convert to a number LED_framerate = numToInt( arg1Ptr ); break; } // Show result info_msg("Setting framerate to: "); printInt32( LED_framerate ); print("ms"); }
inline void LED_scan() { // Latency measurement start Latency_start_time( ledLatencyResource ); // Check for current change event if ( LED_currentEvent ) { // Turn LEDs off in low power mode if ( LED_currentEvent < 150 ) { LED_enable_current = 0; // Pause animations and clear display Pixel_setAnimationControl( AnimationControl_WipePause ); } else { LED_enable_current = 1; // Start animations Pixel_setAnimationControl( AnimationControl_Forward ); } LED_currentEvent = 0; } // Check if an LED_pause is set // Some ISSI operations need a clear buffer, but still have the chip running if ( LED_pause ) goto led_finish_scan; // Check enable state if ( LED_enable && LED_enable_current ) { // Disable Hardware shutdown of ISSI chips (pull high) GPIO_Ctrl( hardware_shutdown_pin, GPIO_Type_DriveHigh, GPIO_Config_Pullup ); } // Only write pages to I2C if chip is enabled (i.e. Hardware shutdown is disabled) else { // Enable hardware shutdown GPIO_Ctrl( hardware_shutdown_pin, GPIO_Type_DriveLow, GPIO_Config_Pullup ); goto led_finish_scan; } // Check if any I2C buses have errored // Reset the buses and restart the Frame State if ( i2c_error() ) { i2c_reset(); Pixel_FrameState = FrameState_Update; } // Only start if we haven't already // And if we've finished updating the buffers if ( Pixel_FrameState == FrameState_Sending ) goto led_finish_scan; // Only send frame to ISSI chip if buffers are ready if ( Pixel_FrameState != FrameState_Ready ) goto led_finish_scan; // Adjust frame rate (i.e. delay and do something else for a bit) Time duration = Time_duration( LED_timePrev ); if ( duration.ms < LED_framerate ) goto led_finish_scan; // FPS Display if ( LED_displayFPS ) { // Show frame calculation dbug_msg("1frame/"); printInt32( Time_ms( duration ) ); print("ms + "); printInt32( duration.ticks ); print(" ticks"); // Check if we're not meeting frame rate if ( duration.ms > LED_framerate ) { print(" - Could not meet framerate: "); printInt32( LED_framerate ); } print( NL ); } // Emulated brightness control // Lower brightness by LED_brightness #if ISSI_Chip_31FL3731_define == 1 for ( uint8_t chip = 0; chip < ISSI_Chips_define; chip++ ) { for ( uint8_t ch = 0; ch < LED_EnableBufferLength; ch++ ) { LED_pageBuffer_brightness[ chip ].ledctrl[ ch ] = LED_pageBuffer[ chip ].ledctrl[ ch ]; } for ( uint8_t ch = 0; ch < LED_BufferLength; ch++ ) { // Don't modify is 0 if ( LED_pageBuffer[ chip ].buffer[ ch ] == 0 || LED_brightness == 0 ) { LED_pageBuffer_brightness[ chip ].buffer[ ch ] = 0; continue; } // XXX (HaaTa) Yes, this is a bit slow, but it's pretty accurate LED_pageBuffer_brightness[ chip ].buffer[ ch ] = (LED_pageBuffer[ chip ].buffer[ ch ] * LED_brightness) / 0xFF; } } #endif // Update frame start time LED_timePrev = Time_now(); // Set the page of all the ISSI chips // This way we can easily link the buffers to send the brightnesses in the background for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { uint8_t bus = LED_ChannelMapping[ ch ].bus; // Page Setup LED_setupPage( bus, LED_ChannelMapping[ ch ].addr, ISSI_LEDPwmPage ); } // Send current set of buffers // Uses interrupts to send to all the ISSI chips // Pixel_FrameState will be updated when complete LED_chipSend = 0; // Start with chip 0 LED_linkedSend(); led_finish_scan: // Latency measurement end Latency_end_time( ledLatencyResource ); }
// Single strobe matrix scan // Only goes through a single strobe // This module keeps track of the next strobe to scan uint8_t Matrix_single_scan() { // Start latency measurement Latency_start_time( matrixLatencyResource ); // Read systick for event scheduling uint32_t currentTime = systick_millis_count; // Current strobe uint8_t strobe = matrixCurrentStrobe; // XXX (HaaTa) // Before strobing drain each sense line // This helps with faulty pull-up resistors (particularily with SAM4S) for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ ) { GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveSetup, Matrix_type ); #if ScanCodeMatrixInvert_define == 2 // GPIO_Config_Pulldown GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveLow, Matrix_type ); #elif ScanCodeMatrixInvert_define == 1 // GPIO_Config_Pullup GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_DriveHigh, Matrix_type ); #endif GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_ReadSetup, Matrix_type ); } // Strobe Pin GPIO_Ctrl( Matrix_cols[ strobe ], GPIO_Type_DriveHigh, Matrix_type ); // Used to allow the strobe signal to propagate, generally not required if ( strobeDelayTime > 0 ) { delay_us( strobeDelayTime ); } // Scan each of the sense pins for ( uint8_t sense = 0; sense < Matrix_rowsNum; sense++ ) { // Key position uint16_t key = Matrix_colsNum * sense + strobe; #if ScanCodeRemapping_define == 1 uint16_t key_disp = matrixScanCodeRemappingMatrix[key]; #else uint16_t key_disp = key + 1; // 1-indexed for reporting purposes #endif // Check bounds, before attempting to scan // 1-indexed as ScanCode 0 is not used if ( key_disp > MaxScanCode_KLL || key_disp == 0 ) { continue; } volatile KeyState *state = &Matrix_scanArray[ key ]; // Signal Detected // Increment count and right shift opposing count // This means there is a maximum of scan 13 cycles on a perfect off to on transition // (coming from a steady state 0xFFFF off scans) // Somewhat longer with switch bounciness // The advantage of this is that the count is ongoing and never needs to be reset // State still needs to be kept track of to deal with what to send to the Macro module // Compared against the default state value (ScanCodeMatrixInvert_define), usually 0 if ( GPIO_Ctrl( Matrix_rows[ sense ], GPIO_Type_Read, Matrix_type ) != ScanCodeMatrixInvert_define ) { // Only update if not going to wrap around if ( state->activeCount < DebounceDivThreshold ) state->activeCount += 1; state->inactiveCount >>= 1; } // Signal Not Detected else { // Only update if not going to wrap around if ( state->inactiveCount < DebounceDivThreshold ) state->inactiveCount += 1; state->activeCount >>= 1; } // Check for state change // But only if: // 1) Enough time has passed since last state change // 2) Either active or inactive count is over the debounce threshold // Update previous state state->prevState = state->curState; // Determine time since last decision uint32_t lastTransition = currentTime - state->prevDecisionTime; // Attempt state transition switch ( state->prevState ) { case KeyState_Press: case KeyState_Hold: if ( state->activeCount > state->inactiveCount ) { state->curState = KeyState_Hold; } else { // If not enough time has passed since Hold // Keep previous state if ( lastTransition < debounceExpiryTime ) { state->curState = state->prevState; Macro_keyState( key_disp, state->curState ); continue; } state->curState = KeyState_Release; } break; case KeyState_Release: case KeyState_Off: if ( state->activeCount > state->inactiveCount ) { // If not enough time has passed since Hold // Keep previous state if ( lastTransition < debounceExpiryTime ) { state->curState = state->prevState; Macro_keyState( key_disp, state->curState ); continue; } state->curState = KeyState_Press; } else { state->curState = KeyState_Off; } break; case KeyState_Invalid: default: erro_msg("Matrix scan bug!! Report me! - "); printHex( state->prevState ); print(" Col: "); printHex( strobe ); print(" Row: "); printHex( sense ); print(" Key: "); printHex( key_disp ); print( NL ); break; } // Update decision time state->prevDecisionTime = currentTime; // Send keystate to macro module Macro_keyState( key_disp, state->curState ); // Check for activity and inactivity if ( state->curState != KeyState_Off ) { matrixStateActiveCount++; } switch ( state->curState ) { case KeyState_Press: matrixStatePressCount++; break; case KeyState_Release: matrixStateReleaseCount++; break; default: break; } // Matrix Debug, only if there is a state change if ( matrixDebugMode && state->curState != state->prevState ) { // Basic debug output if ( matrixDebugMode == 1 && state->curState == KeyState_Press ) { printInt16( key_disp ); print(":"); printHex( key_disp ); print(" "); } // State transition debug output else if ( matrixDebugMode == 2 ) { printInt16( key_disp ); Matrix_keyPositionDebug( state->curState ); print(" "); } else if ( matrixDebugMode == 3 ) { print("\033[1m"); printInt16( key_disp ); print("\033[0m"); print(":"); Matrix_keyPositionDebug( Matrix_scanArray[ key ].prevState ); Matrix_keyPositionDebug( Matrix_scanArray[ key ].curState ); print(" 0x"); printHex_op( state->activeCount, 2 ); print(" 0x"); printHex_op( state->inactiveCount, 2 ); print(" "); printInt32( lastTransition ); print( NL ); } } }
int32_t i2c_send_sequence( uint8_t ch, uint16_t *sequence, uint32_t sequence_length, uint8_t *received_data, void ( *callback_fn )( void* ), void *user_data ) { int32_t result = 0; volatile I2C_Channel *channel = &( i2c_channels[ch - ISSI_I2C_FirstBus_define] ); uint8_t address; #if defined(_kinetis_) uint8_t status; volatile uint8_t *I2C_C1 = (uint8_t*)(&I2C0_C1) + i2c_offset[ch]; volatile uint8_t *I2C_S = (uint8_t*)(&I2C0_S) + i2c_offset[ch]; volatile uint8_t *I2C_D = (uint8_t*)(&I2C0_D) + i2c_offset[ch]; #elif defined(_sam_) Twi *twi_dev = twi_devs[ch]; #endif if ( channel->status == I2C_BUSY ) { return -1; } // Check if there are back-to-back errors // in succession if ( channel->last_error > 5 ) { warn_msg("I2C Bus Error: "); printInt8( ch ); print(" errors: "); printInt32( channel->error_count ); print( NL ); } // Debug /* for ( uint8_t c = 0; c < sequence_length; c++ ) { printHex( sequence[c] ); print(" "); } print(NL); */ channel->sequence = sequence; channel->sequence_end = sequence + sequence_length; channel->received_data = received_data; channel->status = I2C_BUSY; channel->txrx = I2C_WRITING; channel->callback_fn = callback_fn; channel->user_data = user_data; // reads_ahead does not need to be initialized #if defined(_kinetis_) // Acknowledge the interrupt request, just in case *I2C_S |= I2C_S_IICIF; *I2C_C1 = ( I2C_C1_IICEN | I2C_C1_IICIE ); // Generate a start condition and prepare for transmitting. *I2C_C1 |= ( I2C_C1_MST | I2C_C1_TX ); status = *I2C_S; if ( status & I2C_S_ARBL ) { warn_print("Arbitration lost"); result = -1; goto i2c_send_sequence_cleanup; } // Write the first (address) byte. address = *channel->sequence++; *I2C_D = address; // Everything is OK. return result; i2c_send_sequence_cleanup: // Record error, and reset last error counter channel->error_count++; channel->last_error++; // Generate STOP and disable further interrupts. *I2C_C1 &= ~( I2C_C1_IICIE | I2C_C1_MST | I2C_C1_TX ); channel->status = I2C_ERROR; #elif defined(_sam_) // Convert 8 bit address to 7bit + RW address = *channel->sequence++; //print("Address: "); //printHex( address ); //print( NL ); uint8_t mread = address & 1; address >>= 1; // Set slave address twi_dev->TWI_MMR = TWI_MMR_DADR(address) | (mread ? TWI_MMR_MREAD : 0); // Enable interrupts twi_dev->TWI_IER = TWI_IER_RXRDY | TWI_IER_TXRDY | TWI_IER_TXCOMP | TWI_IER_ARBLST; //twi_dev->TWI_IDR = 0xFFFFFFFF; // Generate a start condition twi_dev->TWI_CR |= TWI_CR_START; // Fire off the first read or write. // The first (address) byte is automatically trasmitted before any data // Arbitration errors will be handled in the isr i2c_isr(ch); // Everything is OK. return result; #endif return result; }
inline void LED_scan() { // Latency measurement start Latency_start_time( ledLatencyResource ); // Check for current change event if ( LED_currentEvent ) { // Turn LEDs off in low power mode if ( LED_currentEvent < 150 ) { LED_enable = 0; // Pause animations and clear display Pixel_setAnimationControl( AnimationControl_WipePause ); } else { LED_enable = 1; // Start animations Pixel_setAnimationControl( AnimationControl_Forward ); } LED_currentEvent = 0; } // Check if an LED_pause is set // Some ISSI operations need a clear buffer, but still have the chip running if ( LED_pause ) goto led_finish_scan; // Check enable state if ( LED_enable ) { // Disable Hardware shutdown of ISSI chips (pull high) GPIOB_PSOR |= (1<<16); } // Only write pages to I2C if chip is enabled (i.e. Hardware shutdown is disabled) else { // Enable hardware shutdown GPIOB_PCOR |= (1<<16); goto led_finish_scan; } // Only start if we haven't already // And if we've finished updating the buffers if ( Pixel_FrameState == FrameState_Sending ) goto led_finish_scan; // Only send frame to ISSI chip if buffers are ready if ( Pixel_FrameState != FrameState_Ready ) goto led_finish_scan; // Adjust frame rate (i.e. delay and do something else for a bit) Time duration = Time_duration( LED_timePrev ); if ( duration.ms < LED_framerate ) goto led_finish_scan; // FPS Display if ( LED_displayFPS ) { // Show frame calculation dbug_msg("1frame/"); printInt32( Time_ms( duration ) ); print("ms + "); printInt32( duration.ticks ); print(" ticks"); // Check if we're not meeting frame rate if ( duration.ms > LED_framerate ) { print(" - Could not meet framerate: "); printInt32( LED_framerate ); } print( NL ); } // Emulated brightness control // Lower brightness by LED_brightness #if ISSI_Chip_31FL3731_define == 1 uint8_t inverse_brightness = 0xFF - LED_brightness; for ( uint8_t chip = 0; chip < ISSI_Chips_define; chip++ ) { for ( uint8_t ch = 0; ch < LED_BufferLength; ch++ ) { // Don't modify is 0 if ( LED_pageBuffer[ chip ].buffer[ ch ] == 0 ) { LED_pageBuffer_brightness[ chip ].buffer[ ch ] = 0; continue; } LED_pageBuffer_brightness[ chip ].buffer[ ch ] = LED_pageBuffer[ chip ].buffer[ ch ] - inverse_brightness < 0 ? 0x0 : LED_pageBuffer[ chip ].buffer[ ch ] - inverse_brightness; } } #endif // Update frame start time LED_timePrev = Time_now(); // Set the page of all the ISSI chips // This way we can easily link the buffers to send the brightnesses in the background for ( uint8_t ch = 0; ch < ISSI_Chips_define; ch++ ) { uint8_t bus = LED_ChannelMapping[ ch ].bus; // Page Setup LED_setupPage( bus, LED_ChannelMapping[ ch ].addr, ISSI_LEDPwmPage ); #if ISSI_Chip_31FL3731_define == 1 || ISSI_Chip_31FL3732_define == 1 // Reset LED enable mask // XXX At high speeds, the IS31FL3732 seems to have random bit flips // To get around this, just re-set the enable mask before each send // XXX Might be sufficient to do this every N frames though while ( i2c_send( bus, (uint16_t*)&LED_ledEnableMask[ ch ], sizeof( LED_EnableBuffer ) / 2 ) == -1 ) delay_us( ISSI_SendDelay ); #endif } // Send current set of buffers // Uses interrupts to send to all the ISSI chips // Pixel_FrameState will be updated when complete LED_chipSend = 0; // Start with chip 0 LED_linkedSend(); led_finish_scan: // Latency measurement end Latency_end_time( ledLatencyResource ); }