After posting our previous issue to reddit i finally had time to tinker with the frankenstein (shall we call it FrankenKiss?). This time we tackle the DVD reader.

After the old IDE HDD gave up, I connected the IDE-to-USB adapter to the DVD reader, plugged the power cable, and it got recognized by debian/osmc without any hassle. Osmc sees the dvd or cd as the right thing (e.g. dvd with files, or standard video dvd, and so on) and lets you play media from it.

I said recognized but it turns out there is no physical button directly attached to the eject mechanism of the reader, so to operate the tray I had to manually input eject on the command line. It worked, but it was inconvenient and my dad could not do this on its own.

I tried a workaround on this, by forcing the visibility of the “Disc” menu on osmc’s skin, but it was an ugly hack and I will not discuss it here…

I instead focused on the front panel: the KiSS has a 8 buttons, which used to work to eject the disk, play, change tracks, etcetera. These buttons are connected to a board, which in turns exposes whats looks like a serial cable. The cable was connected to the main board of the original KiSS so the kind of connection could be anything: there were not enough wires for them to be one per button, and the protocol that the board uses could be an I2C or a proprietary protocol. I had no time for that :)

A closer inspection of the eject button reveals that its pins are protruding from the inside panel as shown in this animation:

A quick check with a multimeter confirm my hopes: pressing the button closes the circuit. Time for some GPIO i guess!

First, some setup for my osmc box: we need to install GPIO support for python.

$ sudo apt install build-essential python-dev

and also

$ sudo pip install rpi.gpio

Then I followed this tutorial http://razzpisampler.oreilly.com/ch07.html for soldering and initial code.

As always, my soldering technique is far from good, but I managed to do a decent contact and that’s what I was looking for.

After that, I followed the tutorial to see if the whole thing could work. So I coded the example:

import RPi.GPIO as GPIO
import time

GPIO.setmode(GPIO.BCM)

GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:
    input_state = GPIO.input(18)
    if input_state == False:
        print('Button Pressed')
        time.sleep(0.2)

And launched:

So it works! I tinkered a bit and added a call to the eject linux command inside the loop.

#!/usr/bin/env python2.7 
import RPi.GPIO as GPIO
import time
import os

GPIO.setmode(GPIO.BCM)

GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)

while True:
    input_state = GPIO.input(18)
    if input_state == False:
        print('Button Pressed, ejecting cdrom')
        os.system("eject -T")
        time.sleep(0.2)

And this time it actually ejected the dvd drive!

This code does its job but it is constantly polling for the button status and I wanted a better solution.

So I coded an interrupt-based solution following the tutorial from https://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio-part-3 with some tweaks here and there:

#!/usr/bin/env python2.7 
import RPi.GPIO as GPIO
import time
import os

def toggledvd(channel):
    print('Button Pressed, ejecting cdrom')
    os.system("eject -T")

GPIO.setmode(GPIO.BCM)
GPIO.setup(18, GPIO.IN, pull_up_down=GPIO.PUD_UP)
print("setting callback")
GPIO.add_event_detect(18, GPIO.RISING, callback=toggledvd, bouncetime=5000)

try:
    while True:
        print("waiting 10 seconds just so we do not die")
        time.sleep(10)
except KeyboardInterrupt:
    GPIO.cleanup()       # clean up GPIO on CTRL+C exit
GPIO.cleanup()           # clean up GPIO on normal exit

print("goodbye")

It still has a busy loop but at least it is not constantly polling the GPIO.

Then I registered the script as a systemd service by writing a service descriptor:

osmc@osmc:~/cdeject$ cat /lib/systemd/system/cdejector.service
[Unit]                                                        
Description = GPIO DVD ejector                                
Wants=network-online.target                                   
After=network-online.target                                   
                                                              
[Service]                                                     
Type = idle                                                   
ExecStart = /opt/cdejector/cdejector.py                       
                                                              
[Install]                                                     
WantedBy = multi-user.target                                  

And after that I registered the service as a boot service:

sudo systemctl daemon-reload
sudo systemctl start cdejector
sudo systemctl enable cdejector

This way I can eject and close the dvd tray with the button outside the FrankenKiss.

Kodi is also smart enough to lock the dvd eject if any media is playing, so no further coding is necessary here.

Next up: LCD panel, back side ports, more buttons?