RaspDac mini: How to use a different IR remote control

Ici on parle de Raspberry PI, Sparky, Odroid... avec des solutions comme Squeezelite, MPD, Max2Play... ainsi que leur DAC et accessoires dédiés
Messages : 5
Inscription : jeu. 30 juil. 2020 18:41

RaspDac mini: How to use a different IR remote control

Message par Atair » lun. 24 août 2020 09:36

After having successfully installed Moode 6.5.1 thanks to JeromeL's fine tuto viewtopic.php?f=12&t=2935, I wondered how I can use a different IR control.
Actually I have got the quite good sounding all-in-one stereo Caruso from T+A which is nearly 15 years old.
The speakers and the 3x50W processor controlled amp are still top. But the streaming client is now rather outdated, slow and not highres capable. So I replaced it with the RaspDac mini and use the Caruso as an actice speaker box. I must say, I am very content with this solution.

The only thing I missed is, to use the remote control to switch between my favorite radio station using the number keys. So I looked into the Audiophonic scripts provided thanks to the a.m. tuto.

Adding a second rc is quite easy:
Look into the lirc config file:

Code : Tout sélectionner

This is the place where the ir codes are mapped to keys which then a program logic can read by listening to a socket.
If you followed the a.m. tuto, the Audiophonic script which evalutates the rc keys is:

Code : Tout sélectionner

/home/pi/<some subdir>/oled/raspdac_oled_telecommand.py
These are the two places where you can make your modifications.

Luckily I found a ready made lirc conf file for the T+A rc in this database http://lirc-remotes.sourceforge.net/remotes-table.html. Otherwise you have to first create your own conf file by using the lirc ir codes record utility.

Look at the original Audiophonics lircd.conf in order to find out the key code names. Then you can rename the key code names in your own lircd.conf accordingly. For instance, I used an otherwise unused key F1 to launch the RaspDac mini menu.
When done you can just concatenate the two conf files. And then, after reboot, you can use both remotes in parallel.

Here is the code of my lircd.conf: In the part for my rc, I commented out the original keys and added below a line for the respective RaspDac key.
I did not map the Vol+/Vol- keys, because I use these to control the volume on the Caruso itself, as well as to mute the speaker. (I am running the RaspDac with its volume permanently set to 100.)

Code : Tout sélectionner

begin remote
  name RaspdacMini
  bits 8
  eps 30
  aeps 100
  header 9047 4480
  one 603 1664
  zero 603 531
  ptrail 603
  repeat 9047 2226
  pre_data_bits 16
  pre_data 0x77E1
  post_data_bits 8
  post_data 0x55
  gap 108227
  min_repeat 1
  suppress_repeat 5
  toggle_bit_mask 0x0
      begin codes
          KEY_LEFT 0x10
          KEY_RIGHT 0xE0
          KEY_UP 0xD0
          KEY_DOWN 0xB0
          KEY_ENTER 0xBA 0x20
          KEY_MENU 0x40
          KEY_PLAY 0x7A 0x20
      end codes
end remote
s config file was generated using lirc-0.8.2 with LIRC serial recceiver 
# on Beaujolais Day 2007 (Nov. 15th 2007)
# Contributed by: Lothar Wiemann (lothar.wiemann [at] arcor.de)
# Brand:        T+A
# Remote Model: F 100
# Notes: 	If building a LIRC serial receiver:
#		T+A remotes use a carrier frequency of 31.25 kHz.
#		IR-receivers with 30...33 kHz will work best (eg. Vishay TSOP 1730)
#		Std. 38 kHz receivers not recommended
#		-----------------------------------------------------------------------
#		The F100 uses a modified bi-phase code with header, start-bit, 9 data-bits, no toggle bits.
#		The HEADER is 512us pulse / 2560 us pause
#		The START bit is NOT bi-phase-coded ! It has a length of 1024us pulse / no pause (plead) 
#		The DATA bits are standard bi-phase with 512us pulse/512us pause (one) or  512us pause/512us pulse (zero)	
#		Enjoy
#		------------------------------------------------------------------------

begin remote

  name  lircd.conf
  bits            9
  flags           RC5|CONST_LENGTH
  eps             5
  aeps            192

  header          512  2560
  one             512   512
  zero            512   512
  plead           1024
  gap             130000
  min_repeat      1
  toggle_bit_mask 0x0

      begin codes
          ON_OFF                   0x1F7
          SCL                      0x15F
          DISC                     0x0E7
          A1/PH                    0x017
          A2/TV                    0x1C7
          A3/TUN                   0x147
          REC                      0x57
#          1                        0x02F
#          2                        0x1CF
#          3                        0x14F
#          4                        0x1EF
#          5                        0x1B7
#          6                        0x27
#          7                        0x77
#          8                        0x177
#          9                        0x037
#          0                        0x1E7
          KEY_1                        0x02F
          KEY_2                        0x1CF
          KEY_3                        0x14F
          KEY_4                        0x1EF
          KEY_5                        0x1B7
          KEY_6                        0x27
          KEY_7                        0x77
          KEY_8                        0x177
          KEY_9                        0x037
          KEY_0                        0x1E7
          <>                       0x06B
          Note                     0x09F
          SRND                     0x047
          Speaker                  0x167
          VOL+                     0x1FF
          VOL-                     0x0FF
#          UP                       0x5F
          KEY_UP                   0x5F
#          DOWN                     0xAF
          KEY_DOWN                 0xAF
#          LEFT                     0x12F
          KEY_LEFT                 0x12F
#          RIGHT                    0xD7
          KEY_RIGHT                0xD7
#          OK                       0xCF
          KEY_ENTER                0xCF
#          |<<                      0x199
          KEY_LEFT                 0x199
          <<                       0x1A9
          >>                       0x1A1
#          >>|                      0x191
          KEY_RIGHT                0x191
          Record                   0x141
          Back/RPT                 0x4F
#          STOP                     0xDF
          KEY_STOP                 0xDF
#          PLAY/PAUSE               0x16F
          KEY_PLAY                 0x16F
          SYS_Menu                 0x139
          VID_Menu                 0x73
          AUD_Menu                 0x1AF
          SRC_Menu                 0x107
          RED                      0x1AB
          GREEN                    0x1B3
          YELLOW                   0x1C3
          BLUE                     0x1CB
          LIST                     0x1BB
          STORE                    0x10F
          (i)                      0x1A3
          View                     0x1BF
#          F1                       0x6F
          KEY_MENU                 0x6F
          F2                       0x1DB
          F3                       0x1A7
          F4                       0x193
      end codes

end remote
In the next post I am going to describe how to modify the python code to listen to the number keys in order to select favorite radio stations.

Have fun!
Dernière modification par Atair le lun. 24 août 2020 11:54, modifié 1 fois.

Messages : 5
Inscription : jeu. 30 juil. 2020 18:41

RaspDac mini: How to use a different IR remote control (part2)

Message par Atair » lun. 24 août 2020 11:52

Now to the second part:

For the favorite radio stations I created a playlist named 'FavRadios' with ten entries.

Then I modified the Python script raspdac_oled_telecommand.py accordingly to listen to the number keys:
  • In the __init__ function I added a variable for the playlist name and a dictionary to map the rc number keys to entry numbers in the playlist.
  • Then I introduced new internal function _select_radio which handles the number calls.
  • Finally, I added a check for number keys and call of the new function at the end of the if-elif construct checking the incoming keys.
Here is the complete code. Just replace the original script and after reboot it works like a charm.

Code : Tout sélectionner

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# ----------------------------------------------------------------------------
# Gestion de la télécommande Infra-Rouge
# Fichier : raspdac_oled_telecommand.py
# 15 Mai 2019      : Creation
# 02 Juin 2019     : Gestion du driver ES9038Q2M + ajout Menu Télécommande
# ----------------------------------------------------------------------------
# Ce fichier est utilisé par le script principal raspdac_oled_main.py
# Ce fichier doit être installé dans le même répertoire que :
#   -> raspdac_oled_main.py (script principal)
#   -> raspdac_oled_request_mpd (gestion des requêtes avec le serveur MPD)
#   -> raspdac_oled_request_os (requêtes avec l'OS Linux et le pilote ALSA)
#   -> raspdac_oled_screen_menu.py (gestion du MENU activé par télécommande)
#   -> raspdac_oled_screen_display.py (affichage sur l'écran)
#   -> raspdac_oled_screen_frames.py (définition des trames des pages)
#   -> fonts : répertoire des polices de caractères utilisées pour l'affichage
# ----------------------------------------------------------------------------
import socket
import time
from raspdac_oled_request_os import shell_command
SOCKPATH = "/var/run/lirc/lircd"

# ----------------------------------------------------------------------------
# Gestion de la télécommande infrarouge
class InfraRedTelecommand() :
    # Initialisations
    def __init__(self) :   
        self.bufsize = 128                  # Taille du buffer de réception
        self.socket = socket.socket(        # Construction du socket
            socket.AF_UNIX,                 # famille d'adresses de type UNIX
            socket.SOCK_STREAM )            # type du socket = stream
        self.socket.setblocking(0)          # mode non bloquant
        self.key_time = float(time.time())  # mémorisation de l'instant de l'appui d'une touche
        self.key_quick_gap = 0.5            # intervalle de temps entre deux touches caractérisant des apppuis rapides
        #  Modification by Atair
        self.fav_radios = 'FavRadios'
        self.num_keys = {'KEY_0':'1', 'KEY_1':'2', 'KEY_2':'3', 'KEY_3':'4', 'KEY_4':'5', 'KEY_5':'6', 'KEY_6':'7', 'KEY_7':'8', 'KEY_8':'9', 'KEY_9':'10' } # Mapping keys to entry (slot) numbers in the playlist
    def _select_radio(self,slot):
    	 shell_command( "/usr/bin/mpc single on")                           # Do not proceed if one radio station stops
    	 shell_command( "/usr/bin/mpc shuffle off")                         # Turn shuffle and consume off if on
    	 shell_command( "/usr/bin/mpc consume off")
    	 shell_command( "/usr/bin/mpc clear")                                   # Clear the player's queue
    	 shell_command( "/usr/bin/mpc load " + self.fav_radios)  # Load the FavRadios playlist
    	 shell_command( "/usr/bin/mpc play " + slot)                        # Finally play the selected station

    # End modifications by Atair

    # Récupération du code de touche (lorsqu'une touche est activée sur la télécommande)
    def get_key(self):
        try :
            data = self.socket.recv(self.bufsize).decode("Utf8")
            key = data.split(' ')[2]
            key_trigger = float(time.time())
            delta = key_trigger - self.key_time
            if (delta < self.key_quick_gap) :
                speed = 'HIGH'
            else : 
                speed = 'LOW'
            self.key_time = key_trigger
            return key, speed
        except socket.error as e:           # pas de touche activée sur la télécommande
            return 'NO_KEY', 'LOW'

    # Action déclenchée lorsqu'une touche est activée sur la télécommande
    def action(self, key='NO_KEY', speed='LOW', menu={} ):
        cmd = ""
        # Cas où la page 'MENU' est active
        # Ici la page 'MENU' est affichée à l'écran
        # Et la télécommande permet d'afficher, de sélectionner et de modifier les paramètres du pilote ALSA
        if menu['status'] == 'ON' :
            if key == 'KEY_MENU' :          # Désactivation de la page 'MENU'
            elif key == 'KEY_DOWN' :          # Passage au "control" suivant ('MUTE' -> 'FILTER' -> 'INPUT' -> 'MUTE' -> ...)
                menu['selected_control'] += 1
                if menu['selected_control'] >= menu['controls_number'] :
                    menu['selected_control'] = 0
                menu['selected_item'] = menu['active_item'][menu['selected_control']]
            elif key == 'KEY_UP' :        # Passage au "control" précedent ('MUTE' -> 'INPUT' -> 'FILTER' -> 'MUTE' -> ...)
                if menu['selected_control'] == 0 :
                    menu['selected_control'] = menu['controls_number']
                menu['selected_control'] -= 1
                menu['selected_item'] = menu['active_item'][menu['selected_control']]
            elif key == 'KEY_LEFT' :        # Passage à l'item précédent du "control" courant
                if menu['selected_item'] == 0 :
                    menu['selected_item'] = menu['items_number'][menu['selected_control']]
                menu['selected_item'] -= 1
            elif key == 'KEY_RIGHT' :       # Passage à l'item suivant du "control" courant
                menu['selected_item'] += 1
                if menu['selected_item'] >= menu['items_number'][menu['selected_control']] : 
            elif key == 'KEY_ENTER' :       # Validation de l'item du "control" courant et configuration du pilote ALSA
                menu['active_item'][menu['selected_control']] = menu['selected_item']
                control = menu['controls_list'][menu['selected_control']]
                value = menu['items_list'][menu['selected_control']][menu['selected_item']]
                # Commande à envoyer au pilote ALSA pour valider l'item
                cmd = "amixer sset -c 0 '{control}' '{value}'".format(control=control,value=value)
            else :
        # Cas où la page 'MENU' est non activée
        # Ici la télécommande permet de piloter le serveur de Media MPD (réglage du volume, sélection des plages)
        else :
            if key == "KEY_MENU" :
                cmd = ""
            elif key == 'KEY_UP' :          # Augmentation du volume
                if speed == 'HIGH' :
                    cmd = "/var/www/vol.sh up 5"
                    cmd = "/var/www/vol.sh up 1"
            elif key == 'KEY_DOWN' :        # Réduction du volume
                if speed == 'HIGH' :
                    cmd = "/var/www/vol.sh dn 5"
                    cmd = "/var/www/vol.sh dn 1"
            elif key == 'KEY_LEFT' :        # Passage au titre précédent
                cmd = "/usr/bin/mpc prev"
            elif key == 'KEY_RIGHT' :       # Passage au titre suivant
                cmd = '/usr/bin/mpc next'
            elif key == 'KEY_ENTER' :       # Arrêt du player
                cmd = "/usr/bin/mpc stop"
            elif key == "KEY_PLAY" :        # Bascule entre "play" et "pause"
                cmd = "/usr/bin/mpc toggle"
            elif key == "KEY_STOP" :        # Stop playing
                cmd = "/usr/bin/mpc stop"   

            # Modifications by Atair
            elif key in self.num_keys :     # Select a radio station by number
            # End modifications by Atair

            else :
        # envoi de commande Shell
        if cmd != "" : shell_command(cmd)
        return menu

I also considered to have more favorite stations by allowing for two digit slots and also program the slots directly using the remote with optical feedback on the oled screen. But currently I am content with this simple solution.

You could also think of a solution where you can select and launch ready made playlists by mapping each to a number of the remote, e.g., define a function key that switches between different functionalty of the number keys, either select radios or playlists. Etc., .....