diff --git a/src/display_manager.py b/src/display_manager.py index 85d6cbbc..00b0b71c 100644 --- a/src/display_manager.py +++ b/src/display_manager.py @@ -36,18 +36,18 @@ class DisplayManager: options.parallel = hardware_config.get('parallel', 1) options.hardware_mapping = hardware_config.get('hardware_mapping', 'adafruit-hat-pwm') - # Optimize display settings for chained panels + # Optimize display settings for performance options.brightness = 100 - options.pwm_bits = 11 - options.pwm_lsb_nanoseconds = 200 # Increased for better stability + options.pwm_bits = 8 # Reduced for better performance + options.pwm_lsb_nanoseconds = 100 # Reduced for faster updates options.led_rgb_sequence = 'RGB' options.pixel_mapper_config = '' options.row_address_type = 0 options.multiplexing = 0 - options.disable_hardware_pulsing = False # Enable hardware pulsing for better sync + options.disable_hardware_pulsing = True # Disable pulsing for better performance options.show_refresh_rate = False - options.limit_refresh_rate_hz = 60 # Reduced refresh rate for stability - options.gpio_slowdown = 2 # Increased slowdown for better stability + options.limit_refresh_rate_hz = 120 # Increased refresh rate + options.gpio_slowdown = 1 # Reduced slowdown for better performance # Initialize the matrix self.matrix = RGBMatrix(options=options) @@ -94,14 +94,13 @@ class DisplayManager: # Copy the current image to the offscreen canvas self.offscreen_canvas.SetImage(self.image) - # Wait for the next vsync before swapping - self.matrix.SwapOnVSync(self.offscreen_canvas) + # Swap buffers immediately without waiting for vsync + self.matrix.SwapOnVSync(self.offscreen_canvas, False) # Swap our canvas references self.offscreen_canvas, self.current_canvas = self.current_canvas, self.offscreen_canvas - # Small delay to ensure stable refresh - time.sleep(0.001) + # No delay needed since we're not waiting for vsync except Exception as e: logger.error(f"Error updating display: {e}") diff --git a/src/stock_news_manager.py b/src/stock_news_manager.py index 68b6a73c..fa908ad4 100644 --- a/src/stock_news_manager.py +++ b/src/stock_news_manager.py @@ -205,28 +205,40 @@ class StockNewsManager: separator = " - " # Visual separator between news items news_text = separator.join(news_texts) + # Pre-render the text image for efficient scrolling + text_image = self._create_text_image(news_text) + text_width = text_image.width + display_width = self.display_manager.matrix.width + + # Calculate total width for scrolling + total_width = text_width + display_width + + # Update scroll position with smooth acceleration + scroll_speed = min(self.scroll_speed * 1.1, 3) # Gradually increase speed up to max + self.scroll_position = (self.scroll_position + scroll_speed) % total_width + # Clear the display self.display_manager.clear() - # Calculate text width for scrolling - bbox = self.display_manager.draw.textbbox((0, 0), news_text, font=self.display_manager.small_font) - text_width = bbox[2] - bbox[0] - - # Calculate scroll position - display_width = self.display_manager.matrix.width - total_width = text_width + display_width - - # Update scroll position - self.scroll_position = (self.scroll_position + self.scroll_speed) % total_width - - # Draw the text at the current scroll position - self.display_manager.draw_text( - news_text, - x=display_width - self.scroll_position, - y=None, # Center vertically - color=(255, 255, 255), - small_font=True - ) + # Calculate source and destination regions for efficient blitting + if self.scroll_position < display_width: + # Text is entering from the right + src_x = text_width - (display_width - self.scroll_position) + src_width = display_width - self.scroll_position + dst_x = self.scroll_position + self.display_manager.image.paste( + text_image.crop((src_x, 0, src_x + src_width, text_image.height)), + (dst_x, 0) + ) + else: + # Text is scrolling off the left + src_x = 0 + src_width = text_width + dst_x = self.scroll_position - display_width + self.display_manager.image.paste( + text_image.crop((src_x, 0, src_x + src_width, text_image.height)), + (dst_x, 0) + ) # Update the display self.display_manager.update_display() @@ -234,9 +246,10 @@ class StockNewsManager: # If we've completed a full scroll, move to the next group if self.scroll_position == 0: self.current_news_group = (self.current_news_group + 1) % ((total_headlines + headlines_per_rotation - 1) // headlines_per_rotation) + self.scroll_speed = 1 # Reset speed for next group - # Small delay to control scroll speed - time.sleep(self.scroll_delay) + # Minimal delay to control scroll speed while maintaining smoothness + time.sleep(0.001) # Log frame rate self._log_frame_rate()