File:  [Coherent Logic Development] / freem / src / ssvn_zrpi.c
Revision 1.3: download - view: text, annotated - select for diffs
Sun Mar 9 19:50:47 2025 UTC (3 weeks, 2 days ago) by snw
Branches: MAIN
CVS tags: v0-62-3, v0-62-2, v0-62-1, v0-62-0, HEAD
Second phase of REUSE compliance and header reformat

/*
 *   $Id: ssvn_zrpi.c,v 1.3 2025/03/09 19:50:47 snw Exp $
 *    Support for Raspberry Pi single-board computers
 *
 *  
 *   Author: Serena Willis <snw@coherent-logic.com>
 *    Copyright (C) 1998 MUG Deutschland
 *    Copyright (C) 2020, 2025 Coherent Logic Development LLC
 *
 *
 *   This file is part of FreeM.
 *
 *   FreeM is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU Affero General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   FreeM is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU Affero General Public License for more details.
 *
 *   You should have received a copy of the GNU Affero General Public License
 *   along with FreeM.  If not, see <https://www.gnu.org/licenses/>.
 *
 *   $Log: ssvn_zrpi.c,v $
 *   Revision 1.3  2025/03/09 19:50:47  snw
 *   Second phase of REUSE compliance and header reformat
 *
 *
 * SPDX-FileCopyrightText:  (C) 2025 Coherent Logic Development LLC
 * SPDX-License-Identifier: AGPL-3.0-or-later
 **/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "mpsdef.h"
#include "mref.h"
#include "ssvn_zrpi.h"

#if defined(HAVE_WIRINGPI_H)
# include <wiringPi.h>
#endif

int rpi_pinmode[RPI_PINCOUNT];

void ssvn_zrpi_init (void)
{
    register int i;
    
#if defined(HAVE_WIRINGPI_H)

    wiringPiSetup ();
    
    for (i = 0; i < RPI_PINCOUNT; i++) {
        pinMode (i, INPUT);
        rpi_pinmode[i] = INPUT;
    }

#endif
    
}

void ssvn_zrpi (short action, char *key, char *data)
{
    int pin;
    
    freem_ref_t *ref = (freem_ref_t *) malloc (sizeof (freem_ref_t));
    char *kbuf = (char *) malloc (STRLEN * sizeof (char));    
    char *verb = (char *) malloc (STRLEN * sizeof (char));

    NULLPTRCHK(ref,"ssvn_zrpi");
    NULLPTRCHK(kbuf,"ssvn_zrpi");
    NULLPTRCHK(verb,"ssvn_zrpi");
    
#if !defined(HAVE_WIRINGPI_H)

    /* not on a Raspberry Pi */

    *data = EOL;
    merr_raise (NORPI);

    goto done;

#else

    mref_init (ref, MREF_RT_SSVN, "");
    internal_to_mref (ref, key);

    stcpy (kbuf, key);


    if (strcmp (ref->subscripts[0], "INITIALIZE") == 0) {

        ssvn_zrpi_init ();

        *data = EOL;
        merr_raise (OK);

        goto done;

    }

    if (strcmp (ref->subscripts[0], "GPIO") != 0) {
        merr_raise (INVREF);
        goto done;
    }

    if (ref->subscript_count < 3) {
        merr_raise (INVREF);
        goto done;
    }

    pin = atol (ref->subscripts[1]); 
    strncpy (verb, ref->subscripts[2], 255);

    if (pin < 0 || pin > RPI_PINCOUNT) {
        merr_raise (INVREF);
        goto done;
    }
    
    switch (action) {

        
        case get_sym:

            if (strcmp (verb, "MODE") == 0) {

                switch (rpi_pinmode[pin]) {

                    case INPUT:
                        sprintf (data, "INPUT\201");
                        break;

                    case OUTPUT:
                        sprintf (data, "OUTPUT\201");
                        break;

                    case PWM_OUTPUT:
                        sprintf (data, "PWM_OUTPUT\201");
                        break;

                    case GPIO_CLOCK:
                        sprintf (data, "GPIO_CLOCK\201");
                        break;
                }
                       
                
            }
            else if (strcmp (verb, "DIGITAL") == 0) {

                sprintf (data, "%d\201", digitalRead (pin));
                break;
                
            }
            else if (strcmp (verb, "ANALOG") == 0) {

                sprintf (data, "%d\201", analogRead (pin));
                break;
                
            }            
            else {
                merr_raise (INVREF);
                goto done;
            }

            goto done;

            
        case set_sym:

            
            if (strcmp (verb, "MODE") == 0) {

                if (stcmp (data, "INPUT\201") == 0) {
                    pinMode (pin, INPUT);
                    rpi_pinmode[pin] = INPUT;
                }
                else if (stcmp (data, "OUTPUT\201") == 0) {
                    pinMode (pin, OUTPUT);
                    rpi_pinmode[pin] = OUTPUT;
                }
                else if (stcmp (data, "PWM_OUTPUT\201") == 0) {
                    pinMode (pin, PWM_OUTPUT);
                    rpi_pinmode[pin] = PWM_OUTPUT;
                }
                else if (stcmp (data, "GPIO_CLOCK\201") == 0) {
                    pinMode (pin, GPIO_CLOCK);
                    rpi_pinmode[pin] = GPIO_CLOCK;
                }
                else {
                    merr_raise (INVREF);
                    goto done;
                }

                goto done;
                
            }
            else if (strcmp (verb, "DIGITAL") == 0) {

                char dta[255];
                int val;

                stcpy (dta, data);
                stcnv_m2c (dta);

                val = atoi (dta);

                switch (val) {

                    case 0:
                        digitalWrite (pin, LOW);
                        goto done;

                    case 1:
                        digitalWrite (pin, HIGH);
                        goto done;

                    default:
                        merr_raise (INVREF);
                        goto done;

                }
                
                goto done;

            }
            else if (strcmp (verb, "ANALOG") == 0) {

                char dta[255];
                int val;

                stcpy (dta, data);
                stcnv_m2c (dta);

                val = atoi (dta);

                if (val < 0 || val > 1024) {
                    merr_raise (INVREF);
                    goto done;
                }
                
                analogWrite (pin, val);
                
                goto done;
                
            }
            else {
                merr_raise (INVREF);
                goto done;
            }

            goto done;


        default:

            merr_raise (INVREF);
            goto done;

            break;

    }
    
#endif

    
done:
                
    free (ref);
    free (kbuf);
    free (verb);
    
    return;

}

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>