📄 main.asm
字号:
#include <msp430x16x.h>
#define PLATFORM "SoftBaugh DIr169"
// If you have a Nokia 3310 LCD, you can define this symbol and use the graphics commands
#define GRAPHICS
#define BOOTCODE
// For the TI Nokia 3310 expansion board, the serial channel routed
// to the DB9 connector is also routed to the 3310. So, if we're
// supporting graphics, we need to use JTAG I/O on the primary channel.
#if defined(GRAPHICS) && !defined(BOOTCODE)
#define JTAG_PRIMARY_IO_CHANNEL
#endif
#define MAX_X 48 // X resolution
#define MAX_Y 84 // Y resolution
#ifdef JTAG_PRIMARY_IO_CHANNEL
BRKTEST macro EXITLABEL
jmp EXITLABEL ; ...no, continue execution
endm
#else
BRKTEST macro EXITLABEL
bit.b #URXIFG1, &IFG2 ; is a key ready?
jz EXITLABEL ; ...no, continue execution
cmp.b #0x03, &RXBUF1 ; is the key the break key?
jne EXITLABEL ; ...no, continue execution
endm
#endif
// Include the interpreter core
#include "../interpreter.inc"
// Include the graphics extension if configured
#ifdef GRAPHICS
#include "../graphics.inc"
#endif
; The first address at which a program is stored.
; Make this a flash page boundary.
user_flash_begin equ 0x3000
.code
print_char_table:
dc.w uart_1_print_char
print_at_table:
dc.w uart_1_print_at
#if defined(BOOTCODE)
.bss
boot_input ds.w 1
.code
#endif
; Initialise hardware ready to roll.
hw_init:
#if defined(BOOTCODE)
mov.w #boot_program, boot_input
#elif !defined(JTAG_PRIMARY_IO_CHANNEL)
mov.b #0xC0, &P3SEL; ; P3.6,7 = USART1 TXD/RXD
mov.b #UTXE1 + URXE1, &ME2 ; Enabled USART1 TXD/RXD
bis.b #CHAR, &UCTL1; // 8-bit character, SWRST=1
bis.b #SSEL0, &UTCTL1 // UCLK = ACLK
mov.b #0x03, &UBR01 // 9600 from 1Mhz
mov.b #0x00, &UBR11; //
mov.b #0x4a, &UMCTL1 // Modulation
bic.b #SWRST, &UCTL1 // Initialize USART state machine
mov.b 0xCB, &P1DIR // Init P1.x
mov.b #0x08, &P1OUT //
mov.b #0xFF, &P2DIR // Init P2.x
mov.b #0x00, &P2OUT //
mov.b #0x75, &P3DIR // Init P3.x
mov.b #0x00, &P3OUT //
mov.b #0xFF, &P4DIR // Init P4.x
mov.b #0x00, &P4OUT //
mov.b #0xFF, &P5DIR // Init P5.x
mov.b #0x00, &P5OUT //
mov.b # 0x0, &P6SEL ; // P6.0 = analog input
mov.b #0xFE, &P6DIR // Init P6.x
mov.b #0x00, &P6OUT //
#endif
#ifdef GRAPHICS
call #lcd_init
call #lcd_update
#endif
; Set up flash timing generator
mov.w #0xa54a, &FCTL2 ; FTG source is MCLK/11 FIXME!
ret
uart_1_print_at:
ret
uart_1_print_char:
#if defined(JTAG_PRIMARY_IO_CHANNEL)
push.w r12
push.w r13
push.w r14
push.w r15
call #_debug_putchar
pop.w r15
pop.w r14
pop.w r13
pop.w r12
#elif defined(BOOTCODE)
// Do nothing
#else
print_char_00:
bit.b #UTXIFG1, &IFG2
jz print_char_00
mov.b r15, &TXBUF1
cmp.b #'\n', r15
jnz print_char_return
print_char_10:
bit.b #UTXIFG1, &IFG2
jz print_char_10
mov.b #'\r', &TXBUF1
print_char_return:
#endif
ret
get_char:
#if defined(JTAG_PRIMARY_IO_CHANNEL)
push.w r12
push.w r13
push.w r14
call #_debug_getchar
pop.w r14
pop.w r13
pop.w r12
ret
#elif defined(BOOTCODE)
add.w #1, &boot_input
mov.w &boot_input, r15
mov.b -1(r15), r15
#else
get_char_00:
bit.b #URXIFG1, &IFG2
jz get_char_00
mov.b &RXBUF1, r15
cmp.b #'\r', r15
jnz get_char_return
mov.b #'\n', r15
#endif
get_char_return:
call #print_char
ret
x_led:
call #eval_expr
cmp.w #0, r15
jnz value_error
cmp.w #1, r14
jz x_led_20
cmp.w #2, r14
jnz value_error
call #check_comma
call #eval_expr_on_off
bis.w r14, r15
cmp.w #0, r15
jz x_led_10
bis.b #1, &P1OUT
jmp term
x_led_10:
bic.b #1, &P1OUT
jmp term
x_led_20:
call #check_comma
call #eval_expr_on_off
bis.b r14, r15
cmp.w #0, r15
jz x_led_30
bis.b #2, &P1OUT
jmp term
x_led_30:
bic.b #2, &P1OUT
jmp term
#ifdef GRAPHICS
; Graphics support data
.bss
shadow_ram ds.b MAX_X/8 * MAX_Y
.code
// Connections for the TI Nokia 3310 LCD expansion board
// Pin 1 VDD = P5.5 + 100 nF to GND
// Pin 2 SCK = P5.3
// Pin 3 SDIN = P5.1
// Pin 4 D/C = P5.2
// Pin 5 SCE = P5.0
// Pin 6 GND = GND
// Pin 7 VOUT 100 nF to GND
// Pin 8 RES = P5.4
#define PORTOUT P5OUT
#define PORTDIR P5DIR
#define PORTSEL P5SEL
#define PinVCC 0x10 //P5.4
#define PinDC 0x80 //P5.5
#define PinSCE 0x40 //P5.6
#define PinRES 0x20 //P5.7
// Support Macros
#define LcdPowerOn
#define LcdPowerOff
#define LcdDataMode bis.b #PinDC, &PORTOUT
#define LcdCmdMode bic.b #PinDC, &PORTOUT
#define LcdChipDisable bis.b #PinSCE, &PORTOUT
#define LcdChipEnable bic.b #PinSCE, &PORTOUT
#define RES_HIGH bis.b #PinRES, &PORTOUT
#define RES_LOW bic.b #PinRES, &PORTOUT
#define SPIWaitTxBufferEmpty() while(!(IFG2 & UTXIFG1))
#define SPIWaitRxBufferEmpty() while((IFG2&URXIFG1)==0)
SPIWaitTxBufferEmpty macro
L?1 bit.b #UTXIFG1, &IFG2 ; USART0 TX buffer ready (empty)?
jz L?1 ; ...no, busy wait
endm
SPIWaitRxBufferEmpty macro
L?1 bit.b #URXIFG1, &IFG2 ; USART0 TX buffer ready (empty)?
jz L?1 ; ...no, busy wait
endm
lcd_spi_send_byte:
SPIWaitTxBufferEmpty
mov.b r15, &TXBUF1
ret
// Writes direct commands via SPI to the LCD controller
lcd_send_command:
LcdChipEnable
LcdCmdMode
call #lcd_spi_send_byte
SPIWaitRxBufferEmpty
SPIWaitTxBufferEmpty
LcdChipDisable
ret
// Writes direct data via SPI to the LCD controller
lcd_send_data:
LcdChipEnable
LcdDataMode
call #lcd_spi_send_byte
SPIWaitRxBufferEmpty
SPIWaitTxBufferEmpty
LcdChipDisable
ret
// Hardware reset of the LCD Controller
lcd_reset:
RES_LOW
lcd_reset_10:
mov.w #0, r15
sub.w #1, r15
jnz lcd_reset_10
RES_HIGH
ret
// Transfer shadow RAM content via SPI to LCD memory
lcd_update:
mov.w #0x20, r15 ; Funcset H=0 PD=0 V=0
call #lcd_send_command
mov.w #0x80, r15 ; SetX 0
call #lcd_send_command
mov.w #0x40, r15 ; SetY 0
call #lcd_send_command
mov.w #0x22, r15 ; Funcset H=1 PD=0 V=0
call #lcd_send_command
mov.w #shadow_ram, r14 ; start of shadow ram
mov.w #SIZEOF(shadow_ram), r13 ; number of bytes to transfer
LcdChipEnable
LcdDataMode
lcd_update_10:
mov.b @r14+, r15
call #lcd_spi_send_byte
SPIWaitRxBufferEmpty
sub.w #1, r13 ; finished transfer?
jnz lcd_update_10
ret
SPIWaitTxBufferEmpty
nop
LcdChipDisable
; Init Port, SPI and LCD Controler
lcd_init:
bis.b #USPIE1, &ME2
mov.b #CKPH|SSEL1|SSEL0|STC, &UTCTL1; SMCLK, 3-pin mode, clock idle low, data valid on rising edge, UCLK delayed
mov.b #0x02, &U1BR0 ; UCLK/2
mov.b #0, &U1BR1
mov.b #0, &UMCTL1 ; no modulation
mov.b #CHAR|SYNC|MM, UCTL1 ; 8-bit SPI Master ** SWRST**
SPIWaitTxBufferEmpty
; Init Port
mov.b #0x0a, &PORTSEL ; P3.1-3 SPI option select
mov.b #0xff, &PORTDIR ; P3 is output
mov.b #0xff, &PORTOUT
; LCD Interface init
LcdPowerOff
LcdChipDisable
LcdCmdMode
RES_HIGH
; LCD Display Power up sequence
LcdPowerOn
RES_HIGH
LcdChipDisable
LcdChipEnable
RES_LOW
mov.w #0x1f, r15
lcd_init_10:
sub.w #1, r15
jnz lcd_init_10
RES_HIGH
LcdChipDisable
LcdChipEnable
// Initialise LCD controller
mov.b #0x21, r15 ; Funcset H=1 PD=0 V=0
call #lcd_send_command
mov.b #0xa7, r15 ; Set Vop to 49
call #lcd_send_command
mov.b #0x06, r15 ; Tmpcontrol 2
call #lcd_send_command
mov.b #0x16, r15 ; SetBias 6
call #lcd_send_command
mov.b #0x20, r15 ; Funcset H=0 PD=0 V=0
call #lcd_send_command
mov.b #0x0c, r15 ; Display Control D=1 E=0 normal
call #lcd_send_command
mov.b #0x80, r15 ; SetX 0
call #lcd_send_command
mov.b #0x40, r15 ; SetY 0
call #lcd_send_command
mov.w #0x22, r15 ; Funcset H=1 PD=0 V=0
call #lcd_send_command
ret
; Plot point at X=R15, Y=R14
plot:
cmp.w #MAX_X+1, r15
jc plot_return
cmp.w #MAX_Y+1, r14
jc plot_return
; Index into table = y*6 + x/8
mov.w r14, r13
add.w r14, r14
add.w r13, r14
add.w r14, r14
mov.w r15, r13
rra.w r13
rra.w r13
rra.w r13
add.w r13, r14
and.w #7, r15
add.w r15, r15
bis.b bitpos(r15), shadow_ram(r14)
plot_return:
ret
display_clear:
mov.w #shadow_ram, r14 ; start of shadow ram
mov.w #SIZEOF(shadow_ram), r13 ; number of bytes to transfer
display_clear_10:
mov.b #0, @r14
add.w #1, r14
sub.w #1, r13 ; finished transfer?
jnz display_clear_10
ret
x_display:
cmp.b #T_UPDATE, r4 ; DISPLAY UPDATE command?
jnz x_display_10 ; ...no, can't be anything else, so error
call #lcd_update ; transfer shadow RAM to 3310
mov.b @tp+, r4 ; skip UPDATE
jmp term ; ensure terminated
x_display_10:
cmp.b #T_CLEAR, r4 ; DISPLAY CLEAR command?
jnz syntax_error ; ...no, can't be anything else, so error
call #display_clear
mov.b @tp+, r4 ; skip UPDATE
jmp term ; ensure terminated
#endif
boot_program:
dc.b "10 FOR X = 0 TO 47\n"
dc.b "15 FOR Y = 0 TO 81\n"
dc.b "20 PLOT X, Y\n"
dc.b "30 NEXT\n"
dc.b "40 IF (X AND 7) = 0 DISPLAY UPDATE\n"
dc.b "50 NEXT\n"
dc.b "RUN\n"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -