MSX LoRa – First contact

Finalmente após algum período longe do desenvolvimento de software para MSX, decidi voltar ao game unindo o útil mundo do IoT ao agradável universo de retrocomputing através do nosso querido e amado MSX.

Como se trata de um tema atual, rico de informações e possibilidades, decidi escrever dois artigos sendo esse aqui o primeiro que é mais introdutório e o segundo será mais prático, descrevendo o passo-a-passo de como usar toda a tecnologia envolvida nesse pequeno projeto.

Não é a primeira vez que me aventuro na área de comunicação no MSX, pois há 10 anos atrás (passou o tempo e nem percebi) escrevi sobre Networking no MSX através de 2 artigos intitulados MSX Networking e MSX Networking – Developers, developers, developers, developers, … respectivamente e que na época tiveram boa receptividade na comunidade MSX.

Nesses posts apresentei tecnologias como a interface de rede para MSX denominada ObsoNET e a interface que estava sendo desenvolvida na comunidade MSX na época e que não tinha nome e que eu intitulei como OptoNET e desde então é reconhecida como OptoNET, inclusive teve uma versão Wi-Fi da mesma e que usa ESP8266.

No ultimo artigo inclusive liberei a implementação de uma abstração de Network Socket para uso em aplicações escritas em Turbo Pascal 3 no MSX, bem como a implementação de um driver para OptoNET sendo assim possível a sua programação em Pascal usando essa abstração.

Nesse interim adquiri quase tudo o que pude referente a comunicação, desde as diversas placas de rede existentes para MSX como a excelente Gr8Net de Eugeny Brychkov (from Russia with love), DenYoNet da Sunrise, até interfaces RS-232 como a Fast Harukaze e a CT-80NET da Gradiente.

Comecei a desenvolver muita coisa para RS-232 utilizando a BIOS padronizada pelo consorcio MSX mas infelizmente paralisei seu desenvolvimento em um estágio bem avançado, o mesmo tendo acontecido com o desenvolvimento das rotinas para uso da ObsoNET que também está quase no mesmo estágio de conclusão das rotinas de RS-232 e que esse ano, ambas as implementações certamente serão concluídas e assim teremos mais uma importante feature na PopolonY2k Framework Library.

Pois bem, há quase 10 anos tenho essas duas interfaces RS-232, Fast Harukaze e a Gradiente CT-80NET e arrisco a dizer que a possibilidade de programar softwares de comunicação para MSX foi o que me fez a voltar a ser bastante atuante na comunidade (isso lá no início dos anos 2000) e que principalmente foi um tópico que me fez a querer ter um MSX real (agora também os sintetizados via FPGA) para colocar meus planos em prática.

RS-232 – O inicio de tudo

O RS-232, também conhecido como RS-232C, é um protocolo padrão de mercado criado no final dos anos 60, mais especificamente em 1969 e que teve seu uso amplamente difundido para o público técnico e de uso geral principalmente nos anos 80 com o advento da computação pessoal difundida pelos mais diversos PC`’s de 8, 16 e 32 Bits da época, atravessando o tempo e chegando aos dispositivos IoT dos dias atuais, como Arduino e Raspberry Pi.

LoRa – Um protocolo serial via wireless

A comunicação avançou muito nos últimos anos e com todo esse avanço tivemos diversas tecnologias criadas que vão desde comunicação via Ethernet cabeada, até WiFi, o que chamamos de comunicação Wireless ou sem fio.

Apesar do bom e velho RS-232C e suas variantes como a RS-485 terem sido desenvolvidos principalmente para operar utilizando cabos, não é recente a sua utilização via wireless através de dispositivos especialmente projetados para lidar com as caraterísticas especiais de uma comunicação sem fio.

Nesse universo e principalmente devido ao grande avanço das tecnologias de Internet Of Things (IoT), muita coisa nova tem sido desenvolvida, principalmente através da união de grandes players de tecnologia, que por sua vez tem ajudado a criar padrões para utilização no universo IoT.

É nesse cenário nasce a Lora Alliance, que é uma organização sem fins lucrativos responsável pela criação, especificação de tecnologias baseadas em LoRa.

Mas que raios é esse LoRa afinal ?

LoRa é um protocolo de comunicação via rádio que significa Long Range (Longo alcance), ou seja, é um protocolo para envio de informações a longas distâncias, onde se tem relatos de comunicação entre 2 pontos a uma distância de até 15Km.

É lógico que depende de vários fatores, como visada (Line of Sight) dentre outros que podem interferir no alcance, porém só o fato de existir essa possibilidade de comunicação a longas distâncias já torna LoRa muito interessante para uso em diversas aplicações como já vem sendo utilizado pelo agronegócio para monitoria de equipamentos em fazendas que na maioria dos casos é um ambiente propício para esse tipo de aplicação

Apesar da grande distância que um dispositivo LoRa pode proporcionar, nem tudo são flores sendo a principal desvantagem a baixa velocidade pois a comunicação entre dispositivos LoRa é extremamente lenta, impossibilitando o seu uso em transmissões com grande volume de dados como áudio e vídeo por exemplo.

Esse é um dos principais motivos pelos quais as informações trafegadas entre dispositivos LoRa, estar restrita a envio de dados de telemetria ou aplicações onde baixa latência não é o principal requisito.

LoRa possui duas topologias de operação, sendo elas Point-to-Point e Network, essa última de fato é uma espécie de Broadcasting, além de variantes como a LoRaWan capaz de colocar um dispositivo LoRa na internet, o que foge um pouco do escopo desse post portanto vamos explorá-la em um post futuro.

Dispositivos LoRa na prática

Na prática temos uma infinidade de dispositivos LoRa desenvolvidos por diversos fabricantes e embora exista uma certa padronização no nível de sinal, frequência de rádio e afins, não há uma padronização na interface de software com LoRa, com isso cada fabricante de dispositivos LoRa está criando sua própria abstração de comunicação com seus dispositivos.

A fabricante REYAX, é a que melhor se adaptou e está usando comandos AT, padrão da Hayes criado para comunicação via modem que se tornou padrão de facto sendo amplamente utilizado pela industria desde os anos 80 bem como pela própria REYAX em seu RYLR998, o que torna esse dispositivo um dos mais “padronizados” em nível de software no mercado.

Dentre os diversos fabricantes, um dos mais “famosos” é a chinesa EBYTE, que possui diversos modelos de módulos LoRa, todos bem parecidos visualmente e operacionalmente entre si, apenas mudando especificações técnicas talvez relacionadas a potência e consumo por exemplo.
O módulo que utilizo nos experimentos com MSX e IoT é exatamente esse da imagem, o E220-900T22D.

Tanto o módulo LoRa da REYAX, quanto o da EBYTE, tem sua interface física de comunicação baseada em UART TTL serial e no caso dos módulos da EBYTE eles tem um protocolo binário bem simples para setup do módulo LoRa e que está disponível quando o módulo está operando em modo de setup/configuração.

A documentação do módulo LoRa da EBYTE pode ser encontrada nesse link aqui, ou em nosso repositório local aqui.

Infelizmente a documentação do módulo da EBYTE não é muito clara e gera algumas duvidas que nos induz a pensar que a documentação está errada ou o módulo não funciona, entretanto após pesquisar outros sites e vídeos sobre esses módulos da EBYTE percebi mesmo que essa documentação é só mau escrita mesmo e que o módulo funciona corretamente e de fato ele é mais simples do que eu imaginava, não necessitando conhecer algum protocolo específico para sua operação (exceto quando você está em modo de setup/configuração do módulo).

Bom, acredito que após essa longa introdução sobre comunicação, dispositivos seriais e LoRa, podemos começar a colocar a mão na massa e ver como usar os dispositivos LoRa e principalmente como utilizá-los através de um computador MSX.

Como eu já citei inicialmente, esse é o primeiro artigo introdutório e no próximo descreveremos tecnicamente os detalhes e possibilidades de integração de dispositivos LoRa no MSX ou em outras tecnologias como Arduino, Raspberry Pi, etc.

Enjoy

[]’s
PopolonY2k

PopolonY2k Framework Memory Mapper support

Após alguns meses do lançamento da última versão do PopolonY2k Framework, venho trabalhando em alguns programas de exemplo para reforçar os conceitos implementados no framework bem como na difusão de conhecimento de tudo o que tem nele desenvolvido.

A comunidade nacional tem utilizado muitas partes do framework e principalmente a comunidade internacional tem reportado alguns problemas encontrados, principalmente no Pop!Art, o que me levou a verificar que de fato os problemas estão relacionados a algumas peças do framework e que brevemente serão ajustadas ainda esse ano.

No grupo de WhatsApp “MSX Pascal, C, ASM e etc” temos discutido muito sobre assuntos relacionados a desenvolvimento para retro-machines, principalmente para o MSX e em algumas dessas discussões surgiram alguns questionamentos sobre o uso das rotinas de uso da mapper do PopolonY2k Framework.

Por esse motivo, preparei um sample com um código bem elucidativo sobre o uso das principais rotinas de alocação e paginação da mapper que fazem uso das rotinas do MSXDOS2 disponíveis no framework, conforme análise e explicação pode ser vista no vídeo abaixo.

MSXDOS2 Mapper PopolonY2k Framework routines

O framework também contempla uso da mapper através do acesso direto a portas de I/O, o que torna o seu uso mais rápido, entretanto essas rotinas são as chamadas “mal comportadas” e devem ser utilizadas com muita cautela principalmente quando se tem completa certeza de que não há conflitos com áreas pré-alocadas pelo próprio MSXDOS2 via suas rotinas padrão.

O Pop!Art faz isso com extrema segurança, onde o mesmo aloca e preenche os dados da música VGM usando as rotinas de mapper padrão do MSXDOS2 e usa as de acesso direto, apenas no momento em que está tocando quando está apenas fazendo paginação dos segmentos da mapper pré-alocados pelas rotinas do MSXDOS2.

Os exemplos estão sendo adicionados diretamente no repositório do projeto na OldSkoolTech no SourceForge.net e podem ser consultados nesse link aqui.

O sample de uso da mapper (maprtest.pas) está completamente comentado sendo bem auto-explicativo, além de ter uma análise bem completa no vídeo acima, podendo seu código ser conferido abaixo:

(*<maprtest.pas>
 * Memory mapper routines test.
 *
 * - Routines tested:
 * - InitMapper;
 * - GetMapperPageByAddress;
 * - PutMapperPageByAddress;
 * - AllocMapperSegment;
 * - FreeMapperSegment;
 *
 * CopyLeft (c) since 1995 by PopolonY2k.
 *)

(**
  *
  * $Id$
  * $Author$
  * $Date$
  * $Revision$
  * $HeadURL$
  *)

{-----------------------------------------------------------------------------}
{                      PopolonY2k Framework dependencies                      }
{-----------------------------------------------------------------------------}

{$i types.pas}
{$i helpchar.pas}
{$i msxbios.pas}
{$i extbio.pas}
{$i maprbase.pas}
{$i maprallc.pas}
{$i maprpage.pas}

{-----------------------------------------------------------------------------}
{                             Module definitions                              }
{-----------------------------------------------------------------------------}

Type TMappedBuffer = Array[0..ctMaxMapperPageSize] Of Char; { Mapped 16K bufr }


{-----------------------------------------------------------------------------}
{                              Helper functions                               }
{-----------------------------------------------------------------------------}

(**
  * Print part of a buffer content passed as reference.
  * @param aBuffer Reference to buffer to be printed;
  *)
Procedure PrintBuffer( Var aBuffer : TMappedBuffer );
Const
       __ctMaxCol   : Byte = 10;

Var
       x, y  : Byte;

Begin
  For y := 0 To __ctMaxCol Do
    For x := 0 To __ctMaxCol Do
    Begin
      GotoXY( ( x + 1 ), ( y + 1 ) );
      Write( aBuffer[( x + y ) * __ctMaxCol] );
    End;

  WriteLn;
  WriteLn( 'Press <enter> to continue' );
  ReadLn;
  ClrScr;
End;

{-----------------------------------------------------------------------------}
{                    Main program variables and constants                     }
{-----------------------------------------------------------------------------}

Const
           ctDefaultPage  = $8000;     { Default page for data - Page 2 }

Var
      maprHandle       : TMapperHandle;
      chKey            : Char;
      nActiveSegmentId : Byte;
      aSegments        : Array[0..1] Of Byte;
      aDataBuffer      : TMappedBuffer Absolute ctDefaultPage;


{-----------------------------------------------------------------------------}
{                          Main program entry point                           }
{-----------------------------------------------------------------------------}

Begin    { Main program entry }
  ClrScr;

  { Initialize mapper system }
  If( Not InitMapper( maprHandle ) )  Then
  Begin
    WriteLn( 'Error to initialize Mapper' );
    Exit;
  End;

  WriteLn( 'Mapper succesfully initialized' );

  { Get the current segment used by data buffer on stack }
  aSegments[0] := GetMapperPageByAddress( maprHandle, Addr( aDataBuffer ) );

  WriteLn( 'Main Segment -> ', aSegments[0], ' on page 2' );
  WriteLn( 'Press <enter> to see it''s content' );
  ReadLn;
  ClrScr;

  { Fill page 2 on Main Segment, fully with X character }
  FillChar( aDataBuffer, SizeOf( aDataBuffer ), 'X' );
  PrintBuffer( aDataBuffer );

  { Alloc new segment to put data (MSXDOS2 BIOS) }
  If( Not AllocMapperSegment( maprHandle,
                              maprHandle.nPriMapperSlot,
                              UserSegment, aSegments[1] ) )  Then
  Begin
    WriteLn( 'Mapper segment allocation failed' );
    Exit;
  End;

  WriteLn( 'New Segment -> ', aSegments[1], ' successfully allocated' );
  WriteLn( 'Type <enter> to see it''s content' );
  ReadLn;
  ClrScr;

  { Activate page 2 content to the New Segment allocated }
  PutMapperPageByAddress( maprHandle, aSegments[1], Addr( aDataBuffer ) );

  { Fill page 2 on New Segment fully with Y character }
  FillChar( aDataBuffer, SizeOf( aDataBuffer ), 'Y' );

  PrintBuffer( aDataBuffer );

  nActiveSegmentId := aSegments[1];

  { Handle user switch segment contents }
  Repeat
    GotoXY( 1, 19 );
    WriteLn( 'Active Segment -> ', nActiveSegmentId );
    WriteLn;
    WriteLn( '0 - Switch to Main Segment ', aSegments[0] );
    WriteLn( '1 - Switch to New Segment  ', aSegments[1] );
    WriteLn( 'ESC - exit' );
    chKey := ReadKey;

    If( chKey In ['0', '1'] ) Then
    Begin
      nActiveSegmentId := aSegments[Byte( chKey ) - Byte( '0' )];

      { Activate page 2 content to segment chosen by user }
      PutMapperPageByAddress( maprHandle,
                              nActiveSegmentId,
                              Addr( aDataBuffer ) );

      { Show segment content }
      PrintBuffer( aDataBuffer );
    End;
  Until( chKey = #27 );

  WriteLn;

  { Release all segments allocated by the application }
  If( Not FreeMapperSegment( maprHandle,
                             maprHandle.nPriMapperSlot,
                             aSegments[1] ) ) Then
  Begin
    WriteLn( 'SegmentId -> ', aSegments[1], ' deallocation failed' );
    Exit;
  End;

  WriteLn( 'All segments successfully deallocated' );
End.

Em tempo, Ricardo Jurczyk Pinheiro desenvolveu um excelente e mais completo exemplo que faz uso das rotinas de mapper do framework de maneira mais completa, explorando inclusive outras funções de suporte a mapper do framework.

Seu exemplo pode ser visto no link abaixo:

https://github.com/ricardojpinheiro/test/blob/master/mappdemo.pas

Enjoy coding 🙂

Referências

PopolonY2k Youtube channel

Em meados do ano passado, mais especificamente em maio de 2020, comecei a dar um foco no meu canal do Youtube que já existia desde 2006 e que de fato só tinha alguns vídeos curtos de cunho pessoal, bem como resultados de trabalhos em desenvolvimento como foi o caso do Pop!Art, liberado no ínicio desse ano e divulgado no canal há mais de 5 anos.

Pop!Art playlist

Pois bem, decidi reestabelecer o canal como um complemento desse blog, principalmente para deixar registros audio visuais de quaisquer experimentos e trabalhos aqui divulgados.

Como resultado desse primeiro ano do canal tenho liberado cada vez mais vídeos em intervalos menores de tempo e a medida que começo a juntar mais material, fica mais fácil de manter essa constância na liberação de material para o canal.

A idéia é ter registrado no canal, todos os experimentos e informações relacionadas a coisas que gosto, que variam desde desenvolvimento de software a eletrônica em geral, enfim, tudo o que é sobre tecnologia, nova ou velha.

DIY (Do it yourself) playlist

Sugestões de conteúdo são bem vindas, então aguardo sua inscrição no canal e aproveita para clicar no “sininho” para receber as notificações de novos vídeos no canal. 🙂

Channel unboxing playlist

[]’s
PopolonY2k