Shop OBEX P1 Docs P2 Docs Learn Events
Can't Wait for PropGCC on the P2? - Page 18 — Parallax Forums

Can't Wait for PropGCC on the P2?

1151618202126

Comments

  • samuellsamuell Posts: 554
    edited 2019-01-23 17:11
    Dave Hein wrote: »
    samuell wrote: »
    Hi,

    Here is a new version of the prime number calculation program, provided in the zip file attached. It should run without issues at 160MHz. To compile it, just run the shell script.

    I tried to implement David Zemmon code "common.c" and "common.h", but the compiler started complaining about variable redefinitions. So, in the mean time, 160MHz it is!

    Kind regards, Samuel Lourenço

    I tried the new program, and hangs after calculating several prime numbers if I specify a maximum of 100000. It works fine for smaller numbers. If I increase the stack size from 56 to 57 or more it works for a max 100000. I added my check_stacks code, and it reports 56 used even for a max of 100000. I even printed out the first few ints of the stack to make sure check_stacks is working correctly. I'm not sure what is causing the hang up, but a stack larger than 56 seems to fix it.
    That is strange, and I can't reproduce the issue. I did a few big runs, including one calculating numbers between 1 and 100000000 (see attached images), and no longer saw any issues associated with the stack. Normally, when the stacks were set to 46 ints, the program would hang in those circumstances, but didn't saw that happening with the new version.

    Is this caused by a zero terminated string on the stack? If you put a non zero int on the last position of each stack, does it change to zero? This could be a power supply issue as well. A larger stack may mask the problem. You could try reducing the clock and see if it works.

    Kind regards, Samuel Lourenço
    1024 x 768 - 121K
    1024 x 768 - 124K
    1024 x 768 - 122K
  • __red__ wrote: »
    So I've been digging around the threads for about 30m looking for why we need to use wine on the Mac at all.

    What am I missing?

    What's the issue with it not being native? Maybe it's something I can help with.

    (Probably not given the people working on this already but just on the off-chance, multiple eyeballs etc...)
    There might be some confusion about which tool requires a WIN environment and thus wine on macOS or Linux systems...

    1. Ray's SpinEdit, is a WIN app (C Sharp-based, I think) and was tested with wine on macOS (& Linux???) by several forum folks. With a little work setting a COM port in dosdevices, I got it to work for me. It executes WIN versions of the fastspin & loadp2 to compile & load P2 programs.

    2. spin2gui is a TCL program, that "should" run on macOS natively...

    It requires:
    - the XQuartz app, which provides a Unix-friendly graphic display environment
    - TCL (or Wish), to execute the spin2gui Tcl code
    - A P2 configuration setup that points to macOS versions of: fastspin & loadp2

    dgately

  • __red__ wrote: »
    So I've been digging around the threads for about 30m looking for why we need to use wine on the Mac at all.

    What am I missing?

    What's the issue with it not being native? Maybe it's something I can help with.

    (Probably not given the people working on this already but just on the off-chance, multiple eyeballs etc...)

    I think the wine-on-mac was for SpinEdit mostly. I haven't noticed anyone mentioning p2gcc on mac via wine.
  • samuellsamuell Posts: 554
    edited 2019-01-23 18:17
    Hi Dave,

    Regarding the program, I did some experimentation with this code. I can't get it to fail yet, but by changing the stack size (by typedef) I've concluded the same as you did, regarding the way stacks are filled (that is, from the higher address to the lower address).

    Here is the code:
    /*
     * Programa de cálculo de números primos para a placa de desenvolvimento
     * "Prop II"
     * 
     * Este programa foi criado para verificar o desempenho da placa "Prop II",
     * mas pode ser utilizado com outras placas de desenvolvimento baseadas no
     * Propeller P8X32A. O programa calcula números primos dentro de uma dada
     * gama, cujos valores são introduzidos pelo utilizador.
     * 
     * Nota:
     * Para o máximo desempenho, o programa deve ser compilado utilizando o modelo
     * de memória "LMM Main RAM". Deverá seleccionar a opção "Math Lib" no
     * separador "Linker".
     *
     * Autor: Samuel Lourenço
     * Data: 27 de Agosto de 2016
     */
    
    // Includes
    #include <math.h>
    #include <propeller.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    #define STACKSIZE 56
    
    // Protótipos
    void init(void);
    _Bool isprime(unsigned long long);
    void isprime_cog(void* param);
    void init_stacks(int num);
    void check_stacks(int num);
    void print_stacks(int num);
    
    // Variáveis globais
    static short lockid;
    unsigned int stacks[7][STACKSIZE];
    static volatile _Bool flags[7] = {0, 0, 0, 0, 0, 0, 0}, results[7];
    static volatile unsigned long long numbers[7] = {0, 0, 0, 0, 0, 0, 0};
    /* Tanto o array "flags" como o array "numbers" são indicadores de estado, e por
     * isso devem ser inicializados a zero. O array "flags" indica a disponibilidade
     * de cada 'cog' (zero para "inactivo" e um para "activo"), ao passo que o
     * array "numbers" é indicativo das tarefas, uma vez que armazena os números 
     * processar (um valor a zero significa que o 'cog' correspondente está livre).
     * Estes arrays são implicitamente limpos depois da sessão de cálculo. O array
     * "results" não é indicador de estado, pelo que não precisa de ser
     * inicializado a zero. */
    
    
    // Patch for P2 added here - Thanks Dave Hein!
    int __attribute__((noinline)) isqrt(int x)
    {
        __asm__("qsqrt r0, #0");
        __asm__("getqx r0");
    }
    
    int __attribute__((noinline)) lockclr2(int id)
    {
        __asm__("lockrel r0 wc");
        __asm__("muxc    r0,##-1");
    }
    
    int __attribute__((noinline)) lockset2(int id)
    {
        __asm__("locktry r0 wc");
        __asm__("muxnc   r0,##-1");
    }
    
    int64_t __attribute__((noinline)) __umoddi3(int64_t x, int64_t y)
    {
        __asm__("setq r1");
        __asm__("qdiv r0, r2");
        __asm__("getqy r0");
        __asm__("mov r1, #0");
    }
    // End of patch
    
    
    void main(void)
    {
        long long count, min, max, in, out;
        char input[256];
        init();
        while (1)
        {
            count = 0;
            min = 0;
            max = 0;
            /* É importante limpar as variáveis anteriores antes de cada ciclo de
             * cálculo. */
            init_stacks(STACKSIZE);
            while (min <= 0)
            {
                printf("Insira o valor mínimo: ");
                gets(input);  // Lê a string introduzida
                min = atol (input);  // Converte para 'long long integer'
                if (min <= 0)  // Se o valor introduzido for menor ou igual a zero, ou não for um número
                    printf("O valor mínimo deve ser um número maior do que zero!\n");
            }
            while (max <= 0)
            {
                printf("Insira o valor máximo: ");
                gets(input);  // Lê a string introduzida
                max = atol (input);  // Converte para 'long long integer'
                if (max <= 0)  // Se o valor introduzido for menor ou igual a zero, ou não for um número
                    printf("O valor máximo deve ser um número maior do que zero!\n");
            }
            if (min <= max)  // Se o valor mínimo for menor ou igual ao valor máximo
            {
                printf("\nA calcular números primos...\n\n");
                out = in = min;
                /* A variável "in" guarda o valor a introduzir, enquanto que a
                 * variável "out" serve para fazer uma gestão dos números a
                 * verificar depois do cálculo. Estas variáveis vão sendo
                 * incrementadas por cada número que é introduzido ou verificado no
                 * array "numbers". Note que o valor em "out" não corresponde
                 * necessariamente ao valor que está a ser extraído do array. */
                while (out <= max)
                {
                    short i;
                    for (i = 0; i < 7; i++)  // Este ciclo "varre" os valores dos arrays "flags", "numbers" e "results"
                    {
                        while (lockset2(lockid) == -1)  // Espera pelo 'lock' dos recursos
                            ;
                        if (!flags[i] && numbers[i] != 0)  // Se o 'cog' estiver marcado como estando "inactivo" e o número não for zero
                        {
                            if (results[i])  // Se o número for primo
                            {
                                count++;  // Incrementa o valor da variável "count", que serve para a contagem dos números primos
                                printf("%d:\t%u\n", (int)count, (unsigned int)numbers[i]);  // Imprime a contagem e o número
                            }
                            numbers[i] = 0;  // Uma vez verificado se é primo ou não, limpa o número na posição 'i'
                            out++;  // Incrementa o valor da variável "out"
                        }
                        if (in <= max && numbers[i] == 0)  // Se houver novos números a introduzir e se houver 'cogs' livres
                        {
                            numbers[i] = (unsigned long long)in;  // Introduz o número da variável "in" no array "numbers", posição 'i'
                            flags[i] = 1;  // Marca o 'cog' correspondente ao índex como "activo", efectivamente dando sinal ao mesmo para arrancar
                            in++;  // Incrementa o valor de "in"
                        }
                        lockclr2(lockid);  // Retira o 'lock' dos recursos
                    }
                }
                printf("\n%lld número(s) primo(s) encontrados.\n\n", count);  // Apresenta a contagem final de números primos
            }
            else  // Se o valor mínimo for maior do que o valor máximo
                printf("O valor mínimo não pode ser maior do que o valor máximo!\n");
            check_stacks(STACKSIZE);
            print_stacks(STACKSIZE);
        }
    }
    
    void init (void)  // Rotina de inicialização do micro-controlador
    {
        lockid = (short)locknew();  // Cria um 'lock'
        lockclr2(lockid);  // Limpa o estado do 'lock' criado, garantindo que este fica a zero
        short i;
        for (i = 0; i < 7; i++)  // Os 'cogs' 1 a 7 são inicializados aqui, sempre com a mesma rotina
        {
            cogstart(isprime_cog, NULL, stacks[i], sizeof(stacks[i]));  // Inicia cada 'cog' com a rotina "isprime_cog" e atribui-lhe o seu 'stack'
        }
    }
    
    _Bool isprime(unsigned long long number)  // Função para cálculo de números primos
    {
        /* Esta pode ser considerada a função central do programa. Para ver se um
         * dado número é primo ou não, primeiro verifica-se se o mesmo é um, dois,
         * três, ou se é divisível por dois ou três. Considera-se que se o número
         * for igual a um, ou divisível por dois ou três, não é primo. Sendo dois
         * ou três, é primo. Não se satisfazendo qualquer das condições
         * anteriores, verifica-se se o número é divisível por todos os números
         * ímpares não múltiplos de três, a partir de cinco até (pelo menos) ao
         * inteiro da raiz quadrada do mesmo (inclusive). Repare que não é
         * necessário ensaiar todas as divisões até o quociente ser igual ao
         * próprio número. Deste modo, o algoritmo fica muito mais rápido. */
        _Bool retval;
        unsigned long sqrt_num;
        if (number == 2 || number == 3)  // Se o número for dois ou três
            retval = 1;  // então é primo
        else if (number < 2 || number % 2 == 0 || number % 3 == 0)  // Se for zero ou um, ou divisível por dois ou por três (não sendo dois ou três)
            retval = 0;  // não é primo
        else
        {
            retval = 1;  // Assume-se que o número é primo, até haver uma divisão inteira
            sqrt_num = (unsigned long)isqrt(number);  // Calcula previamente a raíz quadrada do número
            unsigned long n;
            for (n = 5; n <= sqrt_num; n += 6)  // Ciclo onde são testadas as divisões por números ímpares que não sejam múltiplos de três
            {
                if (number % n == 0 || number % (n + 2) == 0)  // Se a divisão por 'n' ou por 'n + 2' for inteira
                {
                    retval = 0;  // o número não é primo
                    break;  // Sai do ciclo
                }
            }
        }
        return retval;  // Retorna o valor um se o número dado for primo, e zero se não o for
    }
    
    void isprime_cog(void *param)  // Rotina dedicada a cada 'cog'
    {
        _Bool flag, result;
        unsigned long long number;
        short i = cogid() - 1;  // Vê de antemão qual é o 'cog' que está a executar esta rotina, e associa o valor obtido a um índex
        while(1)
        {
            while (lockset2(lockid) == -1)  // Espera pelo 'lock' dos recursos
                ;
            flag = flags[i];  // Lê as variáveis "flag"
            number = numbers[i];  // e "number" dirigida ao 'cog' que está a executar este procedimento
            lockclr2(lockid);  // Retira o 'lock'
            /* Os recursos devem estar disponíveis para os outros 'cogs' enquanto
             * se verifica se o número é primo ou não. Se assim não fosse, não seria
             * possível ter vários 'cogs' a fazer esta verificação em simultâneo. */
            if (flag)  // Se o 'cog' estiver marcado como activo, então inicia o cálculo
            {
                result = isprime(number);  // Calcula se o número dado é primo ou não
                while (lockset2(lockid) == -1)  // Espera pelo 'lock' dos recursos
                    ;
                results[i] = result;  // Devolve o resultado (se é primo ou não)
                flags[i] = 0;  // Marca o 'cog' como "inactivo"
                lockclr2(lockid);  // Retira o 'lock'
            }
        }
    }
    
    void init_stacks(int num)
    {
        int i, j;
        for (i = 0; i < 7; i++)
        {
            for (j = 0; j < num; j++)
                stacks[i][j] = 0xdeadbeef;
        }
    }
    
    void check_stacks(int num)
    {
        int i, j;
        for (i = 0; i < 7; i++)
        {
            for (j = 0; j < num; j++)
            {
                if (stacks[i][j] != 0xdeadbeef) break;
            }
            printf("stack %d used %d ints\n", i, num - j);
        }
    }
    
    void print_stacks(int num)
    {
        int i, j;
        for (i = 0; i < 7; i++)
        {
            printf("Stack %d:\n", i);
            for (j = 0; j < num; j++)
            {
                printf("0x%8x ", stacks[i][j]);
            }
            printf("\n");
        }
    }
    
    

    Also tried to reduce the stack to 46 ints, and the data is overwritten elsewhere. That might be a hint that 56 ints might not do it, if there is "relocation" happening.

    Please, see the attached images to see some test results. Meanwhile, I'll run a huge test with the stack size set to 300, to see if I catch anything out of boundaries.

    Kind regards, Samuel Lourenço
    1024 x 768 - 95K
    1024 x 768 - 96K
    1024 x 768 - 96K
    1024 x 768 - 96K
    1024 x 768 - 97K
  • Ok, test completed without issues. Did a run from 1 to 10000000, with the stack size set to 300 ints. There were no new values written out of boundaries.

    Kind regards, Samuel Lourenço
    1024 x 768 - 93K
  • It's not a stack problem. It has something to do with memory alignment. I inserted an "int dummy[1];" before the stacks declaration, and the problem goes away. However, if I insert "int dummy[16];" the problem happens again. I'm guessing it's a timing issue. It might have something to do with using a lock.

    The problem also happens with "int dummy[8];". Program execution time and hub access time is dependent on how things line up in hub memory. A program can take N cycles to run, but if you move the program or its data by 1 long it will take a different number of cycles. However, if you move it by 8 longs it will take the same number of cycles. This is due to the architecture of the hub RAM.

    When I get a chance sometime next week I'll see if I can figure out where the program is hanging.
  • Dave Hein wrote: »
    It's not a stack problem. It has something to do with memory alignment. I inserted an "int dummy[1];" before the stacks declaration, and the problem goes away. However, if I insert "int dummy[16];" the problem happens again. I'm guessing it's a timing issue. It might have something to do with using a lock.

    The problem also happens with "int dummy[8];". Program execution time and hub access time is dependent on how things line up in hub memory. A program can take N cycles to run, but if you move the program or its data by 1 long it will take a different number of cycles. However, if you move it by 8 longs it will take the same number of cycles. This is due to the architecture of the hub RAM.

    When I get a chance sometime next week I'll see if I can figure out where the program is hanging.
    It makes sense that is not a stack issue. However, I can't still reproduce the issue, even after inserting "int dummy[1];" where you said. We need to have more test cases, or in this case more volunteers to test this on a P2.

    Could you zip the failing code and send it to me? I want to recreate the conditions you are having.

    Kind regards, Samuel Lourenço
  • You would need to try sizes of 1 through 7 since you may have a different memory alignment than I do. However, it's certainly possible that you may not be able to reproduce the issue even after trying all 7 alignments.
  • evanhevanh Posts: 15,916
    Dave,
    If you're interested in using smartpins for the revised getch()/putch() then I've honed my versions.
    '===============================================
    getch
    		testp   #rx_pin         wz    'byte received? (IN high == yes)
    if_z		rdpin   char, #rx_pin         'get data
    if_z		shr     char, #32-8           'shift the data to bottom of register
    if_z		ret                     wcz   'restore C/Z flags of calling routine
    		jmp     #getch                'wait while Smartpin is idle
    
    
    '===============================================
    putch
    		rqpin   inb, #tx_pin    wc    'transmiting? (C high == yes)  *Needed to initiate tx
    		testp   #tx_pin         wz    'buffer free? (IN high == yes)
    if_z_or_nc	wypin   char, #tx_pin         'write new byte to Y buffer
    if_z_or_nc	ret                     wcz   'restore C/Z flags of calling routine
    		jmp     #putch                'wait while Smartpin is both full (nz) and transmitting (c)
    
    
    They're explicitly built to retain the calling flags. I found this to be valuable.
    You'll also note the same "char" variable as your code, because I used your bit-bashing versions to get me going.

    It does require an init routine though. I hoping that's no biggie for building into in C startup.
    '===============================================
    diaginit	'only called once at beginning
    
    '----- Configure diag comport to use smartpins instead of bit-bashing -----
    		wrpin   #%00_11111_0, #rx_pin 'Asynchronous serial receive
    		wxpin   asynconfig, #rx_pin   'set baurdrate and framing
    		dirh    #rx_pin
    		wrpin   #%01_11110_0, #tx_pin 'Asynchronous serial transmit mode
    		wxpin   asynconfig, #tx_pin   'set X with baudrate and framing
    _ret_		dirh    #tx_pin               'release Z from zero
    
    
  • evanhevanh Posts: 15,916
    Regarding stack operations: I hope everyone knows that Pnut's alias for PUSHA/PUSHB builds the hubRAM stack up from low memory not down from high memory. And Pnut's POPA/POPB does the matching reverse.

    They are just aliases, either way can be done without using the PUSH/POP aliases. Or the aliases could be redefined but that could have compatibility issues.

  • I tried the following command this evening when I got home from work and it works fine!
    loadp2 -b 115200 -l 115200 cdemo.binary -t -v -p /dev/cu.usbserial-P2EEQXU -SINGLE
    
    However, it doesn't work if I leave off the "-SINGLE" part. Is there a reason that the two-stage loader won't work on the Mac? The load itself seems to complete but nothing appears on the serial console without -SINGLE.
  • I found a bug in loadp2 today where the load mode isn't set if the serial port is specified. I have fixed it in my local copy, and it now sets the load mode to SINGLE when the port is specified. Specifying -CHIP should work with the P2 Eval board. Using either SINGLE or CHIP work for me.
  • David BetzDavid Betz Posts: 14,516
    edited 2019-01-24 02:12
    Dave Hein wrote: »
    I found a bug in loadp2 today where the load mode isn't set if the serial port is specified. I have fixed it in my local copy, and it now sets the load mode to SINGLE when the port is specified. Specifying -CHIP should work with the P2 Eval board. Using either SINGLE or CHIP work for me.
    Ah yes, -CHIP does work as well as -SINGLE. Can you explain what all of these options mean?
  • dgately wrote: »
    1. Ray's SpinEdit, is a WIN app (C Sharp-based, I think) and was tested with wine on macOS (& Linux???) by several forum folks. With a little work setting a COM port in dosdevices, I got it to work for me. It executes WIN versions of the fastspin & loadp2 to compile & load P2 programs.

    That makes sense wrt wine now. C#/.net executables can actually be made to run natively under linux. The P1 emulator Gear is a good example of that.
    [nix-shell:~/projects/spinedit]$ mono SpinEdit.exe 
    Cannot open assembly 'SpinEdit.exe': File does not contain a valid CIL image.
    

    I'll drop Ray a message just in case I'm missing something.
    2. spin2gui is a TCL program, that "should" run on macOS natively...

    I should probably attempt to package that too.

    Speaking of - I really should try and get OSX as a supported platform in my build system too. I'll see if I can put a few hours in this evening to get that done.

    Thanks for the info, appreciate it.

    Red

  • David Betz wrote: »
    Dave Hein wrote: »
    I found a bug in loadp2 today where the load mode isn't set if the serial port is specified. I have fixed it in my local copy, and it now sets the load mode to SINGLE when the port is specified. Specifying -CHIP should work with the P2 Eval board. Using either SINGLE or CHIP work for me.
    Ah yes, -CHIP does work as well as -SINGLE. Can you explain what all of these options mean?

    SINGLE - Uses a single-stage loader using the P2's Prop_Hex command. This sends each byte using 2 hex digits plus a space character. The user program runs at 20MHz using the RCFAST mode. It must set up the clock frequency itself to run at a higher frequency.

    CHIP - Uses a two-stage loader. The Prop_Hex command is used to load a small program that accepts the data as binary bytes. It sets up the clock frequency before starting the user program. This mode works with the P2 silicon chip.

    FPGA - Works the same as the CHIP mode, but works with the P2 implemented in an FPGA.
  • Dave Hein wrote: »
    David Betz wrote: »
    Dave Hein wrote: »
    I found a bug in loadp2 today where the load mode isn't set if the serial port is specified. I have fixed it in my local copy, and it now sets the load mode to SINGLE when the port is specified. Specifying -CHIP should work with the P2 Eval board. Using either SINGLE or CHIP work for me.
    Ah yes, -CHIP does work as well as -SINGLE. Can you explain what all of these options mean?

    SINGLE - Uses a single-stage loader using the P2's Prop_Hex command. This sends each byte using 2 hex digits plus a space character. The user program runs at 20MHz using the RCFAST mode. It must set up the clock frequency itself to run at a higher frequency.

    CHIP - Uses a two-stage loader. The Prop_Hex command is used to load a small program that accepts the data as binary bytes. It sets up the clock frequency before starting the user program. This mode works with the P2 silicon chip.

    FPGA - Works the same as the CHIP mode, but works with the P2 implemented in an FPGA.
    Thanks for the explanation!

  • I checked in a fix for loadp2 so that it now sets the load mode to SINGLE when the serial port is specified. This can be overridden with the -CHIP or -FPGA option.

    loadp2 can also now be used as serial terminal without loading a program. This is done by specifying a port along with the -t, such as "loadp2 -t -p com4".

  • David BetzDavid Betz Posts: 14,516
    edited 2019-01-24 02:56
    Dave Hein wrote: »
    I checked in a fix for loadp2 so that it now sets the load mode to SINGLE when the serial port is specified. This can be overridden with the -CHIP or -FPGA option.

    loadp2 can also now be used as serial terminal without loading a program. This is done by specifying a port along with the -t, such as "loadp2 -t -p com4".
    What does it do if the serial port is not specified?

    Edit: I see. It tries to find a port with a P2. Unfortunately, it doesn't seem to work on the Mac. In any case, I don't see why it should choose different load options just because it automatically finds the port.

  • evanhevanh Posts: 15,916
    David Betz wrote: »
    In any case, I don't see why it should choose different load options just because it automatically finds the port.
    That would have got messed up as a side effect of all the little changes to the problematic DTR toggling. Which I guess still isn't sorted on OSX.

  • When loadp2 finds a port it also receives the version ID from the P2. This allows it to distinguish between an FPGA and a P2 silicon chip. This can be overridden by specifying -SINGLE, -FPGA or -CHIP.

    We could do the same thing when a port is specified, and I did implement for a short time. However, this cause problems with a particular FPGA board. So when a port is explicitly specified I just open the serial port, but I don't request the version ID.

    Now that I think about it, I believe the problem was caused by doing a reset after I identified the board, and before it was loaded. I don't think the reset is necessary between requesting the ID and performing the load. I'll have to try that to see if it works.
  • I think -CHIP doesn't work on MacOS due to the higher baud rate?
  • I believe David Betz said that -CHIP worked for him. However, he also specified -l 115200 and -b 115200. So MacOS may require that the loader and user baud rates match, and they have to be standard baud rates. I'm not sure that's true, but maybe somebody with a Mac can try various baud rates to see what works, and what doesn't.
  • Dave Hein wrote: »
    I believe David Betz said that -CHIP worked for him. However, he also specified -l 115200 and -b 115200. So MacOS may require that the loader and user baud rates match, and they have to be standard baud rates. I'm not sure that's true, but maybe somebody with a Mac can try various baud rates to see what works, and what doesn't.
    I suspect higher baud rates will work as well. I just tried 115200 because I thought it was safe. I'll try higher rates tonight when I get home from work. Also, I doubt it is necessary for the baud rates to match.

  • evanhevanh Posts: 15,916
    I remember 230400 and 460800 being listed as common speeds in some header file.
  • evanh wrote: »
    I remember 230400 and 460800 being listed as common speeds in some header file.
    921600 definitely works because it is used by proploader.
  • 230400 (2 * 115200) works on MacOS, not higher as far as I can see.
  • Here are two small patches for loadp2 that I've applied for spin2gui:

    (1) errmsg.patch fixes the error message on Unix when an illegal baud rate is given. I think the original intention was to print a list of legal baud rates, but somewhere along the way that stopped working; this patch restores it.

    (2) waitexit.patch adds a -k flag to loadp2 which causes the program to wait for the user to hit a key before exiting. This is mainly useful in environments where the terminal window will close after loadp2 exits; it gives the user a chance to see any error messages
  • Mark_T wrote: »
    230400 (2 * 115200) works on MacOS, not higher as far as I can see.
    It's odd that nothing higher works. I'll try it tonight but higher baud rates certainly work with proploader on the Mac.

  • ersmith wrote: »
    Here are two small patches for loadp2 that I've applied for spin2gui:

    (1) errmsg.patch fixes the error message on Unix when an illegal baud rate is given. I think the original intention was to print a list of legal baud rates, but somewhere along the way that stopped working; this patch restores it.

    (2) waitexit.patch adds a -k flag to loadp2 which causes the program to wait for the user to hit a key before exiting. This is mainly useful in environments where the terminal window will close after loadp2 exits; it gives the user a chance to see any error messages
    Eric, thanks for the patches. I'll incorporate them the next time I update loadp2.
  • RaymanRayman Posts: 14,646
    edited 2019-01-24 17:41
    Just FYI, with regard to SpinEdit (sorry to drop this in, but want to answer that question...)
    It's not .NET or C#. It's MFC version of C++. It just needs Wine.
    But, Wine made me install XQuartz, mono and Gecko before it would run...
    With Wine installed the icon for SpinEdit changes to a wine glass and you can click on it to run it...
    I commented about that here:
    http://forums.parallax.com/discussion/169259/spinedit-editor-for-spin-spin2-and-fastbasic/p2
Sign In or Register to comment.