Skip to content

Commit

Permalink
add support for usage without oled display
Browse files Browse the repository at this point in the history
  • Loading branch information
vergoh committed Jan 5, 2024
1 parent 4f6a168 commit be88b77
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 17 deletions.
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ MicroPython implementation for ESP32 using a small OLED display to show the "cur
- "currently playing" information with progress bar
- artist + track
- show/podcast + episode
- playback control
- playback control (optional)
- play / pause
- next track
- pause after current track
Expand All @@ -26,6 +26,7 @@ MicroPython implementation for ESP32 using a small OLED display to show the "cur
- ESP32 with [MicroPython](https://micropython.org/) 1.14 or later
- version 1.18 or later recommended
- SSD1306 or SSD1309 compatible 128x64 pixel OLED display in i2c mode
- optional if buttons are only needed / used
- verified
- [0.96" SSD1306](https://www.google.com/search?q=128x64+oled+i2c+0.96+ssd1306)
- [2.42" SSD1309](https://www.google.com/search?q=128x64+oled+i2c+2.42+ssd1309) (recommended)
Expand All @@ -36,6 +37,8 @@ MicroPython implementation for ESP32 using a small OLED display to show the "cur
- wlan connectivity
- Spotify account
- Premium needed for playback control
- control buttons (optional)
- buzzer (optional)

See also beginning of [Case.md](Case.md) for a full list of needed components for building the cased solution shown above.

Expand Down
1 change: 1 addition & 0 deletions src/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"use_led": false,
"setup_network": true,
"enable_webrepl": false,
"use_display": true,
"show_progress_ticks": true,
"contrast": 127,
"low_contrast_mode": false,
Expand Down
34 changes: 28 additions & 6 deletions src/oled.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,25 @@

class OLED:

def __init__(self, scl_pin = 22, sda_pin = 21, contrast = 127):
self.i2c = SoftI2C(scl = Pin(scl_pin), sda = Pin(sda_pin))
def __init__(self, scl_pin = 22, sda_pin = 21, contrast = 127, enable = True):
self.oled_width = 128
self.oled_height = 64
self.standby_x = 0
self.standby_y = 0
self.status_dot = False
self.status_dot_size = 1

if enable is False:
self.enabled = False
return

self.i2c = SoftI2C(scl = Pin(scl_pin), sda = Pin(sda_pin))
self.oled = ssd1306.SSD1306_I2C(self.oled_width, self.oled_height, self.i2c)
self.oled.fill(0)
self.oled.contrast(contrast)
self.oled.text(" ... ", 4, 30)
self.oled.show()
self.standby_x = 0
self.standby_y = 0
self.status_dot = False
self.status_dot_size = 1
self.enabled = True

def _replace_chars(self, text):
result = []
Expand Down Expand Up @@ -52,6 +58,13 @@ def _replace_chars(self, text):
return ''.join(result)

def show(self, artist, title, progress = None, ticks = True, separator = True):
if not self.enabled:
if progress is not None:
print("Display: {} - {} ({}%)".format(artist.strip(), title.strip(), progress))
else:
print("Display: {} - {}".format(artist.strip(), title.strip()))
return

self.oled.fill(0)

if self.status_dot:
Expand Down Expand Up @@ -115,6 +128,9 @@ def show(self, artist, title, progress = None, ticks = True, separator = True):
self.oled.show()

def standby(self):
if not self.enabled:
return

self.oled.fill(0)
self.oled.pixel(self.standby_x, self.standby_y, 1)
self.oled.show()
Expand All @@ -129,6 +145,9 @@ def standby(self):
self.standby_y -= 1

def _corner_dot(self, fill, size = 1):
if not self.enabled:
return

for x in range(self.oled_width - size, self.oled_width):
for y in range(size):
self.oled.pixel(x, y, fill)
Expand All @@ -149,5 +168,8 @@ def disable_status_dot(self):
self.status_dot = False

def clear(self):
if not self.enabled:
return

self.oled.fill(0)
self.oled.show()
36 changes: 26 additions & 10 deletions src/spotify.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,12 @@ def __init__(self):
time.sleep_ms(100)
self.led.value(0)

self.oled = oled.OLED(scl_pin = self.config['pins']['scl'], sda_pin = self.config['pins']['sda'], contrast = self.config['contrast'])
if self.config['low_contrast_mode']:
self.oled.oled.precharge(0x22)
if self.config['use_display']:
self.oled = oled.OLED(scl_pin = self.config['pins']['scl'], sda_pin = self.config['pins']['sda'], contrast = self.config['contrast'])
if self.config['low_contrast_mode']:
self.oled.oled.precharge(0x22)
else:
self.oled = oled.OLED(enable = False)
self.oled.show(_app_name, "__init__", separator = False)

self._validate_config()
Expand Down Expand Up @@ -105,7 +108,7 @@ def _set_memory_debug(self):
print("no \"memdebug\" file or directory found, memory debug output disabled")

def _validate_config(self):
boolean_entries = const("use_led,use_buzzer,setup_network,enable_webrepl,show_progress_ticks,low_contrast_mode,blank_oled_on_standby")
boolean_entries = const("use_display,use_led,use_buzzer,setup_network,enable_webrepl,show_progress_ticks,low_contrast_mode,blank_oled_on_standby")
integer_entries = const("contrast,status_poll_interval_seconds,standby_status_poll_interval_minutes,idle_standby_minutes,long_press_duration_milliseconds,api_request_dot_size,buzzer_frequency,buzzer_duty")
dict_entries = const("spotify,pins,wlan")
spotify_entries = const("client_id,client_secret")
Expand Down Expand Up @@ -143,11 +146,15 @@ def _raise_config_error(self, e):
def _wait_for_connection(self):
was_connected = self.wlan.isconnected()

if not self.config['use_display'] and not self.wlan.isconnected():
print("waiting for connection...")

while not self.wlan.isconnected():
self.oled.show(_app_name, "waiting for connection", separator = False)
time.sleep_ms(500)
self.oled.show(_app_name, "waiting for connection", separator = True)
time.sleep_ms(500)
if self.config['use_display']:
self.oled.show(_app_name, "waiting for connection", separator = False)
time.sleep_ms(500)
self.oled.show(_app_name, "waiting for connection", separator = True)
time.sleep_ms(500)

if not was_connected:
self._reset_button_presses()
Expand Down Expand Up @@ -385,6 +392,7 @@ async def _show_play_progress_for_seconds(self, api_tokens, cp, seconds):
self.oled.show("Unknown content", "")
await asyncio.sleep(seconds)
else:
show_progress = True
progress_start = time.time()
progress = None

Expand Down Expand Up @@ -417,7 +425,11 @@ async def _show_play_progress_for_seconds(self, api_tokens, cp, seconds):
playing_artist = cp['item'].get('show', {}).get('name', 'Unknown Podcast')
playing_title = cp['item'].get('name', 'Unknown Episode')

self.oled.show(playing_artist, playing_title, progress = progress, ticks = self.config['show_progress_ticks'])
if show_progress:
self.oled.show(playing_artist, playing_title, progress = progress, ticks = self.config['show_progress_ticks'])
if not self.config['use_display']:
show_progress = False

if time.time() >= progress_start + seconds:
break

Expand Down Expand Up @@ -470,6 +482,7 @@ async def _standby(self):

async def _start_standby(self, last_playing):
loop_begins = time.time()
show_progress = True

while loop_begins + (self.config['status_poll_interval_seconds'] - 1) > time.time():

Expand All @@ -479,7 +492,10 @@ async def _start_standby(self, last_playing):
if time.time() >= standby_time:
return True

self.oled.show("Spotify", "not playing", progress = progress, ticks = False)
if show_progress:
self.oled.show("Spotify", "not playing", progress = progress, ticks = False)
if not self.config['use_display']:
show_progress = False

if await self._wait_for_button_press_ms(1000):
return False
Expand Down

0 comments on commit be88b77

Please sign in to comment.