目次

画像処理下準備3

 カメラから取得した画像データを、カラー液晶ディスプレイ
 に表示して確認するのが、簡単な動作テストになりますが、
 手持ちがないので、モノクログラフィック液晶に画像を表示
 します。

 利用するモノクログラフィック液晶は、128x64のTG12864を
 使います。(傷を避けるために、シートを貼っています。)



 ピン数の少ないマイコンに接続できるように、シフトレジスタ
 を利用し、インタフェース回路は、次のようにしました。



 回路を実装した基板は、次のようになります。



 マイコンは、10ピンを次のように使います。

 キャラクタ型のLCDと似たインタフェースで
 2つのレジスタを持っていると考えられます。

 レジスタへのデータ転送は、次のシーケンスとします。
  1. LCW_RSの論理値を、指定値に
  2. シフトレジスタに8ビットデータ転送
  3. LCW_EをLに設定
  4. LCW_RWをLに設定
  5. LCW_EをHに設定
  6. ディレイ
  7. LCW_EをLに設定
  8. LCW_RWをHに設定
 液晶は、64x64の画面を左右に2枚持っているので  上のシーケンスをひとつの関数にして、CS1、CS2  により左、右の表示領域を選びます。  これらの操作を加えて、液晶の表示のために作成  したテストファームウエアは、以下です。  (ATmega644Pを使っています。) #include <avr/io.h> #include <avr/interrupt.h> typedef unsigned char UBYTE ; typedef signed char SBYTE ; typedef unsigned short UWORD ; typedef signed short SWORD ; typedef unsigned long ULONG ; typedef signed long SLONG ; #define OFF 0 #define ON 1 #define LCD_DAT 7 #define LCD_CLK 6 #define LCD_RST 5 #define LCD_CS2 4 #define LCD_CS1 3 #define LCD_RS 2 #define LCD_RW 1 #define LCD_E 0 #define LCD_RS_H 1 #define LCD_RS_L 0 #define MASKFF 0xFF #define MASK80 0x80 #define MASK40 0x40 #define MASK20 0x20 #define MASK10 0x10 #define MASK08 0x08 #define MASK04 0x04 #define MASK02 0x02 #define MASK01 0x01 #define MASKF0 0xF0 #define SEL_LEFT 2 #define SEL_RIGHT 1 #define SEL_NONE 0 #define GMAX 512 #define YMAX 8 #define XMAX 64 volatile UBYTE eflag ; volatile UBYTE lgdat[GMAX] ; volatile UBYTE rgdat[GMAX] ; volatile UBYTE lgdatx[GMAX] ; volatile UBYTE rgdatx[GMAX] ; volatile UBYTE mode ; volatile ULONG timcnt ; /*--------------------------------*/ /* Insert user functions protoype */ /*--------------------------------*/ void user_initialize(void); void update_led(UBYTE x); void send_data(UBYTE which,UBYTE x); void select_plane(UBYTE x); void display(UBYTE x); void set_address(UBYTE x); void set_page(UBYTE x); void set_start_line(UBYTE x); void set_display_data(UBYTE x); void display_lcd(UBYTE which,UBYTE *x); void init_lcd(void); void display_bw(UBYTE x); void display_black(void); void display_white(void); void rotate(UBYTE *x,UBYTE *y); void rotate_gdat(UBYTE *s,UBYTE *d); void delay_ms(UBYTE x); /*------*/ /* main */ /*------*/ int main(void) { UWORD i ; /* initialize I/O */ user_initialize(); /* enable interrupt */ sei() ; /* initialize LCD */ init_lcd(); /* endless loop */ while ( ON ) { /* get DIP switch data*/ PORTA = ((PINA & MASKF0) >> 4); /* select mode */ if ( eflag ) { /* clear flag */ eflag = OFF ; /* get mode */ mode = (PIND & 3) ; PORTA = (mode << 4) ^ MASKF0 ; /* handling */ if ( mode == 1 ) { display_white(); } if ( mode == 2 ) { display_black(); } if ( mode == 3 ) { init_lcd(); } if ( mode == 0 ) { for ( i = 0 ; i < GMAX ; i++ ) { /* initialize left area */ *(lgdatx+i) = 0x55 ; /* initialize right area */ *(rgdatx+i) = 0xaa ; if ( (i & 3) == 0 ) { *(lgdatx+i) = 0x00 ; *(rgdatx+i) = 0xff ; } } /* rotate */ rotate_gdat((UBYTE *)lgdat,(UBYTE *)lgdatx); rotate_gdat((UBYTE *)rgdat,(UBYTE *)rgdatx); /* show */ display_lcd(SEL_LEFT ,(UBYTE *)lgdatx); display_lcd(SEL_RIGHT,(UBYTE *)rgdatx); } } } /* dummy */ return 0 ; } /*-----------------------*/ /* Insert user functions */ /*-----------------------*/ void user_initialize(void) { UWORD i ; /* PORT A */ PORTA = 0b11111111 ; /* 11111111 */ DDRA = 0b11111111 ; /* oooooooo */ /* PORT B */ PORTB = 0b00000000 ; /* 00000000 */ DDRB = 0b11111111 ; /* oooooooo */ /* PORT C */ PORTC = 0b00100010 ; /* 00100010 */ DDRC = 0b11111111 ; /* oooooooo */ /* PORT D */ PORTD = 0b00001111 ; /* 00001111 */ DDRD = 0b11110000 ; /* ooooiiii */ /* initialize timer1 */ { /* clear counter */ TCNT1 = 0 ; /* set compare value */ OCR1A = 15999 ; OCR1B = 30000 ; /* prescaler 1/1 => 16MHz */ TCCR1B = (1 << WGM12) | (1 << CS10) ; /* enable compare match */ TIMSK1 = (1 << OCIE1A) ; } /* initialize INT0 */ { /* select falling edge */ EICRA = (1 << ISC01) ; /* enable INT0 */ EIMSK = (1 << INT0); } /* initialize registers */ eflag = OFF ; timcnt = 0 ; mode = 0 ; /* clear */ for ( i = 0 ; i < GMAX ; i++ ) { *(lgdat+i) = 0 ; *(rgdat+i) = 0 ; *(lgdatx+i) = 0 ; *(rgdatx+i) = 0 ; } } void update_led(UBYTE x) { volatile UBYTE bport ; /* generate code */ bport = (1 << x); /* inverse */ bport ^= 0xff; /* impress */ PORTB = bport ; } void send_data(UBYTE which,UBYTE x) { UBYTE loop ; UBYTE tmp ; /* get data */ tmp = x ; /* Write mode */ PORTC &= ~(1 << LCD_RW); /* data transfer to 74HC164 */ for ( loop = 0 ; loop < 8 ; loop++ ) { /* set bit datum */ PORTC &= ~(1 << LCD_DAT) ; if ( tmp & MASK80 ) { PORTC |= (1 << LCD_DAT) ; } /* CLOCK : H */ PORTC |= (1 << LCD_CLK) ; /* shift */ tmp <<= 1 ; /* CLOCK : L */ PORTC &= ~(1 << LCD_CLK) ; } /* confirm RS */ PORTC &= ~(1 << LCD_RS) ; if ( which ) { PORTC |= (1 << LCD_RS) ; } /* latch */ PORTC |= (1 << LCD_E) ; PORTC &= ~(1 << LCD_DAT) ; /* dummy */ PORTC &= ~(1 << LCD_E) ; /* read mode */ PORTC |= (1 << LCD_RW); } void select_plane(UBYTE x) { /* CS1 = 0 , CS2 = 0 */ PORTC &= ~(1 << LCD_CS1); PORTC &= ~(1 << LCD_CS2); /* */ if ( x == SEL_LEFT ) { PORTC |= (1 << LCD_CS1); } if ( x == SEL_RIGHT ) { PORTC |= (1 << LCD_CS2); } } void display(UBYTE x) { send_data(LCD_RS_L,0x3E | x); } void set_address(UBYTE x) { /* check */ if ( x >= XMAX ) return ; /* send address */ send_data(LCD_RS_L,0x40 | x); } void set_page(UBYTE x) { /* check */ if ( x >= YMAX ) return ; /* send address */ send_data(LCD_RS_L,0xb8 | x); } void set_start_line(UBYTE x) { /* check */ if ( x >= XMAX ) return ; /* send address */ send_data(LCD_RS_L,0xC0 | x); } void set_display_data(UBYTE x) { send_data(LCD_RS_H,x); } void display_lcd(UBYTE which,UBYTE *x) { UBYTE xx ; UBYTE yy ; UBYTE tmp ; /* select plane */ select_plane(which); /* show */ display(OFF); /* transfer data */ set_start_line(0) ; for ( yy = 0 ; yy < YMAX ; yy++ ) { set_page(yy) ; set_address(0) ; for ( xx = 0 ; xx < XMAX ; xx++ ) { tmp = *x ; set_display_data( tmp ) ; x++ ; } } /* show */ display(ON); /* disable all plane */ select_plane(SEL_NONE); } void init_lcd(void) { UBYTE i ; /* send reset signal */ { PORTC &= ~(1 << LCD_RST) ; for ( i = 0 ; i < 32 ; i++ ) ; /* delay dummy */ PORTC |= (1 << LCD_RST) ; } /* delay 30 ms */ delay_ms( 30 ) ; /* select first line */ send_data(OFF,0xC0); /* display on */ send_data(OFF,0x3f); } void display_bw(UBYTE x) { UBYTE xx ; UBYTE yy ; UBYTE k ; for ( k = 0 ; k < 2 ; k++ ) { /* select plane */ select_plane(SEL_LEFT); if ( k ) { select_plane(SEL_RIGHT); } /* show */ display(OFF); /* transfer data */ set_start_line(0) ; for ( yy = 0 ; yy < YMAX ; yy++ ) { set_page(yy) ; set_address(0) ; for ( xx = 0 ; xx < XMAX ; xx++ ) { set_display_data( x ^ MASKFF ) ; if ( k ) { set_display_data( x ) ; } } } /* show */ display(ON); /* disable all plane */ select_plane(SEL_NONE); } } void display_black(void) { display_bw( 0 ); } void display_white(void) { display_bw( MASKFF ); } void rotate(UBYTE *x,UBYTE *y) { UBYTE adat[8] ; UBYTE mask ; UBYTE i ; UBYTE j ; UBYTE shf ; UBYTE result ; /* get */ for ( i = 0 ; i < 8 ; i++ ) { *(adat+i) = *(x+i) ; } /* rotate */ for ( i = 0 ; i < 8 ; i++ ) { /* shift counter */ shf = 7 - i ; /* 80 40 20 10 08 04 02 01 */ mask = (1 << shf) ; /* result */ result = 0 ; /* bit operation */ for ( j = 7 ; j > 0 ; j-- ) { result |= (((*(adat+j) & mask) >> shf) & 1) ; result <<= 1 ; } result |= (((*(adat+0) & mask) >> shf) & 1) ; /* put */ *(y+i) = result ; } } void rotate_gdat(UBYTE *s,UBYTE *d) { UBYTE adat[8] ; UBYTE bdat[8] ; UBYTE i ; UBYTE j ; UBYTE k ; UWORD ptr ; /* destination pointer */ ptr = 0 ; /* block handling */ for ( i = 0 ; i < 8 ; i++ ) { for ( j = 0 ; j < 8 ; j++ ) { /* get */ for ( k = 0 ; k < 8 ; k++ ) { *(adat+k) = *(s+64*i+j+k*8); } /* rotate */ rotate(adat,bdat) ; /* put */ for ( k = 0 ; k < 8 ; k++ ) { *(d+ptr+k) = *(bdat+k); ptr++ ; } } } } /* INT0 interrupt */ ISR(INT0_vect) { eflag = ON ; } void delay_ms(UBYTE x) { ULONG last ; last = timcnt + x ; while ( timcnt < last ) ; } /* TIMER1 interrupt (1msec) */ ISR(TIMER1_COMPA_vect) { timcnt++ ; }  仕様は単純で、次のようにしました。  セレクタスイッチで動作指定後、トリガーを  与えると、左あるいは右の領域に白を表示。  セレクタスイッチとして、次の基板を使いました。  すべてプッシュスイッチとしたので、動作を与える  には、次の仕様にします。  左領域のみ白表示。  右領域のみ白表示。  初期化リセット。  画像を表示する場合、フレームバッファを持っていた方が  よいので、FPGAを使うなら、内部SRAMをフレームバッファ  とします。  利用している液晶は、画面を次のように使っているので  回転処理を実行する回路が必要になります。  ラスター(横)方向にデータを並べるのではなく、縦に  1バイトのデータを与えると、意図した画像になります。  単純な並べ変えなので、VHDLコードにするのは簡単でした。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity rotxtst is port ( -- system nRESET : in std_logic ; CLOCK : in std_logic ; -- trigger TRG : in std_logic ; -- select SELIN : in std_logic_vector(2 downto 0) ; SELOUT : in std_logic_vector(2 downto 0) ; -- input Din : in std_logic_vector(7 downto 0); -- output Dout : out std_logic_vector(7 downto 0)--; ); end rotxtst; architecture Behavioral of rotxtst is -- trigger signal iTRG_SFT : std_logic_vector(2 downto 0); signal iTRG : std_logic ; -- data input signal iDin0 : std_logic_vector(7 downto 0); signal iDin1 : std_logic_vector(7 downto 0); signal iDin2 : std_logic_vector(7 downto 0); signal iDin3 : std_logic_vector(7 downto 0); signal iDin4 : std_logic_vector(7 downto 0); signal iDin5 : std_logic_vector(7 downto 0); signal iDin6 : std_logic_vector(7 downto 0); signal iDin7 : std_logic_vector(7 downto 0); -- data output signal iDout0 : std_logic_vector(7 downto 0); signal iDout1 : std_logic_vector(7 downto 0); signal iDout2 : std_logic_vector(7 downto 0); signal iDout3 : std_logic_vector(7 downto 0); signal iDout4 : std_logic_vector(7 downto 0); signal iDout5 : std_logic_vector(7 downto 0); signal iDout6 : std_logic_vector(7 downto 0); signal iDout7 : std_logic_vector(7 downto 0); begin -- trigger process(nRESET,CLOCK) begin if ( nRESET = '0' ) then iTRG_SFT <= "000" ; elsif rising_edge(CLOCK) then iTRG_SFT <= iTRG_SFT(1 downto 0) & TRG ; end if; end process; iTRG <= '1' when( iTRG_SFT = "011" or iTRG_SFT = "001" ) else '0' ; -- get data process(nRESET,CLOCK) begin if ( nRESET = '0' ) then iDin0 <= (others => '0') ; iDin1 <= (others => '0') ; iDin2 <= (others => '0') ; iDin3 <= (others => '0') ; iDin4 <= (others => '0') ; iDin5 <= (others => '0') ; iDin6 <= (others => '0') ; iDin7 <= (others => '0') ; elsif rising_edge(CLOCK) then if ( iTRG = '1' ) then if ( conv_integer(SELIN) = 0 ) then iDin0 <= Din ; end if ; if ( conv_integer(SELIN) = 1 ) then iDin1 <= Din ; end if ; if ( conv_integer(SELIN) = 2 ) then iDin2 <= Din ; end if ; if ( conv_integer(SELIN) = 3 ) then iDin3 <= Din ; end if ; if ( conv_integer(SELIN) = 4 ) then iDin4 <= Din ; end if ; if ( conv_integer(SELIN) = 5 ) then iDin5 <= Din ; end if ; if ( conv_integer(SELIN) = 6 ) then iDin6 <= Din ; end if ; if ( conv_integer(SELIN) = 7 ) then iDin7 <= Din ; end if ; end if ; end if; end process; -- output Dout <= iDout1 when ( SELOUT = "001" ) else iDout2 when ( SELOUT = "010" ) else iDout3 when ( SELOUT = "011" ) else iDout4 when ( SELOUT = "100" ) else iDout5 when ( SELOUT = "101" ) else iDout6 when ( SELOUT = "110" ) else iDout7 when ( SELOUT = "111" ) else iDout0 ; -- rotate iDout0 <= iDin7(7) & iDin6(7) &iDin5(7) & iDin4(7) &iDin3(7) & iDin2(7) &iDin1(7) & iDin0(7); iDout1 <= iDin7(6) & iDin6(6) &iDin5(6) & iDin4(6) &iDin3(6) & iDin2(6) &iDin1(6) & iDin0(6); iDout2 <= iDin7(5) & iDin6(5) &iDin5(5) & iDin4(5) &iDin3(5) & iDin2(5) &iDin1(5) & iDin0(5); iDout3 <= iDin7(4) & iDin6(4) &iDin5(4) & iDin4(4) &iDin3(4) & iDin2(4) &iDin1(4) & iDin0(4); iDout4 <= iDin7(3) & iDin6(3) &iDin5(3) & iDin4(3) &iDin3(3) & iDin2(3) &iDin1(3) & iDin0(3); iDout5 <= iDin7(2) & iDin6(2) &iDin5(2) & iDin4(2) &iDin3(2) & iDin2(2) &iDin1(2) & iDin0(2); iDout6 <= iDin7(1) & iDin6(1) &iDin5(1) & iDin4(1) &iDin3(1) & iDin2(1) &iDin1(1) & iDin0(1); iDout7 <= iDin7(0) & iDin6(0) &iDin5(0) & iDin4(0) &iDin3(0) & iDin2(0) &iDin1(0) & iDin0(0); end Behavioral;  8バイトのデータを、8回に分けて与えると  内部で切貼りして、8バイトのデータになる  ようにしました。  内部にある8バイトの回転したデータは、8回  に分けて出力できるようになっています。  FPGA内部で入出力ピンが不要な場合は、次のVHDL  コードで回路を入れられます。 library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity rotxtst is port ( -- input Din0 : in std_logic_vector(7 downto 0); Din1 : in std_logic_vector(7 downto 0); Din2 : in std_logic_vector(7 downto 0); Din3 : in std_logic_vector(7 downto 0); Din4 : in std_logic_vector(7 downto 0); Din5 : in std_logic_vector(7 downto 0); Din6 : in std_logic_vector(7 downto 0); Din7 : in std_logic_vector(7 downto 0); -- output Dout0 : out std_logic_vector(7 downto 0); Dout1 : out std_logic_vector(7 downto 0); Dout2 : out std_logic_vector(7 downto 0); Dout3 : out std_logic_vector(7 downto 0); Dout4 : out std_logic_vector(7 downto 0); Dout5 : out std_logic_vector(7 downto 0); Dout6 : out std_logic_vector(7 downto 0); Dout7 : out std_logic_vector(7 downto 0)--; ); end rotxtst; architecture Behavioral of rotxtst is -- data input signal iDin0 : std_logic_vector(7 downto 0); signal iDin1 : std_logic_vector(7 downto 0); signal iDin2 : std_logic_vector(7 downto 0); signal iDin3 : std_logic_vector(7 downto 0); signal iDin4 : std_logic_vector(7 downto 0); signal iDin5 : std_logic_vector(7 downto 0); signal iDin6 : std_logic_vector(7 downto 0); signal iDin7 : std_logic_vector(7 downto 0); -- data output signal iDout0 : std_logic_vector(7 downto 0); signal iDout1 : std_logic_vector(7 downto 0); signal iDout2 : std_logic_vector(7 downto 0); signal iDout3 : std_logic_vector(7 downto 0); signal iDout4 : std_logic_vector(7 downto 0); signal iDout5 : std_logic_vector(7 downto 0); signal iDout6 : std_logic_vector(7 downto 0); signal iDout7 : std_logic_vector(7 downto 0); begin -- input iDin0 <= Din0 ; iDin1 <= Din1 ; iDin2 <= Din2 ; iDin3 <= Din3 ; iDin4 <= Din4 ; iDin5 <= Din5 ; iDin6 <= Din6 ; iDin7 <= Din7 ; -- output Dout1 <= iDout1 ; Dout2 <= iDout2 ; Dout3 <= iDout3 ; Dout4 <= iDout4 ; Dout5 <= iDout5 ; Dout6 <= iDout6 ; Dout7 <= iDout7 ; Dout0 <= iDout0 ; -- rotate iDout0 <= iDin7(7) & iDin6(7) &iDin5(7) & iDin4(7) &iDin3(7) & iDin2(7) &iDin1(7) & iDin0(7); iDout1 <= iDin7(6) & iDin6(6) &iDin5(6) & iDin4(6) &iDin3(6) & iDin2(6) &iDin1(6) & iDin0(6); iDout2 <= iDin7(5) & iDin6(5) &iDin5(5) & iDin4(5) &iDin3(5) & iDin2(5) &iDin1(5) & iDin0(5); iDout3 <= iDin7(4) & iDin6(4) &iDin5(4) & iDin4(4) &iDin3(4) & iDin2(4) &iDin1(4) & iDin0(4); iDout4 <= iDin7(3) & iDin6(3) &iDin5(3) & iDin4(3) &iDin3(3) & iDin2(3) &iDin1(3) & iDin0(3); iDout5 <= iDin7(2) & iDin6(2) &iDin5(2) & iDin4(2) &iDin3(2) & iDin2(2) &iDin1(2) & iDin0(2); iDout6 <= iDin7(1) & iDin6(1) &iDin5(1) & iDin4(1) &iDin3(1) & iDin2(1) &iDin1(1) & iDin0(1); iDout7 <= iDin7(0) & iDin6(0) &iDin5(0) & iDin4(0) &iDin3(0) & iDin2(0) &iDin1(0) & iDin0(0); end Behavioral;  ラスター方向に並んでいる画像データを  手持ちグラフィック液晶で表示するため  上のVHDLコードを参考に、ファームウエア  を修正しました。 #include <avr/io.h> #include <avr/interrupt.h> #include <avr/pgmspace.h> typedef unsigned char UBYTE ; typedef signed char SBYTE ; typedef unsigned short UWORD ; typedef signed short SWORD ; typedef unsigned long ULONG ; typedef signed long SLONG ; #define OFF 0 #define ON 1 #define LCD_DAT 7 #define LCD_CLK 6 #define LCD_RST 5 #define LCD_CS2 4 #define LCD_CS1 3 #define LCD_RS 2 #define LCD_RW 1 #define LCD_E 0 #define LCD_RS_H 1 #define LCD_RS_L 0 #define MASKFF 0xFF #define MASK80 0x80 #define MASK40 0x40 #define MASK20 0x20 #define MASK10 0x10 #define MASK08 0x08 #define MASK04 0x04 #define MASK02 0x02 #define MASK01 0x01 #define MASKF0 0xF0 #define SEL_LEFT 2 #define SEL_RIGHT 1 #define SEL_NONE 0 #define GMAX 512 #define YMAX 8 #define XMAX 64 volatile UBYTE eflag ; volatile UBYTE eflagx ; volatile UBYTE fbuf[GMAX] ; volatile UBYTE lgdat[GMAX] ; volatile UBYTE rgdat[GMAX] ; volatile UBYTE lgdatx[GMAX] ; volatile UBYTE rgdatx[GMAX] ; volatile UBYTE mode ; volatile ULONG timcnt ; /*--------------------------------*/ /* Insert user functions protoype */ /*--------------------------------*/ void user_initialize(void); void send_data(UBYTE which,UBYTE x); void select_plane(UBYTE x); void display(UBYTE x); void set_address(UBYTE x); void set_page(UBYTE x); void set_start_line(UBYTE x); void set_display_data(UBYTE x); void display_lcd(UBYTE which,UBYTE *x); void init_lcd(void); void display_bw(UBYTE x,UBYTE which); void display_black0(void); void display_white0(void); void display_black(void); void display_white(void); void rotate(UBYTE *x,UBYTE *y); void rotate_gdat(UBYTE *s,UBYTE *d); void delay_ms(UBYTE x); void init_gdat(UBYTE *x,UBYTE y); void show_sample(void); /* sample data */ const UBYTE PROGMEM img_dat[]={ 0x00,0x00,0x30,0x30,0x38,0xF8,0xF8,0x18,0x0C,0x08,0xE0,0xE0,0x60,0xFC,0xFC,0xFC, 0x00,0x00,0xF0,0xF0,0xF0,0x00,0x00,0x00,0x00,0xF8,0xF8,0xF8,0x18,0x18,0x18,0x18, 0x18,0x18,0x18,0x18,0x18,0xF8,0xF8,0xF8,0x00,0x00,0x00,0x00,0xC0,0xD8,0x58,0x58, 0x58,0x58,0x58,0x58,0xF8,0xF8,0xF8,0x58,0x58,0x58,0x58,0x58,0xD8,0xC0,0xC0,0x00, 0x00,0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x98,0x98,0x98,0xD8,0xD8,0xF8,0xF8, 0x78,0x38,0x10,0x00,0x00,0x00,0x20,0xF0,0xF0,0xC0,0x80,0x00,0x98,0xB8,0xF8,0xF8, 0xD8,0xD8,0xD8,0xF8,0xF8,0xB8,0xB8,0x98,0x00,0x00,0x00,0x18,0x98,0x98,0x98,0xF8, 0xF8,0xF8,0x98,0x9C,0x9C,0x9C,0x98,0xF8,0xF8,0xF8,0x98,0x98,0x98,0x18,0x00,0x00, 0x00,0x00,0xC3,0xE3,0x7F,0xFF,0xFF,0x3B,0x73,0x2C,0x0F,0x0F,0xC0,0xFF,0xFF,0x7F, 0xF8,0xDE,0x1F,0x0F,0x00,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x63,0x63,0x63,0x63, 0x63,0x63,0x63,0x63,0x63,0xFF,0xFF,0xFF,0x00,0x00,0x00,0x00,0x07,0xF7,0xF0,0xF5, 0x55,0x55,0x55,0x50,0xF7,0xF7,0xF7,0x50,0x55,0x55,0x55,0xF0,0xF7,0xF7,0x07,0x00, 0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0xFF,0xFF,0xFF,0x1B,0x19,0x19,0x18, 0x18,0x18,0x18,0x18,0x00,0x00,0x0C,0x0C,0xFD,0xFD,0x00,0x00,0xFF,0xFF,0x6D,0x6D, 0x6D,0xFF,0xFF,0x6D,0x6D,0x6D,0xFF,0xFF,0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0x31, 0xD9,0xDF,0xCF,0xC7,0xC1,0xCF,0xDF,0xDF,0xD9,0x19,0x19,0xFF,0xFF,0x00,0x00,0x00, 0x00,0x01,0x03,0x01,0x00,0x1F,0x1F,0x00,0x08,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00, 0x01,0x07,0x0F,0x1E,0x0C,0x00,0x08,0x0C,0x1F,0x0F,0x07,0x01,0x00,0x00,0x00,0x00, 0x00,0x00,0x18,0x18,0x18,0x1F,0x1F,0x0F,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x07, 0x02,0x02,0x02,0x02,0x0F,0x1F,0x1F,0x1A,0x1A,0x1A,0x1A,0x1B,0x1B,0x1F,0x1E,0x0E, 0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x1F,0x1F,0x0F,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x08,0x1C,0x0E,0x07,0x03,0x06,0x0C,0x0B,0x1B,0x18,0x18, 0x18,0x1B,0x1B,0x18,0x1B,0x1B,0x1B,0x1B,0x18,0x08,0x00,0x00,0x1F,0x1F,0x1F,0x00, 0x0F,0x0F,0x0F,0x06,0x06,0x06,0x07,0x07,0x1F,0x18,0x18,0x1F,0x1F,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0x30,0xB0,0x38,0xB8,0x7C,0xFC,0x7C,0xFC, 0x7C,0xFC,0xFC,0xF8,0xF8,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x02,0x02,0x02,0x02,0x04,0x04,0x04,0x04,0x04,0x04,0x08, 0x08,0x08,0x08,0x38,0x24,0x24,0x3C,0x24,0x24,0x3C,0x44,0x48,0x78,0x48,0x48,0x78, 0x48,0x50,0x20,0x20,0x20,0x20,0x20,0x20,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0xE0,0x20,0xD0, 0x30,0xD0,0x50,0x50,0x20,0xE0,0x80,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0xAA,0x00,0xAA,0x00,0xAA,0x00,0xAA, 0x00,0xAA,0x00,0xFE,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x0C,0xEC,0xEC,0xEC,0x0C,0x0C,0x0C,0x0C,0x3C,0xFC,0xFC,0x80,0x00, 0x00,0x00,0x00,0x00,0x00,0xD8,0xBC,0x78,0x20,0xD8,0xD8,0xD8,0xFC,0xFC,0xD8,0xD8, 0x18,0xFC,0xFC,0xFC,0xCC,0xFC,0xFC,0xFC,0x00,0x00,0x00,0xF0,0xF0,0xF0,0x30,0x30, 0x30,0x30,0x30,0xFC,0xFC,0xFC,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1F,0xE0,0x01,0x3E, 0xFE,0xC2,0x03,0x02,0x01,0xE0,0x1F,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x04,0xFE,0x04,0x0A,0x08,0x0A,0xF8,0x0A, 0x08,0x1A,0xF0,0x1B,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x80,0xC0,0xF8,0xFF,0x3F,0x07,0x00,0x00,0x00,0x00,0x00,0x07,0x1F,0xFF,0xF8, 0xE0,0x80,0x00,0x00,0x00,0x01,0xF3,0xF3,0x62,0xBF,0xBF,0xBF,0xF2,0xF2,0xBF,0xBF, 0x80,0xFF,0xFF,0x7F,0x18,0xFF,0xFF,0xFF,0x00,0x00,0x80,0xFF,0xFF,0x3F,0xF0,0xF0, 0xF0,0x30,0x30,0x3F,0x3F,0x3F,0x33,0x33,0x33,0xF3,0xF3,0xF3,0x03,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x02,0xFC, 0x07,0x07,0x04,0xFC,0x02,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x7F,0x00,0x00,0x00,0x00,0xFF,0x00, 0x00,0x00,0x07,0xF8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x04, 0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, 0x07,0x0F,0x07,0x00,0x00,0x07,0x0F,0x03,0x00,0x01,0x01,0x01,0x0F,0x0F,0x01,0x01, 0x05,0x0F,0x07,0x0C,0x0C,0x0F,0x0F,0x87,0x80,0x84,0x8F,0x0F,0x03,0x00,0x0F,0x0F, 0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x06,0x0F,0x0F,0x0F,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x07, 0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x00, 0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x14,0x12, 0x1E,0x12,0x12,0x1E,0x12,0x11,0x0F,0x09,0x09,0x0F,0x09,0x09,0x0E,0x02,0x02,0x02, 0x02,0x01,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; /*------*/ /* main */ /*------*/ int main(void) { /* initialize I/O */ user_initialize(); /* enable interrupt */ sei() ; /* initialize LCD */ init_lcd(); /* endless loop */ while ( ON ) { /* get mode */ mode = (PIND & 3) ; /* select mode (orange button) */ if ( eflag ) { /* clear flag */ eflag = OFF ; /* handling */ if ( mode == 1 ) { display_white(); } if ( mode == 2 ) { display_black(); } if ( mode == 3 ) { init_lcd(); } } /* select mode (yellow button) */ if ( eflagx ) { /* clear flag */ eflagx = OFF ; /* handling */ if ( mode == 0 ) { show_sample(); } if ( mode == 1 ) { display_black0(); } if ( mode == 2 ) { display_white0(); } if ( mode == 3 ) { /* initialize cross hatch */ init_gdat((UBYTE *)lgdat,0x00); init_gdat((UBYTE *)rgdat,0xCC); /* rotate */ rotate_gdat((UBYTE *)lgdat,(UBYTE *)lgdatx); rotate_gdat((UBYTE *)rgdat,(UBYTE *)rgdatx); /* show */ display_lcd(SEL_LEFT ,(UBYTE *)lgdatx); display_lcd(SEL_RIGHT,(UBYTE *)rgdatx); } } } /* dummy */ return 0 ; } /*-----------------------*/ /* Insert user functions */ /*-----------------------*/ void user_initialize(void) { UWORD i ; /* PORT A */ PORTA = 0b11111111 ; /* 11111111 */ DDRA = 0b11111111 ; /* oooooooo */ /* PORT B */ PORTB = 0b00000000 ; /* 00000000 */ DDRB = 0b11111111 ; /* oooooooo */ /* PORT C */ PORTC = 0b00100010 ; /* 00100010 */ DDRC = 0b11111111 ; /* oooooooo */ /* PORT D */ PORTD = 0b00001111 ; /* 00001111 */ DDRD = 0b11110000 ; /* ooooiiii */ /* initialize timer1 */ { /* clear counter */ TCNT1 = 0 ; /* set compare value */ OCR1A = 15999 ; OCR1B = 30000 ; /* prescaler 1/1 => 16MHz */ TCCR1B = (1 << WGM12) | (1 << CS10) ; /* enable compare match */ TIMSK1 = (1 << OCIE1A) ; } /* initialize INT0 */ { /* select falling edge */ EICRA = (1 << ISC11) | (1 << ISC01) ; /* enable INT1 and INT0 */ EIMSK = (1 << INT1) | (1 << INT0) ; } /* initialize registers */ eflag = OFF ; eflagx = OFF ; timcnt = 0 ; mode = 0 ; /* clear */ for ( i = 0 ; i < GMAX ; i++ ) { *(lgdat+i) = 0 ; *(rgdat+i) = 0 ; *(lgdatx+i) = 0 ; *(rgdatx+i) = 0 ; } /* transfer */ for ( i = 0 ; i < GMAX ; i++ ) { *(fbuf+i) = pgm_read_byte(&img_dat[i]); } } void send_data(UBYTE which,UBYTE x) { UBYTE loop ; UBYTE tmp ; /* get data */ tmp = x ; /* Write mode */ PORTC &= ~(1 << LCD_RW); /* data transfer to 74HC164 */ for ( loop = 0 ; loop < 8 ; loop++ ) { /* set bit datum */ PORTC &= ~(1 << LCD_DAT) ; if ( tmp & MASK80 ) { PORTC |= (1 << LCD_DAT) ; } /* CLOCK : H */ PORTC |= (1 << LCD_CLK) ; /* shift */ tmp <<= 1 ; /* CLOCK : L */ PORTC &= ~(1 << LCD_CLK) ; } /* confirm RS */ PORTC &= ~(1 << LCD_RS) ; if ( which ) { PORTC |= (1 << LCD_RS) ; } /* latch */ PORTC |= (1 << LCD_E) ; PORTC &= ~(1 << LCD_DAT) ; /* dummy */ PORTC &= ~(1 << LCD_E) ; /* read mode */ PORTC |= (1 << LCD_RW); } void select_plane(UBYTE x) { /* CS1 = 0 , CS2 = 0 */ PORTC &= ~(1 << LCD_CS1); PORTC &= ~(1 << LCD_CS2); /* */ if ( x == SEL_LEFT ) { PORTC |= (1 << LCD_CS1); } if ( x == SEL_RIGHT ) { PORTC |= (1 << LCD_CS2); } } void display(UBYTE x) { send_data(LCD_RS_L,0x3E | x); } void set_address(UBYTE x) { /* check */ if ( x >= XMAX ) return ; /* send address */ send_data(LCD_RS_L,0x40 | x); } void set_page(UBYTE x) { /* check */ if ( x >= YMAX ) return ; /* send address */ send_data(LCD_RS_L,0xb8 | x); } void set_start_line(UBYTE x) { /* check */ if ( x >= XMAX ) return ; /* send address */ send_data(LCD_RS_L,0xC0 | x); } void set_display_data(UBYTE x) { send_data(LCD_RS_H,x); } void display_lcd(UBYTE which,UBYTE *x) { UBYTE xx ; UBYTE yy ; UBYTE tmp ; /* select plane */ select_plane(which); /* show */ display(OFF); /* transfer data */ set_start_line(0) ; for ( yy = 0 ; yy < YMAX ; yy++ ) { set_page(yy) ; set_address(0) ; for ( xx = 0 ; xx < XMAX ; xx++ ) { tmp = *x ; set_display_data( tmp ) ; x++ ; } } /* show */ display(ON); /* disable all plane */ select_plane(SEL_NONE); } void init_lcd(void) { UBYTE i ; /* send reset signal */ { PORTC &= ~(1 << LCD_RST) ; for ( i = 0 ; i < 32 ; i++ ) ; /* delay dummy */ PORTC |= (1 << LCD_RST) ; } /* delay 30 ms */ delay_ms( 30 ) ; /* select first line */ send_data(OFF,0xC0); /* display on */ send_data(OFF,0x3f); } void display_bw(UBYTE x,UBYTE which) { UBYTE xx ; UBYTE yy ; UBYTE k ; /* disable all plane */ select_plane(SEL_NONE); k = 0 ; /* LEFT */ if ( which == SEL_LEFT ) { select_plane(SEL_LEFT); k++ ; } /* RIGHT */ if ( which == SEL_RIGHT ) { select_plane(SEL_RIGHT); k++ ; } /* judge */ if ( k == 0 ) return ; /* show */ display(OFF); /* transfer data */ set_start_line(0) ; for ( yy = 0 ; yy < YMAX ; yy++ ) { set_page(yy) ; set_address(0) ; for ( xx = 0 ; xx < XMAX ; xx++ ) { set_display_data( x ) ; } } /* show */ display(ON); /* disable all plane */ select_plane(SEL_NONE); } void display_black0(void) { display_bw(0x00,SEL_LEFT); display_bw(0x00,SEL_RIGHT); } void display_white0(void) { display_bw(MASKFF,SEL_LEFT); display_bw(MASKFF,SEL_RIGHT); } void display_black(void) { display_bw(MASKFF,SEL_LEFT); display_bw(0x00,SEL_RIGHT); } void display_white(void) { display_bw(0x00,SEL_LEFT); display_bw(MASKFF,SEL_RIGHT); } void rotate(UBYTE *x,UBYTE *y) { UBYTE adat[8] ; UBYTE mask ; UBYTE i ; UBYTE j ; UBYTE shf ; UBYTE result ; /* get */ for ( i = 0 ; i < 8 ; i++ ) { *(adat+i) = *(x+i) ; } /* rotate */ for ( i = 0 ; i < 8 ; i++ ) { /* shift counter */ shf = 7 - i ; /* 80 40 20 10 08 04 02 01 */ mask = (1 << shf) ; /* result */ result = 0 ; /* bit operation */ for ( j = 7 ; j > 0 ; j-- ) { result |= (((*(adat+j) & mask) >> shf) & 1) ; result <<= 1 ; } result |= (((*(adat+0) & mask) >> shf) & 1) ; /* put */ *(y+i) = result ; } } void rotate_gdat(UBYTE *s,UBYTE *d) { UBYTE adat[8] ; UBYTE bdat[8] ; UBYTE i ; UBYTE j ; UBYTE k ; UWORD ptr ; /* destination pointer */ ptr = 0 ; /* block handling */ for ( i = 0 ; i < 8 ; i++ ) { for ( j = 0 ; j< 8 ; j++ ) { /* get */ for ( k = 0 ; k < 8 ; k++ ) { *(adat+k) = *(s+64*i+j+k*8); } /* rotate */ rotate(adat,bdat) ; /* put */ for ( k = 0 ; k < 8 ; k++ ) { *(d+ptr+k) = *(bdat+k); } /* update pointer */ ptr += 8 ; } } } /* INT0 interrupt */ ISR(INT0_vect) { eflag = ON ; } /* INT1 interrupt */ ISR(INT1_vect) { eflagx = ON ; } void delay_ms(UBYTE x) { ULONG last ; last = timcnt + x ; while ( timcnt < last ) ; } void init_gdat(UBYTE *x,UBYTE y) { UBYTE xx ; UBYTE yy ; UWORD ptr ; /* Y direction */ for ( yy = 0 ; yy < XMAX ; yy++ ) { /* X direction */ for ( xx = 0 ; xx < YMAX ; xx++ ) { /* calculate pointer */ ptr = 8 * yy + xx ; /* store */ if ( xx & 1 ) { *(x+ptr) = y ; if ( yy & 4 ) { *(x+ptr) = y ^ MASKFF ; } } else { *(x+ptr) = y ^ MASKFF ; if ( yy & 4 ) { *(x+ptr) = y ; } } } } } void show_sample(void) { UBYTE x; UBYTE y; UBYTE buf ; UWORD ptr ; /* initialize pointer */ ptr = 0 ; /* line handling */ for ( y = 0 ; y < YMAX ; y++ ) { /* select left plane */ select_plane(SEL_LEFT); set_page(y); set_address(0) ; select_plane(SEL_NONE); /* select right plane */ select_plane(SEL_RIGHT); set_page(y); set_address(0) ; select_plane(SEL_NONE); /* raster handling */ for ( x = 0 ; x < 128 ; x++ ) { /* get data from buffer */ buf = *(fbuf+ptr); /* which plane */ if ( x < 64 ) { select_plane(SEL_LEFT); } else { select_plane(SEL_RIGHT); } /* transfer data */ set_display_data(buf) ; /* disable both plane */ select_plane(SEL_NONE); /* update pointer */ ptr++; } } } /* TIMER1 interrupt (1msec) */ ISR(TIMER1_COMPA_vect) { timcnt++ ; }  このファームウエアで液晶に画像を表示すると  以下のようになります。  フレームバッファに、ラスター方向に市松模様を  格納し、液晶の仕様にあわせてから、転送した例  です。  秋月電子のサンプルソースにあった画像データを  転送しました。画像データだけをサンプルソース  から取り出して、表示処理をあわせました。  フレームバッファに画像データを入れずに、片側だけ  白にした場合です。(右だけ白)  左だけ白にした例。
目次

inserted by FC2 system