Vol.904 11.Oct.2024

フォントデータのROM化(1) 合字とは PICミニBB(14)_フォントROMで半角文字表示

F Excel_VBAによるフォントデータのROM化(1)

by fjk

 Excel_VBAを使って、abc899でフォントデータのファイル化、abc901でPICのEPROMへの書込が出来るようになった。そこで、この2つの機能をまとめ、フォントデータのROM化を行いやすくした。

  1. フォントビュアー・ライターのExcelVBA変更・機能追加
    • フォントビットデータを、横方向の1行目データを先に保存し、次に2行目を保存。
    • 通信データ、受信データ、通信ポート番号、通信コマンドセル、次アドレスの計算ボタンを追加
    • 「送信」ボタンを押すと、シリアル通信を実施(SendDataセルの内容を送信)
    • HEXデータファイルは、16進数テキストデータ(CSV)で、C言語データとしてそのまま利用も可
       【 半角Asciiフォントファイル(東雲8x16a.bdfより[一部改])shnm8x16a.csv
      当初、通信機能ボタンは右上のみに設置していたが、文字パターンの近くにも同様のボタンを配置した。
      全フォントを自動でROMに書き込んでも良いが、今回は途中でパターン修正も行えるよう手動にした。
       (注:パターンデータを変更する場合、BDFセル(B5:B20)に16進数を入力すること!)
     
  2. Romライタープログラムの使い方 (注:使用する数値は、port番号を除き、全て16進数です)
    ● 使用する(USBの)シリアル通信ポート番号をCPortセルに入力
    ① BDFファイルを読み込む(必要であれば「カレントフォルダーの変更」も実施)
    ② 文字入力セルに文字を入力(半角/全角の文字とファイルは一致させてください)
    ・コードが一致せず砂時計のまま(サーチ中)の場合、ESCキーを押すと元に戻ります
    ・Excelでアポストロフィ(シングルクォテーション)そのものを入力するには、アポストロフィを2つ続けて入力
    ③「パターン表示」ボタンをクリック(ここで、気に入らなければ、パターンの編集もできる)
    ④「HEXデータ記録」ボタンを押すとFileNameで指定されたファイルに追加モードで保存
    ⑤ 送信するコマンドをCMDセルに、書き込みたいアドレス(20bit)をAddressセルに16進数でセットする
    ・「次番地」ボタンを押すとフォントバイトデータ数をアドレスに加算します
    ⑥「送信データ作成」ボタンを押すと、SendDataセルに送信データを作成し、表示。
    ⑦「送信」ボタンを押すとデータを送信し、受信結果も表示(「送信+」ボタンは送信後addressも加算)。
    ・送受信が正常に終了するとSendDataセルが消去される(2秒以上かかります)
    ・送信内容を手動で行うには、SendDataにデータを手入力後、「送信」ボタンをクリック


全角フォントの例

半角フォントの例(パターンの一部を変更)
【Excel xlsmプログラム】 BDFViewerWriter.xlsm(zip)
 BDFViewerWriter.xlsmは全角用、BDFViewerWriterH.xlsmは半角用(BDFViewerWriter.xlsmに半角ファイルを追加したもの)
 
【Excel VBAプログラム】 BDFViewerWriter.bas(zip)

Option Explicit
Dim filePath As Variant
Dim shtNam As String
Dim RowSize As Long,  CorSize As Long

Sub BDF_Load()
    filePath = Application.GetOpenFilename(filefilter:="BDFファイル(*.bdf),*.bdf")
    If filePath = False Then Exit Sub
    Dim fi As Variant
    fi = Array(Array(1, xlTextFormat))
    Dim maxRow As Long
    Workbooks.OpenText Filename:=filePath, FieldInfo:=fi, Space:=True
    Dim ws As Worksheet
    Set ws = Workbooks.Item(Workbooks.Count).Sheets(1)
    ws.Move After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
    Dim shtNam As String
    shtNam = ActiveSheet.Name                   ' 新シート名を取得
    Worksheets("16dot").Range("C1").Value = shtNam
    maxRow = ThisWorkbook.Sheets(shtNam).Cells(1, 1).End(xlDown).row
    MsgBox shtNam & " をロードしました " & maxRow
    Worksheets("16dot").Select
End Sub

Sub findKey()
    Dim ws As Worksheet
    Set ws = Worksheets(Worksheets.Count)
    Dim kw As String
    kw = "ENCODING"
    RowSize = 16
    CorSize = 16
    Dim code As Long
    code = Worksheets("16dot").Range("B24").Value
    Dim i As Integer
    Dim r As Range
    With ws.Range("A:A")
      Worksheets("16dot").Range("C1").Value = ws.Name
      Set r = .Find(what:="FONTBOUNDINGBOX", LookAt:=xlWhole)
      If r Is Nothing Then
        Exit Sub
      Else
        CorSize = r.Offset(0, 1).Value
        Worksheets("16dot").Range("C2") = CorSize
        RowSize = r.Offset(0, 2).Value
        Worksheets("16dot").Range("E2") = RowSize
      End If
      Set r = .Find(what:=kw, LookAt:=xlWhole)
      Do
        If r Is Nothing Then
          MsgBox ("該当無し")
          Exit Do
        Else
          If r.Next.Value = code Then
            For i = 1 To 16
              If i <= RowSize Then
                Worksheets("16dot").Range("B4").Offset(i) = r.Offset(4 + i).Value
              Else
                Worksheets("16dot").Range("B4").Offset(i) = 0
              End If
            Next i
            Worksheets("16dot").Select
            Exit Do
          Else
            Set r = .FindNext(r)
          End If
        End If
      Loop While Not r Is Nothing
    End With
End Sub

Sub saveHex()
    Dim fso As Object, tso As Object
    Dim strPath  As String, hData() As String
    Dim i As Integer, j As Integer, rofs As Integer, dsz As Integer, cnt As Integer
    Set fso = CreateObject("Scripting.FileSystemObject")
    strPath = Worksheets(Worksheets.Count).Name & ".csv"
    Set tso = fso.OpenTextFile(strPath, 8, True)
    RowSize = Worksheets("16dot").Range("E2")
    CorSize = Worksheets("16dot").Range("C2")
    rofs = 10 + 16 - CorSize
    dsz = CorSize * 2 + 2
    ReDim hData(dsz) As String
    Debug.Print CorSize & " " & dsz
    cnt = 0
    For j = 0 To 1
      For i = 0 To CorSize - 1
        hData(cnt) = Cells(21 + j, rofs + i).Value
        Debug.Print cnt; " "; hData(cnt)
        cnt = cnt + 1
        Next i
  Next j
  hData(cnt) = "//"
  hData(cnt+1) = Cells(23, 2)
  hData(cnt+2) = Cells(23, 4)
  With tso
    .WriteLine Text:=Join(hData, ",")
    .Close  'ファイルのクローズ
  End With
  Set fso = Nothing
  Set tso = Nothing
  MsgBox CurDir() & "\" & strPath & " にデータを追加しました"
End Sub

Sub ShowFolderPicker()
  Dim fd As FileDialog
  Set fd = Application.FileDialog(msoFileDialogFolderPicker)
  With fd
    If .Show = -1 Then
      MsgBox "選択されたフォルダ: " & .SelectedItems(1)
      ChDir Path:=.SelectedItems(1)
    Else
      MsgBox "フォルダが選択されませんでした。"
    End If
  End With
End Sub
Sub SerialEC()
  Dim cmd As String, rdc As String
  Dim row As Integer
  Dim S_Time As Date
  ec.COMn = Range("AB2")
  ec.Setting = "115200,n,8,2"
  ec.AsciiLineTimeOut = 1000
  cmd = Range("AB4")
  ec.AsciiLine = cmd
  row = 8
  Range("AB6:AB40").Value = ""
  S_Time = Now
  Do
    If Now > S_Time + TimeSerial(0, 0, 1) Then
      Exit Do     'TimeOut 2sec
    End If
    DoEvents
    Debug.Print "EC: " & ec.InBuffer
    If ec.InBuffer > 0 Then
      DoEvents
      rcv = ec.AsciiLine
      Cells(row, 28) = rcv
      row = row + 1
      S_Time = Now
    End If
  Loop
  ec.InBufferClear          '受信バッファをクリア
  ec.COMn = -1              '終了処理
  Range("AB4").Value = ""
End Sub

Sub setSerialData()
  Dim sData()     As String
  Dim i As Integer, j As Integer, rofs As Integer, dsz As Integer, cnt As Integer
  RowSize = Worksheets("16dot").Range("E2")
  CorSize = Worksheets("16dot").Range("C2")
  rofs = 10 + 16 - CorSize
  dsz = CorSize * 2 + 1
  ReDim sData(dsz) As String
  If Range("AC2") = "W" Or Range("AC2") = "S" Then
    sData(0) = Range("AC2") & Range("AD2")
    cnt = 1
  Else
    cnt = 0
  End If
  For j = 0 To 1
    For i = 0 To CorSize - 1
      sData(cnt) = Cells(21 + j, rofs + i).Value
      Debug.Print cnt; " "; sData(cnt)
      cnt = cnt + 1
    Next i
  Next j
  Cells(4, 28) = Join(sData, ",")
End Sub

Sub addAddress()
  Dim adr As Variant,  hdt As Variant
  hdt = WorksheetFunction.Hex2Dec(Range("ad2"))
  adr = Val(hdt) + Range("C2") * 2
  Range("AD2") = WorksheetFunction.Dec2Hex(adr, 5)
End Sub

Sub sendPlus()
  Call SerialEC
  Call addAddress
End Sub


G 合字とは  ~文字コードの確認と入力

by fjk

 合字とは、「㍻」や「㋿」のように2つの文字が一つのフォントになったもので、1文字として扱われます。通常の使用では、「れいわ」と読みを入力後、漢字変換を行うと候補として出てきます。「㍻」は文字コードとしてU+337B(JIS:2D5F、sift-JIS:877E)が割り当てられていますが、「㋿」はJISコードには無くユニコードでU+32FFが割り当てられています。
 これらの文字のコード確認や、コードなどで入力するには、以下を実行

【IME】
 「IMEパッド/Unicode」
【ATOK】
 「文字コード/Unicode表」
※ このファイルは合字を表示するため、s-jis文字コードでは表示できないので、utf-8文字コードで記述しています。


P PICミニBBシリーズ(14)  ~フォントROMで半角文字表示

by fjk

 前項の方法で、「ExcelによるフォントデータのROM化」が可能となったので、とりあえずASCII半角フォントパターン(8x16ドット)をEEPROM(25LC1024)の0x00200から0x007FFに書込み、ASCII半角文字を文字コードでグラフィックLCDに表示できるようにした。


JIS半角フォントコード表(ROMのアドレス0x00200から格納)

【ハードウェア】
abc903のBBセットをそのまま利用。
 
【ソフトウェア】
プログラムの基本は「abc903のおまけ」と同じだが、半角文字/文字列を表示する関数を追加した。
半角フォンパターンデータを前項のExcelでEEPROMに書込後、myProject.hファイルの「#define FONT_ROM」を有効にし、再コンパイルすると、グラフィックLCDに返信データが半角文字で表示されるようになる。
 

半角フォント文字列表示例

 ※ 全てのパターンのテストが完全に終わっていないので、バグがあるかも知れません(謝)。
 ※ 電源投入直後、メモリデータが正しく読めないことがあります。
    ->ROMの準備が間に合わない?->しばらく待つと正常になります。

 これまでのソースをここで纏めておくと・・、


MCC設定(Osc = HFINTOSC、Clock = 32MHz、Divider = 1)

eusart設定

spi設定

【abc904-18325.cファイル】 abc904-18325.c(zip)

/*******************************(abc904-18325)*********
 * SPI接続メモリ(24LC1024/23LCV1024) with AQM1248A  
 ******************************************************/

#include "myProject.h"

char     sBf[BFSIZE];                           // 文字列作業エリア
char     RBuf[BFSIZE];                          // シリアル受信バッファ
uint8_t  SFlg;                                  // シリアル受信フラグ

//---- ターミナルにプロンプト文字表示
void prtPrompt(uint8_t m){
    if(m)  printf("# ");                        // 連続書込モード中
    else   printf("$ ");                        // 通常書込モード
}

/*-----------------------------------
 *        Main application
 ------------------------------------*/
void main(void){
    uint8_t cmd;

    SYSTEM_Initialize();
    SSP1CON1bits.SSPEN = 1;                     //SPI1を有効に
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();

    gLCD_int();
    gLCD_clr(0);                                // 黒ベタは0xFF
    puts("Ready\r");                            // 動作確認用
    gLCD_strX(0,0,"Ready");
    prtPrompt(spiMem_SqMode());
    while (1){
        if(SFlg){
            gLCD_clr(0);                        // グラフィック画面消去
            gLCD_strX(0,0,RBuf);                // LCDにコマンド表示
            cmd = RBuf[0];                      // コマンドは第1文字
            #ifndef VBA
                printf("\n\r");
            #endif
            switch(cmd) {                       // 各コマンドの実行
                case 'W': spiMem_cmd_W(RBuf);  break;
                case 'R': spiMem_cmd_R(RBuf);  break;
                case 'Q': spiMem_cmd_Q(RBuf);  break;
                case 'U': spiMem_cmd_U(RBuf);  break;
                case 'S': spiMem_cmd_W(RBuf);  break;
                case 'P': spiMem_cmd_P(RBuf);  break;
                case 'K': spiMem_cmd_K(RBuf);  break;
                                                // 有効なコマンドがなく
                default:  if(spiMem_SqMode()){
                            spiMem_cmd_WSQ(RBuf);
                          }                     // 連続書込モード中なら
                          break;                // 書込シーケンスを実行
            }
            SFlg = 0;
            #ifndef VBA
                prtPrompt(spiMem_SqMode());
            #endif
        }
        IO_RA4_Toggle();
        __delay_ms(500);
    }
}

 
【myProject.hファイル】 myProject.h(zip)

/**************************(myProject.h)***
 *   プロジェクト個別条件指定ファイル     *
 *   (main.cと同じフォルダーに作成)     *
 ******************************************/

#include "mcc_generated_files/mcc.h"
#include "AQM1248A_v3.h"
#include "spi_Mem3.h"

#define  ON    1
#define  OFF   0

#define  VBA                                    // Excel VBA 使用?
//#define FONT_ROM                              // フォントROM有り?

/***** PIC電源電圧 ***********************/
//--- VCC宣言無しは5V(VCC=50と同じ)
#define VCC   50                                // 電源電圧は5V
//#define VCC   33                              // 電源電圧は3.3V
/***** EUSARTモジュール *******************/
#define BFSIZE  120                             // 80 から増やした
//--- ECHO宣言無しはエコー有り(ECHO ONと同じ)
#define ECHO  ON                                // エコー有り
//#define ECHO  OFF                             // エコー無し

/***** MSSPモジュール *********************/
#define MASTER 1
#define SRAVE  2
//#define I2CMODE MASTER                        // マスターとして使用
//#define I2CMODE SRAVE                         // スレーブとして使用
//--- MSSPが一つしか無い場合は I2C宣言無し
//#define I2C  1                                // I2C1を使用
//#define I2C  2                                // I2C2を使用

#if I2CMODE == MASTER
    #if I2C == 1
       #include "mcc_generated_files/examples/i2c1_master_example.h"
    #elif I2C == 2
       #include "mcc_generated_files/examples/i2c2_master_example.h"
    #else
        #include "mcc_generated_files/examples/i2c_master_example.h"
    #endif
#endif

//--- SPIが一つしか無い場合は宣言しない
#define SPIMODE MASTER                          // マスターとして使用
//#define SPIMODE SRAVE                         // スレーブとして使用

#define SPI  1                                  // SPI1を使用
//#define SPI  2                                // SPI2を使用

 
【spi_Mem3.hファイル】 spi_Mem3.c/h(zip)

/******************************(spi_Mem3.h)***************
 *	SPI接続メモリ(25LC1024/23LCV1024)ヘッダーファイル
 ********************************************************/

#include "ctype.h"                              // isxdigit()
#include "stdio.h"                              // puts(),..
#include "stdlib.h"                             // atoi()...
#include "string.h"                             // strtok()...

#define SPIMEM_WRITEcmd 0x02                    // WRITE
#define SPIMEM_READcmd  0x03                    // READ

#define SPIROM_WR_STATS 0x01                    // WRSR
#define SPIROM_WRITEcmd 0x02                    // WRITE
#define SPIROM_READcmd  0x03                    // READ
#define SPIROM_RD_STATS 0x05                    // RDSR
#define SPIROM_WR_ENABL 0x06                    // WREN
#define SPIROM_PG_ERASE 0x42                    // PE Page Erase
#define SPIROM_CP_ERASE 0xC7                    // CE Chip Erase
#define SPIROM_SC_ERASE 0xD8                    // SE Sector Erase

/***  SPI 汎用サブルーチン *****/
//-----  アドレスadrから、1バイトを読み出す
uint8_t SPI_Mem_Read(uint32_t adr);

//-----  アドレスadrに、1バイトdtを書き込む
uint8_t SPI_Mem_Write(uint32_t adr, uint8_t dat);

//-----  アドレスadrからcntバイトをary[]に読み出す
void SPI_Mem_NRead(uint32_t adr,uint8_t *ary,uint16_t cnt);

//-----  アドレスadrからary[]のcntバイトを書き込む
void SPI_Mem_NWrite(uint32_t adr,uint8_t *ary,uint16_t cnt);

//----  シーケンスモードの確認
uint8_t spiMem_SqMode();

//--- SPI-ROMのステータスの取得
uint8_t SPI_Rom_RdStat();

/****  ターミナルコマンド (*strはコマンドライン文字列) *****/
//----- Wコマンド   W[aaaa][,[d0,・・[,]]]
uint16_t spiMem_cmd_W(char *str);

//---- Rコマンド  R[aaaa][,n]
uint16_t spiMem_cmd_R(char *str);

//---- WSQ (連続書込モード)
uint16_t spiMem_cmd_WSQ(char *str);

//---- Qコマンド(連続書込モードの解除)   Q
void spiMem_cmd_Q(char *str);

//---- U(dump)コマンド    U[aaaa]
//       (128バイトのデータをDBuf[]に読み出す)
int spiMem_cmd_U(char *str);

//---- P(Page)コマンド    P[W/R][aaaa]
//        (DBuf[]の128バイトの表示と、読み書き)
int spiMem_cmd_P(char *str);

//---- Kコマンド(漢字表示コマンド)   K[H}
int spiMem_cmd_K(char *str);
【spi_Mem3.cファイル】

/******************************(spi_Mem3.c)***************
 *	SPI接続メモリ(25LC1024/23LCV1024)読み書きライブラリ
 ***********************************************************/

#include  
#include  
#include  "myProject.h"
#define   MBFSIZE 130                           // メモリ操作用バッファーサイズ

//=== グローバル変数 ============
char     Dlm[] = ",";                           // 文字列区切りデリミタ
char     SBuf[20];                              // 文字列処理用バッファー

//--- SPIメモリー用
static uint32_t CrtAdr = 0;                     // カレントアドレス
static uint8_t  DBuf[MBFSIZE];                  // ページメモリ用バッファー
static uint8_t  SqMode = 0;                     // シーケンスモードフラグ
static char     lstCmd;                         // 最終コマンド
static uint8_t  spiRom = 1;                     // 1:spiEEPRom、0:spiRam

/*************************************
 *  SPIC EEPROM function
 **************************************/
//---- ROMステータスの読み出し
uint8_t SPI_Rom_RdStat(){                       // ROMのみ使用
    uint8_t stat;
    CS0_SetLow();
    SPI1_ExchangeByte(SPIROM_RD_STATS);
    stat = SPI1_ExchangeByte(0xAA);             // 0xAAはダミー
    CS0_SetHigh();
    return stat;
}

//---- コマンドと24ビットアドレスを送信 
void sendAdr(uint8_t cmd, uint32_t adr){
    if(spiRom) CS0_SetLow();                    // spiRom(25LC1024)選択
    else       CS1_SetLow();                    // spiRam(23LCV1024)選択
    SPI1_ExchangeByte(cmd);                     // send Command
    SPI1_ExchangeByte((uint8_t)(adr>>16));
    SPI1_ExchangeByte((uint8_t)(adr>>8));
    SPI1_ExchangeByte((uint8_t)adr);
} 

//-----  アドレスadrから、1バイトを読み出す
uint8_t SPI_Mem_Read(uint32_t adr){
    uint8_t dat;
    if(adr < 0x80000) spiRom = 1;               // spiRom(25LC1024)指定
    else              spiRom = 0;               // spiRam(23LCV1024)指定
    sendAdr(SPIMEM_READcmd,adr);                // send Read_CMD & Address
    dat = SPI1_ExchangeByte(0xAA);
    if(spiRom) CS0_SetHigh();                   // spiRomの場合
    else       CS1_SetHigh();                   // spiRamの場合
    return dat;
}

//-----  アドレスadrに、1バイトdatを書き込む
uint8_t PI_Mem_Write(uint32_t adr, uint8_t dat){
    if(adr < 0x80000){
        spiRom = 1;                             // spiRom(25LC1024)指定
        CS0_SetLow();
        SPI1_ExchangeByte(SPIROM_WR_ENABL);     //Set WriteEnableBit
        CS0_SetHigh();
    }else              spiRom = 0;              // spiRam(23LCV1024)
    sendAdr(SPIMEM_WRITEcmd,adr);               // send W_CMD & Address
    SPI1_ExchangeByte(dat);
    if(spiRom){                                 // spiRomの場合
        CS0_SetHigh();
        __delay_ms(6);
    }else{                                      // spiRamの場合
        CS1_SetHigh();
    }
    return dat;
}

//-----  アドレスadrからcntバイトをary[]に読み出す
void SPI_Mem_NRead(uint32_t adr, uint8_t *ary, uint16_t cnt){
    if(adr < 0x80000) spiRom = 1;               // spiRom(25LC1024)指定
    else              spiRom = 0;               // spiRam(23LCV1024)指定
    sendAdr(SPIMEM_READcmd,adr);                // send R_CMD & Address
    SPI1_ReadBlock(ary, cnt);                   // block read
    if(spiRom){
        CS0_SetHigh();
        while(SPI_Rom_RdStat() & 1);
    }else{
        CS1_SetHigh();
    }
}

//-----  アドレスadrからary[]のcntバイトを書き込む
void SPI_Mem_NWrite(uint32_t adr, uint8_t *ary, uint16_t cnt){
    if(adr < 0x80000){
        spiRom = 1;                             // spiRom(25LC1024)指定
        CS0_SetLow();
        SPI1_ExchangeByte(SPIROM_WR_ENABL);     // SetWriteEnableBit
        CS0_SetHigh();
    }else{
        spiRom = 0;                             // spiRam(23LCV1024)指定
    }
    sendAdr(SPIMEM_WRITEcmd,adr);               // send W_CMD & Address
    SPI1_WriteBlock(ary,cnt);                   //  block write
    if(spiRom){
        CS0_SetHigh();
        while(SPI_Rom_RdStat() & 1);
    }else{
        CS1_SetHigh();
    }
}

/****** 汎用サブルーチン ********************/
//---- ページバッファープリント
void prt_PBf(){
    uint8_t i;
    for(i = 0; i < 128; i++){                   // 16文字x8行字表示
        #ifdef VBA
            if(i % 16 == 0) printf("\r");
        #else
            if(i % 16 == 0) printf("\n\r");
        #endif
        printf(" %02X",DBuf[i]);
    }
    puts("\r");
}

//---- 16進文字列を10進数に変換
uint32_t my_xtoi(char *str){
    uint32_t dec;
    dec = strtoul(str,NULL,16);
    return (uint32_t)dec;
}

/************************************
 * 	コマンドアクション
 ************************************/
//----- Wコマンド   W[aaaa][,[d0,・・[,]]]
uint16_t spiMem_cmd_W(char *str){
    char     *pt;                               // 文字列操作用ポインタ
    uint8_t  last;                              // 文字列の最後の位置
    uint32_t res = 0;                           // Hex文字数値変換結果
    uint8_t  dt = 0;                            // 書き込むバイトデータ
    uint16_t cnt = 0;                           // 書き込んだバイト数

    lstCmd = str[0];
    if(strlen(str)==1){                         // 'W'のみなら
        SqMode = 1;                             // 連続書込モードにセット
        #ifndef VBA
        	puts("SqMode ON\n\r");
        #endif
        return 0;                               // データは書き込まない
    }
    last = (uint8_t)strlen(str)-1;              // 文字列の行末位置を取得
    if(str[last] == ','){                       // 行末がコンマなら
        SqMode = 1;                             // 連続書込モードにセット
        #ifndef VBA
        	puts("SqMode ON\n\r");
        #endif
        str[last]='\0';                         // 行末のコンマを消す
    }
    if(str[1]!=','){                            // 第2文字がコンマか?
        pt = strtok(str+1,Dlm);                 // コマンドの次文字から
        if(pt != NULL){                         // アドレスデータがある
            res = my_xtoi(pt);
            CrtAdr = res;
        }
        pt = strtok(NULL,Dlm);                  // 次文字列取込
    }else{
        pt = strtok(str+1,Dlm);                 // 文字列取込
    } 
    do{
        if(pt != NULL){                         // データがあるか?
            res = my_xtoi(pt);
            dt = (uint8_t)res;
             if(lstCmd=='W'){
                SPI_Mem_Write(CrtAdr,dt);       // データを書き込む
            }else if(lstCmd == 'S'){
                DBuf[CrtAdr & 0x7F]= dt;  
            }
            sprintf(SBuf,"%05lX < %02X",CrtAdr,dt);
            #ifdef VBA
                printf("%s\r",SBuf);
            #else
                printf("%s\n\r",SBuf);
            #endif
            prtHstr_LnClr(0,16,SBuf);
            CrtAdr++; cnt++; 
            pt = strtok(NULL,Dlm);              // 次文字へ
        }
    }while(pt != NULL);                         // データがあるだけ繰返す
    return cnt;                                 // 書き込んだ文字数を返す
}

//---- Rコマンド  R[aaaa][,n]
uint16_t spiMem_cmd_R(char *str){
    char *pt;                                   // 文字列操作用ポインタ
    uint16_t n = 1;                             // 指定された読込バイト数
    uint32_t res = 0;                           // Hex文字数値変換結果
    uint8_t  dt;                                // 読み込んだバイトデータ
    uint16_t cnt = 0;                           // 実際に読込んだバイト数
    uint16_t i;                                 // ループ変数

    lstCmd = str[0];
    if(strlen(str) > 1){
        if(str[1]==','){
            pt = strtok(str+2,Dlm);
            if(pt != NULL){                     // データ無し?
                res = my_xtoi(pt);
                n = (uint16_t)res;
            }
        }else{
            pt = strtok(str+1,Dlm);
            if(pt != NULL){                     // addressがある?
                res = my_xtoi(pt);
                CrtAdr = res;
            }
            pt = strtok(NULL,Dlm);             	// 次文字へ
            if(pt != NULL){                     // データ無し?
                res = my_xtoi(pt);
                n = (uint16_t)res;
            }
        }
    }
    for(i = 0; i < n; i++ ){
        dt = SPI_Mem_Read(CrtAdr);              // データを読み出す
        sprintf(SBuf,"%05lX > %02X",CrtAdr,dt);
        #ifdef VBA
        	printf("%s\r",SBuf);
        #else
        	printf("%s\n\r",SBuf);
        #endif
        prtHstr_LnClr(0,16,SBuf);
        CrtAdr++; cnt++;
    }
    SqMode = 0;
    return cnt;                                 // 読込んだデータ数を返す
}

//---- WSQ (連続書込モード)
uint16_t spiMem_cmd_WSQ(char *str){
    char     *pt;                               // 文字列操作用ポインタ
    uint8_t  dt;                                // 書き込むバイトデータ
    uint32_t res;                               // Hex文字数値変換結果
    uint16_t cnt = 0;                           // 実際に読込んだバイト数

    pt = strtok(str,Dlm);
    while(pt != NULL){                          // データがあるだけ繰返す
        res = my_xtoi(pt);
        dt = (uint8_t)res;
        if(lstCmd == 'W'){
            SPI_Mem_Write(CrtAdr,dt);          // データを書き込む
        }else if(lstCmd=='S'){
			DBuf[CrtAdr & 0x7F]= dt;  
        }
        sprintf(SBuf,"%05lX < %02X",CrtAdr,dt);
        #ifdef VBA
        	printf("%s\r",SBuf);
        #else
        	printf("%s\n\r",SBuf);
        #endif
        prtHstr_LnClr(0,16,SBuf);
        CrtAdr++; cnt++;
        pt = strtok(NULL,Dlm);                  // 次文字列へ
    }
    return cnt;                                 // 書込んだデータ数を返す
}

//---- Qコマンド(連続書込モードの解除)   Q
void spiMem_cmd_Q(char *str){
    lstCmd = str[0];
	SqMode = 0;
	#ifndef VBA
		puts("SqMode OFF\r");
	#endif
}

//---- U(dump)コマンド    U[aaaa]
//       (128バイトのデータをDBuf[]に読み出す)
int spiMem_cmd_U(char *str){
    char    *pt;                                // 文字列操作用ポインタ
    uint32_t res;                               // Hex文字数値変換結果
    uint32_t ad;                                // 指定アドレス

    lstCmd = str[0];
    pt = strtok(str+1,Dlm);
    if(pt != NULL){                             // アドレス有り?
        res = my_xtoi(pt);
        CrtAdr = res;
    }
    ad = CrtAdr & 0xFFFF80;                     // 128バイト単位に 
    SPI_Mem_NRead(ad, DBuf, 128);               // 128バイトをDBuf[]に読出
    sprintf(SBuf,"%05lX - %05lX", ad, ad+127);
    #ifdef VBA
      	printf("%s",SBuf);
    #else
       	printf("%s\r",SBuf);
    #endif
    prtHstr_LnClr(0,16,SBuf);
    prt_PBf();
    SqMode = 0;
    return 0;
}

//---- P(Page)コマンド    P[R/W][aaaa]
//       DBuf[]の128バイトの表示とメモリに読み書き)
int spiMem_cmd_P(char *str){
    char     *pt;                               // 文字列操作用ポインタ
    uint32_t res;                               // Hex文字数値変換結果
    uint32_t ad;                                // 指定アドレス

    lstCmd = str[0];
    if(strlen(str)==1){
        printf("PageBuffer");
        prt_PBf();
        return 0;
    }
    if(str[1]=='R'){
        spiMem_cmd_U(str+1);
        return 0;
    }
    if(str[1] != 'W') return -1;                // 第2文字がW?
    pt = strtok(str+2,Dlm);
    if(pt != NULL){                             // アドレス有り?
        res = my_xtoi(pt);
        CrtAdr = res;
    }
    ad = CrtAdr & 0xFFFF80;                     // 128バイト単位に
    SPI_Mem_NWrite(ad,DBuf,128);                // DBuf[]の128バイト書込
    sprintf(SBuf,"PW:%05lX - %05lX",ad,ad+127);
    #ifdef VBA
      	printf("%s\r",SBuf);
    #else
       	printf("%s\n\r",SBuf);
    #endif    
    prtHstr_LnClr(0,16,SBuf);
    SqMode = 0;    
    return 0;
}

//----  シーケンスモードの確認
uint8_t spiMem_SqMode(){
	return SqMode;
}

//---- K(漢字)表示コマンド  K[H] 
int spiMem_cmd_K(char *str){
    char     *kp;                               // 文字列操作用ポインタ
    uint8_t i;
    kp = (char *)DBuf;
    if(str[1] == 'H'){                          // 第2文字がHか?
        for(i = 0; i < 8; i++){
            gLCD_nk16X(8*i,32,kp+16*i,8);
        }
    }else{
        for(i = 0;i < 4; i++){
            gLCD_nk16X(16*i,32,kp+32*i,16);
        }      
    }
    SqMode = 0;
    return i;
}

 
【AQM1248A_v3.hファイル】 AQM1248A_v3.c/h + Font_5x7.h(zip)

/******************************(AQM1248A_v3.h)************
 *   Grafic LCD  AQM1248A_m.h 用ライブラリ(FONT別)
 **********************************************************/
/*---  G_LCDを初期化する */
void gLCD_int(void);

/*---  G_LCDのRAMの書込みアドレスを指定する
 *	  表示文字位置(xpos,ypos) */
void gLCD_posyx(uint8_t xpos, uint8_t ypos);

/*---  G_LCDのRAMを全消去(指定データで埋める)
 *	  埋めたい1バイトデータ(dat) */
void gLCD_clr(char dat);

/*---  G_LCDにchrコードの文字パターンを表示
 *    表示位置(ypos,xpos)、表示文字(ch)
 *  ・戻り: 次表示X文字位置  */
uint8_t gLCD_chrX(uint8_t xpos, uint8_t ypos, char ch);

/*---  文字列strをG_LCDに表示する
 *	  表示位置(xpos,ypos)、表示文字列(str)
 * ・戻り: 次表示X文字位置  */
uint8_t gLCD_strX(uint8_t xpos, uint8_t ypos, char *str);

/*---  ビットパターンをG_LCDに表示する
 *	表示位置(xpos, ypos)、パターン(*ptn),バイト数(n)
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_ptnX(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t n);

/*---  指定したdatで指定数nだけ表示
 *	表示位置(xpos, ypos)、データ(dat)・・1バイト, 転送数(n) 
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_clrX(uint8_t xpos, uint8_t ypos, char dat, uint8_t n);

/*--- バイト単位で16ドットパターン(漢字など)の表示
 *	  表示位置(xpos, ypos)、データ配列(k)
 *    フォントアドレス(*pKj)、 横ドット数(cdt) 
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_nk16X(uint8_t xpos, uint8_t ypos, char *pKj, uint8_t cdt);

//---- バイtト単位で半角(8x16)文字表示(次xpos位置を返す)
/*	  表示位置(xpos, ypos)、半角文字コード(chCode)
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode);

//---- バイト単位で半角文字列表示(次xpos位置を返す)-----
/*	  表示位置(xpos, ypos)、半角文字列(*str)
 *  ・戻り: 次表示X文字位置 */
uint8_t gLCD_HstrX(uint8_t xpos, uint8_t ypos, char *str);

//---- バイト単位で行をクリアして半角文字列表示(次xpos位置を返す)
/*	  表示位置(xpos, ypos)、半角文字列(*str)
 *  ・戻り: 次表示X文字位置 */
uint8_t prtHstr_LnClr(uint8_t xpos, uint8_t ypos, char* str);

/*========================================*
 *     ドット単位位置で描画               *
 *========================================*/
/*---  ドット単位で点を描く
 *    表示位置(xpos, ypos)、表示色(col、0:白/1:黒/8:反転)*/
 void gLCD_PSet(uint8_t xpos, uint8_t ypos, uint8_t col);

/*---  ドット単位で文字を描く(次xpos位置を返す)
 *    表示位置(xpos, ypos)、表示文字コード(ch)
 *    表示色(col、0:白/1:黒/8:反転)
 * ・戻り: 次表示X文字位置 */
 uint8_t gLCD_PutChr(uint8_t xpos, uint8_t ypos, char ch, uint8_t col);

/*---  ドット単位で文字列を描く(次xpos位置を返す)
 *    表示位置(xpos, ypos)、表示文字列(*str)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
 uint8_t gLCD_PutStr(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t col);

/*-------ドット単位でパターンを描く(次xpos位置を返す)
 *    表示位置(xpos, ypos)、表示パターン(*ptn)・・バイト単位
 *    転送数(n)、表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
 uint8_t gLCD_PutPtn(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t n, uint8_t col);

/*----------ドット単位で直線を描く
 *    開始位置(x0,y0)、終了位置(x1,y1)、
 *    表示色(col、0:白/1:黒/8:反転)*/
 void gLCD_Line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t col);

/*--- バイト単位で16ドットパターン(漢字など)の表示
 *    表示位置(xpos, ypos)、データ配列(k)
 *    データ要素番号(kj)、 横ドット数(cln)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
uint8_t Put_nK16(uint8_t xpos, uint8_t ypos, char *k, uint8_t cln, uint8_t col);

//---- ドット単位で半角文字表示(次xpos位置を返す)
/*    表示位置(xpos, ypos)、半角文字コード(chCode)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
uint8_t Put_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode,uint8_t col);

//---- ドット単位で半角文字列を表示(次xpos位置を返す)
/*    表示位置(xpos, ypos)、半角文字列(*str)
 *    表示色(col、0:白/1:黒/8:反転)
 *  ・戻り: 次表示X文字位置 */
uint8_t Put_HstrX(uint8_t xpos, uint8_t ypos, char *str, uint8_t col);

 
【AQM1248A_v3.cファイル】

/***********************************(AQM1248A_v3.c)*******
 *     AQM1248A グラフィックライブラリ(spi-vRam付き)
 **********************************************************/

#include "myProject.h"
#include "Font_5x7.h"

#define VRAM_ADR    0x80000
#define LCG_C_SIZE  128
#define HASC_OFS    0x00200
#define H_BLANK     0x007F0

static uint8_t vBf[32];                         // フォントパターン用バッファー

//--- SPI-vRam アクセス関数
uint8_t vRam_read(uint8_t xpos, uint8_t ypos){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	return SPI_Mem_Read(adr);
}

void vRam_write(uint8_t xpos, uint8_t ypos, uint8_t dat){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	SPI_Mem_Write(adr, dat);
}

void vRam_Nread(uint8_t xpos,uint8_t ypos,char *ptn,uint8_t n){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	SPI_Mem_NRead(adr,(uint8_t *)ptn,n);
}

void vRam_Nwrite(uint8_t xpos,uint8_t ypos,char *ptn,uint8_t n){
	uint32_t adr;
	adr = VRAM_ADR + (uint32_t)ypos * LCG_C_SIZE + xpos;
	SPI_Mem_NWrite(adr,(uint8_t *)ptn,n);
}

//-------- G-LCDを初期化 ------------------------------------
void gLCD_int (void){
    gCS_SetLow();                               // gLCDセレクト有効
    gRS_SetLow();                               // コマンドデータ指定
    SPI1_ExchangeByte(0xAE);                    // Display = OFF
    SPI1_ExchangeByte(0xA0);                    // ADC = normal
    SPI1_ExchangeByte(0xC8);                    // C.output = revers
    SPI1_ExchangeByte(0xA3);                    // bias = 1/7
    SPI1_ExchangeByte(0x2C);                    // power control 1
    __delay_ms(2);                              // 2mS遅延
    SPI1_ExchangeByte(0x2E);                    // power control 2
    __delay_ms(2);                              // 2mS遅延v
    SPI1_ExchangeByte(0x2F);                    // power control 3
    SPI1_ExchangeByte(0x23);                    // Vo ratio set
    SPI1_ExchangeByte(0x81);                    // E-volume mode
    SPI1_ExchangeByte(0x1C);                    // E-volume value
    SPI1_ExchangeByte(0xA4);                    // 全点灯しない
    SPI1_ExchangeByte(0x40);                    // start line = 0
    SPI1_ExchangeByte(0xA6);                    // 白黒反転しない
    SPI1_ExchangeByte(0xAF);                    // Display = ON
    gCS_SetHigh();                              // gLCDセレクト無効
}

//-------- G-LCDのデータを全消去(指定データで埋める)---
void gLCD_clr (char dat){
    uint8_t x, y;
    gCS_SetLow();                               // gLCDセレクト有効
    for(y = 0; y < 6; y++){
        gRS_SetLow();                           // コマンド指定
        SPI1_ExchangeByte(0xB0 + y);
        SPI1_ExchangeByte(0x10);
        SPI1_ExchangeByte(0x00);
        gRS_SetHigh();                          // 表示データ指定
        for(x = 0; x < 128; x++){
            SPI1_ExchangeByte(dat);
        }
    }
    gCS_SetHigh();                              // gLCDセレクト無効
    for(y = 0; y < 6; y++){
        for(x = 0; x < 128; x++){
            vRam_write(x,y,dat);                // vRamクリア
        }
    }
}

//-------- カーソル位置指定 -----------------------------------
void gLCD_posXY(uint8_t xpos, uint8_t ypos){
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetLow();                               // コマンド指定
    SPI1_ExchangeByte(0xB0 | (ypos >> 3));
    SPI1_ExchangeByte(0x10 | (xpos >> 4));
    SPI1_ExchangeByte(xpos & 0x0F);
    gCS_SetHigh();                              // チップセレクト無効
}

//-------- バイト単位で文字表示(次xpos位置を返す) ---------
uint8_t gLCD_chrX(uint8_t xpos, uint8_t ypos, char chr){
    uint8_t i, sx, yAdr, ptn;
    chr -= 0x20;                                //配列アドレスを計算
    gLCD_posXY(xpos, ypos);                     //表示位置を指定
    sx = xpos;                                  // posxを保存
    yAdr = ypos >> 3;
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    for(i = 0; i < 5; i++) {                    //データを順に取得
        ptn = Font[chr][i];
        if(ptn == 0xFF)  break;                 //幅狭文字なら抜ける
        vBf[i] = ptn;
        SPI1_ExchangeByte(ptn);
        xpos++;
    }
    vBf[i] = 0;
    SPI1_ExchangeByte(0);                       //文字間隔を空ける
    xpos++;
    gCS_SetHigh();                              // チップセレクト無効
    vRam_Nwrite(sx,ypos,(char *)vBf, i);        // vRamに書き込む 
    return xpos;                                //次表示位置を返す
}

//-------- バイト単位で文字列表示(次xpos位置を返す)-----
uint8_t gLCD_strX(uint8_t xpos, uint8_t ypos, char *str){
    while(*str)  xpos = gLCD_chrX(xpos, ypos, *str++);
    return xpos;                                //次表示位置を返す
}

//-------- バイト単位でパターンを表示(次xpos位置を返す)
uint8_t gLCD_ptnX(uint8_t xpos, uint8_t ypos, char *ptn, uint8_t n){
    uint8_t i, yAdr;
    gLCD_posXY(xpos, ypos);                     // 表示位置を指定
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    yAdr = ypos >> 3;
    for(i = 0; i < n; i++){
         SPI1_ExchangeByte(*(ptn + i));
    }
    gCS_SetHigh();                              // チップセレクト無効
    vRam_Nwrite(xpos,ypos,ptn,n);
    return xpos + n;                            // 次表示位置を返す
}

//---- バイト単位でn個の指定データで埋める(次xpos位置を返す)
uint8_t gLCD_clrX(uint8_t xpos, uint8_t ypos, char dat, uint8_t n){
    uint8_t i, yAdr;
    gLCD_posXY(xpos,ypos);                      // 表示位置を指定
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    yAdr = ypos >> 3;
    for(i = 0; i < n; i++) {
        SPI1_ExchangeByte(dat);
    }
    gCS_SetHigh();                              // チップセレクト無効
    for(i=0;i<// 次開始位置を返す
}

//---- バイト単位で(縦)16ドットパターン(漢字など)の表示
/*	xpos: X位置、	ypos: Y位置
 *	*pKj: 漢字パターンデータポインタ、 cdt: 漢字横ドット数
 *---------------------------------------------------- */
uint8_t gLCD_nk16X(uint8_t xpos, uint8_t ypos, char *pKj, uint8_t cdt){
 	gLCD_ptnX(xpos, ypos,(char *)pKj, cdt); 
	xpos = gLCD_ptnX(xpos, ypos+8, (char *)(pKj + cdt),cdt);
	return xpos;
}

//---- 半角(8x16)文字表示(次xpos位置を返す)-----
uint8_t gLCD_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode){
    uint32_t adr;
    if((chCode >= 0x20) & (chCode < 0x7F)){
        adr = (chCode - 0x20) * 16 + HASC_OFS;
    }else{
        adr = H_BLANK;                          // 半角ブランク表示
    }
    SPI_Mem_NRead(adr,(uint8_t *)vBf,16);
    xpos = gLCD_nk16X(xpos, ypos, (char *)vBf, 8); 
    return xpos;
}

//-------- バイト単位で半角文字列表示(次xpos位置を返す)-----
uint8_t LCD_HstrX(uint8_t xpos, uint8_t ypos, char *str){
    while(*str)  xpos = gLCD_HchrX(xpos, ypos, *str++);
    return xpos;                                //次表示位置を返す
}

//--- 行をクリアして半角文字列表示(次xpos位置を返す)
uint8_t prtHstr_LnClr(uint8_t xpos, uint8_t ypos,char* str){
    gLCD_clrX(0,ypos  ,0,LCG_C_SIZE);
    #ifdef FONT_ROM
        gLCD_clrX(0,ypos+8,0,LCG_C_SIZE);
        return  gLCD_HstrX(xpos,ypos,str);
    #else
        return  gLCD_strX(xpos,ypos,str);
    #endif
}

/****** ドット単位位置で描画 ******/
//----------ドット単位で点を描く----------------------
void gLCD_PSet(uint8_t xpos, uint8_t ypos, uint8_t col){
    uint8_t yAdr, yBit;                         // yアドレス、ビット位置
    uint8_t ptn = 0x01;                         // ビットパターン
    uint8_t dat;
    if((xpos > 127) || (ypos > 47))  return;
    dat = vRam_read(xpos, ypos);
    yAdr = ypos >> 3; yBit = ypos & 0x07;
    ptn <<= yBit;
    switch(col){
        case 0:	dat &= (~ptn);	break;
        case 1: dat |= ptn;		break;
        case 8: dat ^= ptn;		break;
    }
    gLCD_posXY(xpos,ypos);  
    gCS_SetLow();                               // チップセレクト有効
    gRS_SetHigh();                              // 表示データ指定
    SPI1_ExchangeByte(dat);
    gCS_SetHigh();                              // チップセレクト無効
    vRam_write(xpos, ypos, dat);
}

//-------ドット単位で文字を描く(次xpos位置を返す)-------
uint8_t gLCD_PutChr(uint8_t xpos, uint8_t ypos, char ch, uint8_t col){
    uint8_t i, j, ptn, msk;                     //ビットマスクデータ
            //有効フォントデータでないなら何もしない
    if((ch < 0x20)||(ch > 0x7f)) return xpos;
    ch -= 0x20;                                 //配列アドレスを計算
    for(i = 0; i < 5; i++){
        msk = 0x01;
        ptn = (uint8_t)Font[ch][i];
        if(ptn == 0xFF) break;                  //幅狭文字なら抜ける
        for(j = 0; j < 8; j++){
            if(ptn & msk)    gLCD_PSet(xpos + i,ypos + j,col);
            msk <<= 1;
        }
    } 
    return xpos + i + 1;
}

//-------ドット単位で文字列を描く(次xpos位置を返す)---
uint8_t gLCD_PutStr(uint8_t xpos, uint8_t ypos, char * str, uint8_t col){
    while(*str)                                 //文字列終端まで継続
        xpos = gLCD_PutChr(xpos,ypos,*str++,col);
    return xpos;                                //次表示位置を返す
}

//-------ドット単位でパターンを描く(次xpos位置を返す)-------
uint8_t gLCD_PutPtn(uint8_t xpos, uint8_t ypos, char * ptn, uint8_t n, uint8_t col){
    uint8_t i, j, msk;                          //ビットマスクデータ
    for(i = 0; i < n; i++){
        msk = 0x01;
        for(j = 0; j < 8; j++){
            if(*ptn & msk)    gLCD_PSet(xpos+i,ypos+j,col);
            msk <<= 1;
        }
        ptn++;
    }
    return xpos + i;
}

// --- ABS、SWAP関数定義

void swap_uint8_t(uint8_t *a, uint8_t *b){
	uint8_t tmp; tmp = *a; *a = *b; *b = tmp;
}
#define ABS(a)    (((a)>0) ? (a) : -(a))

//----------ドット単位で直線を描く-------------------
void gLCD_Line(uint8_t x0, uint8_t y0, uint8_t x1, uint8_t y1, uint8_t col){
    uint8_t steep, x, y, tmp;
    int   ystep, deltax, deltay, error;
    steep = (ABS(y1 - y0) > ABS(x1 - x0));
    if(steep){    swap_uint8_t(&x0,&y0); swap_uint8_t(&x1,&y1); }
    if(x0 > x1){  swap_uint8_t(&x0,&x1); swap_uint8_t(&y0,&y1); }
    deltax = x1 - x0;                           //  傾き計算
    deltay = abs(y1 - y0);
    error = 0;
    y = y0;
    if(y0 < y1) ystep = 1; else ystep = -1;
    for(x = x0; x < x1 + 1; x++){
        if(steep) gLCD_PSet(y,x,col); 
        else      gLCD_PSet(x,y,col);
        error += deltay;
        if((error << 1) >= deltax){
            y += ystep;
            error -= deltax;
        }
    }
}

//---- ドット単位で(縦)16ドットパターンの表示(次xpos位置を返す)
/*	xpos: X位置、	ypos: Y位置,		col: 表示モード
 *	*pKj: 漢字パターンデータポインタ、	cdt: 漢字横ドット数
 *---------------------------------------------------- */
uint8_t Put_nK16(uint8_t xpos, uint8_t ypos, char *pKj, uint8_t cdt, uint8_t col){
 	gLCD_PutPtn(xpos, ypos, (char *)pKj, cdt, col); 
	xpos = gLCD_PutPtn(xpos, ypos+8, (char *)(pKj + cdt),cdt, col);
	return xpos;
}

//---- ドット単位で半角文字表示(次xpos位置を返す)
uint8_t Put_HchrX(uint8_t xpos, uint8_t ypos, uint8_t chCode,uint8_t col){
    uint32_t adr;
    if((chCode >= 0x20) & (chCode < 0x7F)){
        adr = (chCode - 0x20) * 16 + HASC_OFS;
    }else{
        adr = H_BLANK;                          // 半角ブランク
    }
    SPI_Mem_NRead(adr,(uint8_t *)vBf,16);
    xpos = Put_nK16(xpos, ypos, (char *)vBf, 8, col);       
    return xpos;
}

//---- ドット単位で半角文字列を表示(次xpos位置を返す)
uint8_t Put_HstrX(uint8_t xpos, uint8_t ypos, char *str, uint8_t col){
    while(*str)  xpos = Put_HchrX(xpos, ypos, *str++, col);
    return xpos;                                //次表示位置を返す
}

【EUSART】   EUSARTの設定 (abc900)
USBシリアル通信の設定
【PICライブラリ】 ライブラリの使い方 (abc840)
使用するライブラリの追加など


※プログラムのリストをハイライト無しのスタイルで見る場合はここをクリック


※ 本レポートの参考・利用は、あくまでも自己責任でお願いします。


フォントデータのROM化(1) 合字とは PICミニBB(14)_フォントROMで半角文字表示