コントローラの製作
今まではPCに接続してコントロールしていましたが、今度は運転台のようなコントローラを作ります。
【製作中】
メインのマイコンにPIC32MX120F032Bを使用してドライブボードと232Cで通信します。
LDC表示器に秋月のAQM1602Y-RN-GBWを使用します。
スピードメーターには秋月の赤色バーLEDアレイOSX10201-Rを2個使い、20のLEDバーで速度と実際に駆動しているパワーをLEDの点滅で表示します。LEDバーのコントロールにPIC16F1933を使用して、I2CのSlaveモードでPIC32と通信します。
・列車1は運転の記録・再生が出来ます。I2CのEEPROM 24LC64にプログラム運転を記録します。
動画です。
3Dプリンタでフレームを作って仮組
3Dプリンタでパネルを作ったところ
プリント基板で製作中
LEDバー表示用 PIC16F1933のコード
//*********************************************************
//2020_02_11 LED_BAR
//*********************************************************
#include <xc.h>
#define _XTAL_FREQ 4000000
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
//#pragma config DEBUG = OFF
#pragma config FOSC =INTOSC //HS
#pragma config FCMEN = OFF
#pragma config MCLRE = OFF
#pragma config WDTE = OFF //ON
#pragma config CP = OFF
#pragma config LVP = OFF
#pragma config PWRTE = ON
#define RXBUFFER_SIZE 4
#define STATE1 0b00001001 // 0x09 master write last was address
#define STATE2 0b00101001 // 0x29 master write last was data
#define STATE3 0b00001101 // 0x0d master read last was address
#define STATE4 0b00101100 // 0x2c master write last was data
#define STATE5 0b00101000 // 0x28
//PORTアクセス用共用体
union byte_access_long {
long LNG; // Long Access
struct { // byte Access
unsigned char L1;
unsigned char H1;
unsigned char L2;
} BYTE;
struct {
unsigned char PORTB : 8;
unsigned char PORTA : 7;
unsigned char PORTC1 : 3;
unsigned char PORTC2 : 2;
} BIT;
};
volatile unsigned char RXBuffer[RXBUFFER_SIZE];
volatile unsigned char RXBufferIndex = 0;
void setUpI2CSlave(void);
void I2CWrite(unsigned char);
long LED_BAR(unsigned char, unsigned char, char);
//********************************************************
void main(void) {
//最高速32MHz
OSCCONbits.SPLLEN = 1; //×4 PLL
OSCCONbits.IRCF = 14; //8MHz
ANSELA = 0; // アナログ入力 AN8からAN13 を無効
ANSELB = 0; // アナログ入力 AN0からAN7 を無効
PORTA = 0;
PORTB = 0;
TRISA = 0;
TRISB = 0;
TRISC = 0b11000;
OPTION_REG = 0x0f; // WDT,Int Fall, pulup
__delay_ms(10); // 10msec
setUpI2CSlave(); //I2C SlaveMode setting
while (1) {
union byte_access_long speed_led;
speed_led.LNG = LED_BAR(RXBuffer[0], 1, RXBuffer[1]);//i:speed d:明るさ1-10 b:powerの点滅
PORTB = speed_led.BIT.PORTB;
PORTA = speed_led.BIT.PORTA << 1;
PORTC = speed_led.BIT.PORTC1 | (speed_led.BIT.PORTC2 << 5);
//CLRWDT();
__delay_ms(10); // 10msec
}
}
//I2C ADDRESS main用 0x10, sub用 0x12
#define I2C_ADDR 0x10 // I2C 7bit address
void setUpI2CSlave() {
SSPCON2 = 0b00000001; //SEN is set to enable clock stretching
SSPCON3 = 0x00;
SSPADD = I2C_ADDR << 1; //7-bit address is stored in the 7 MSB's of the SSP1ADD register**********
SSPSTAT = 0x00;
SSPCON1 = 0b00110110;
/* Enable interrupts */
SSPIF = 0; //Clear MSSP interrupt flag
SSPIE = 1; //I2C interrupt enable
//end I2C(1) setup----------------------------------------------------------------
// Common Interrupt
PEIE = 1; // Enable Peripheral interrupts
GIE = 1; // Enable global interrupts
}
void checkStatAndMngI2c() {
static char DAStatus = 0;
unsigned char i2cStatus, value;
i2cStatus = SSPSTAT;
i2cStatus = (i2cStatus & 0b00101101); //Mask out unimportant bits
//
switch (i2cStatus) {
case STATE1:
value = SSPBUF; //read buffer, clear BF
RXBufferIndex = 0; //clear index
DAStatus = 1; // next call is address inside memory
if (SSPCON1bits.SSPOV)SSPCON1bits.SSPOV = 0; //clear receive overflow indicator
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
break;
case STATE2:
value = SSPBUF; //read buffer, clear BF
if (DAStatus == 1) {
RXBufferIndex = value;
DAStatus = 2;
} else {
RXBuffer[RXBufferIndex] = value;
RXBufferIndex++; //increment index
if (RXBufferIndex >= RXBUFFER_SIZE)
RXBufferIndex = 0;
}
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
break;
case STATE3:
value = SSPBUF; //dummy read
if (RXBufferIndex >= RXBUFFER_SIZE)
RXBufferIndex = 0;
I2CWrite(RXBuffer[RXBufferIndex]); //write back the index of status requested
RXBufferIndex++;
break;
case STATE4:
if (RXBufferIndex >= RXBUFFER_SIZE)
RXBufferIndex = 0;
I2CWrite(RXBuffer[RXBufferIndex]); //write back the index of status requested
RXBufferIndex++;
break;
case STATE5:
break;
default:
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
break;
}
}
void __interrupt() I2Cinterrupt() {
if (SSPIF) {
SSPIF = 0; // Clear interrupt flag
checkStatAndMngI2c();
}
}
//Byte送信
void I2CWrite(unsigned char data) {
while (SSPSTATbits.BF); //wait while buffer is full
do {
SSPCON1bits.WCOL = 0; //clear write collision flag
SSPBUF = data;
} while (SSPCON1bits.WCOL); //do until write collision flag is clear
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
}
long LED_BAR(unsigned char i, unsigned char d, char b) {
//i:speed d:明るさ1-10 b:powerの点滅
unsigned char s;
long ret = 1;
long b_p = 1;
static unsigned char blink;
unsigned char blink_t = 50;
static unsigned char dimmer;
if (!dimmer--) {
dimmer = 10;
if (!blink--)
blink = blink_t;
}
if (dimmer <= d) {//dimer
s = i;
ret <<= s;
ret--;
} else {
ret = 0;
}
b_p <<= b;
if (blink > (blink_t >> 1)) {
//blink_kn半分の時間点灯
ret |= b_p;
} else {
ret &= ~b_p;
}
return ret;
}
SWLED表示用 PIC16F1827のコード
//*********************************************************
//2020_03_20
//*********************************************************
#include <xc.h>
#define _XTAL_FREQ 4000000
#pragma config CPD = OFF
#pragma config BOREN = OFF
#pragma config IESO = OFF
#pragma config FOSC =INTOSC //HS
#pragma config FCMEN = OFF
#pragma config MCLRE = OFF
#pragma config WDTE = OFF //ON
#pragma config CP = OFF
#pragma config LVP = OFF
#pragma config PWRTE = ON
#define RXBUFFER_SIZE 4
#define STATE1 0b00001001 // 0x09 master write last was address
#define STATE2 0b00101001 // 0x29 master write last was data
#define STATE3 0b00001101 // 0x0d master read last was address
#define STATE4 0b00101100 // 0x2c master write last was data
#define STATE5 0b00101000 // 0x28
volatile unsigned char RXBuffer[RXBUFFER_SIZE];
volatile unsigned char RXBufferIndex = 0;
void setUpI2CSlave(void);
void I2CWrite(unsigned char);
//********************************************************
void main(void) {
//最高速32MHz
OSCCONbits.SPLLEN = 1; //×4 PLL
OSCCONbits.IRCF = 14; //8MHz
ANSELA = 0; // アナログ入力 AN8からAN13 を無効
ANSELB = 0; // アナログ入力 AN0からAN7 を無効
PORTA = 0;
PORTB = 0;
TRISA = 0;
TRISB = 0b10010;
OPTION_REG = 0x0f; // WDT,Int Fall, pulup
__delay_ms(10); // 10msec
setUpI2CSlave(); //I2C SlaveMode setting
while (1) {
//I2Cで受信したデータをポートに出力
PORTB = RXBuffer[1];
PORTA = RXBuffer[0];
__delay_ms(10); // 10msec
}
}
#define I2C_ADDR 0x11 // I2C 7bit address
void setUpI2CSlave() {
SSPCON2 = 0b00000001; //SEN is set to enable clock stretching
SSPCON3 = 0x00;
SSPADD = I2C_ADDR << 1; //7-bit address is stored in the 7 MSB's of the SSP1ADD register**********
SSPSTAT = 0x00;
SSPCON1 = 0b00110110;
/* Enable interrupts */
SSP1IF = 0; //Clear MSSP interrupt flag
SSP1IE = 1; //I2C interrupt enable
//end I2C(1) setup----------------------------------------------------------------
// Common Interrupt
PEIE = 1; // Enable Peripheral interrupts
GIE = 1; // Enable global interrupts
}
void checkStatAndMngI2c() {
static char DAStatus = 0;
unsigned char i2cStatus, value;
i2cStatus = SSPSTAT;
i2cStatus = (i2cStatus & 0b00101101); //Mask out unimportant bits
//
switch (i2cStatus) {
case STATE1:
value = SSPBUF; //read buffer, clear BF
RXBufferIndex = 0; //clear index
DAStatus = 1; // next call is address inside memory
if (SSPCON1bits.SSPOV)SSPCON1bits.SSPOV = 0; //clear receive overflow indicator
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
break;
case STATE2:
value = SSPBUF; //read buffer, clear BF
if (DAStatus == 1) {
RXBufferIndex = value;
DAStatus = 2;
} else {
RXBuffer[RXBufferIndex] = value;
RXBufferIndex++; //increment index
if (RXBufferIndex >= RXBUFFER_SIZE)
RXBufferIndex = 0;
}
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
break;
case STATE3:
value = SSPBUF; //dummy read
if (RXBufferIndex >= RXBUFFER_SIZE)
RXBufferIndex = 0;
I2CWrite(RXBuffer[RXBufferIndex]); //write back the index of status requested
RXBufferIndex++;
break;
case STATE4:
if (RXBufferIndex >= RXBUFFER_SIZE)
RXBufferIndex = 0;
I2CWrite(RXBuffer[RXBufferIndex]); //write back the index of status requested
RXBufferIndex++;
break;
case STATE5:
break;
default:
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
break;
}
}
void __interrupt() I2Cinterrupt() {
if (SSP1IF) {
SSP1IF = 0; // Clear interrupt flag
checkStatAndMngI2c();
}
}
//Byte送信
void I2CWrite(unsigned char data) {
while (SSPSTATbits.BF); //wait while buffer is full
do {
SSPCON1bits.WCOL = 0; //clear write collision flag
SSPBUF = data;
} while (SSPCON1bits.WCOL); //do until write collision flag is clear
if (SSPCON2bits.SEN) SSPCON1bits.CKP = 1; //release the SCL line
}
PIC32のコード
Harmonyの設定
Timerを2つ使います。
Debug中ですが
app.hに一行追加
// ***************************************************************************** // ***************************************************************************** // Section: Included Files // ***************************************************************************** // ***************************************************************************** #include <stdint.h> #include <stdbool.h> #include <stddef.h> #include <stdlib.h> #include "system_config.h" #include "system_definitions.h" #include "atc.h" //追加
atc.h ( ヘッダーファイルに追加)
//
//2021_0821
#define TR_COUNT 3 //列車数
#define ROSEN_NUM 0 //路線(ボード)番号
#define BOARD_COUNT 3 //ボード数
#define RX_BYTE 230 //128//RS232C受信バイト数
#define TX_BYTE 128 //230 //RS232C送信バイト数
#define RX_DATA_BYTE 12 //1列車当たりの受信バイト数
#define TX_DATA_BYTE 12 //1列車当たりの送信バイト数
#define POINT_COUNT 4 //ポイント数
#define YARD_COUNT 2 //YARD数
#define STOP_POS_COUNT 2 //停止位置数
//I2C用変数
DRV_HANDLE hi2c;
DRV_I2C_BUFFER_HANDLE bhi2c;
//USART用変数
DRV_HANDLE handleUSART0;
bool ext_int_enable;
//16bitのINT型の上位H byte、下位L byte読み込み用共用体
union byte_access {
int INT; // Int Access
struct { // byte Access
unsigned char L;
unsigned char H;
} BYTE;
};
//位置情報の構造体
union POSITION { //位置情報
unsigned char BYTE; /* Byte Access */
//struct PSI_BIT BIT; /* Bit Access */
struct {
unsigned char KUKAN : 3; /* 区間 Bit 0-2 */
unsigned char ROSEN : 3; /* 路線 Bit 3-5 */
unsigned char SOU : 1; /* 相 Bit 6 */
unsigned char DIR : 1; /* 方向 Bit 7 */
} BIT;
};
struct STATUS_BIT {
unsigned char CHG : 1; //区間変化
unsigned char SP_MANU : 1; //speed manual
unsigned char REV : 1; //逆転
unsigned char CHG_RCV : 1; //chg flg
unsigned char DUMY : 2; //DUMY
unsigned char SLOW : 1; //減速
unsigned char SAFE : 1; //安全
};
typedef enum {
NONE = 0,
P_SW_ON,
SWITCH_REQ,
SWITCHING,
WAITING,
} POINT_STATE;
typedef enum {
SAFE = 0,
WAIT_PASS,
IMPOSSIBLE,
} POINT_SAFE;
typedef enum {
YARD_NONE = 0,
Y_SW_ON,
YARD_REQ,
YARD_COMP,
POINT_COMP,
YARD_STOP,
YARD_STOP_COMP,
POINT_RET,
POINT_RET_COMP,
YARD_END,
START_REQ,
START_REQ_ACK,
READY_START,
EXIT_POS,
} YARD_STATE;
typedef enum {
GO = 0,
STOP,
SLOW,
STOP_REV,
SLOW_POINT,
SLOW_YARD,
} SAFE_FLAG;
//列車の位置情報の構造体
struct st_position {
//現在位置
union POSITION NOW;
//前の位置
union POSITION BEFORE;
//次の位置
union POSITION NEXT;
//次々の位置
union POSITION ANEXT;
union {
unsigned char BYTE; /* Byte Access */
struct STATUS_BIT BIT; /* Bit Access */
} STATUS;
int speed;
union byte_access speed_cont;
int speed_err;
int speed_peak;
int mascon;
unsigned char henka;
//unsigned char safe;
union byte_access speed_ret; //読み取りスピード
union byte_access speed_ret_rx; //読み取りスピード
union byte_access speed_ret_tx; //読み取りスピード
union byte_access power;
unsigned char point;
unsigned char point_num;
unsigned char yard;
unsigned char yard_num;
unsigned char revers_req;
union byte_access speed_rx;
unsigned char REC_NOW;
unsigned char REC_NEXT;
unsigned char REC_BEFORE;
POINT_STATE point_state;
YARD_STATE yard_state;
};
//監視区間設定用の共用体
union scan_port {
unsigned char BYTE; /* Byte Access */
struct {
unsigned char DUMMY : 2; /* Bit 0-1 */
unsigned char KUKAN : 3; /* Bit 2-4 監視区間*/
unsigned char DISABLE : 1; /* Bit 5 */
unsigned char B6 : 1; /* Bit 6 */
} BIT;
};
//ポイント用共用体
struct point {
union POSITION approach;
union POSITION exit;
unsigned char num;
};
struct yard {
union POSITION approach;
union POSITION start;
union POSITION exit;
union POSITION approach_b;
union POSITION start_b;
union POSITION exit_b;
unsigned char point_num;
unsigned char line;
unsigned char exist;
unsigned char type;
unsigned char y_cont;
unsigned char p_cont;
};
//停止位置
struct stop_position {
union POSITION pos;
char point_num;
};
//操作盤用
struct ContPanel {
struct {
unsigned char POINT : 1;
unsigned char REVERS : 1;
unsigned char YARD : 1;
} SW;
struct {
unsigned char POINT : 1;
unsigned char REVERS : 1;
unsigned char YARD : 1;
} LED;
char point_num;
char yard;
char line;
};
struct RecList {
union POSITION pos;
unsigned char speed;
union {
unsigned char BYTE; /* Byte Access */
struct {
unsigned char YARD : 3;
unsigned char LINE : 3;
unsigned char ENABLE : 1;
} BIT;
} yard;
union {
unsigned char BYTE; /* Byte Access */
struct {
unsigned char POINT_NUM : 3;
unsigned char ENABLE : 1;
unsigned char REVERS : 1;
} BIT;
} point;
//unsigned char point;
};
struct RecList rec_list[128];
unsigned char step;
unsigned char step_stop;
unsigned char rec_status;
unsigned char EnableBit[] = {1, 2, 4, 8, 16, 32, 64, 128};
unsigned int int_counter; //インタラプトカウンタ
unsigned int speed_pw[2]; //スピードパルス幅
struct st_position train[TR_COUNT]; //列車位置情報
struct st_position* train_sou[2];
unsigned char cont_train[2]; //制御する列車番号
unsigned char kukan[2]; //区間
unsigned char kanshi_now[2]; //スピード読み込み用
unsigned char kanshi_before[2]; //スピード読み込み用
union scan_port kanshi; //区間監視用
union byte_access adc_ret; //ADC値
union byte_access adc_brk_ret; //ブレーキのADC値
union byte_access debug1; //ADC値
int gnd_adc;
union byte_access gnd_level;
unsigned char rx_data[RX_BYTE];
unsigned char tx_data[TX_BYTE];
unsigned char receive_data; //通信用受信データ
unsigned char send_data; //通信用送信データ
unsigned char comm_data[128]; //通信用メモリ
unsigned int comm_counter; //通信用インタラプトカウンタ
unsigned char board_num; //ボード番号
unsigned char point_req; //ポイントリクエスト
unsigned char yard_req; //ポイントリクエスト
unsigned char int_count; //interrupt count
unsigned char sw_input[4]; //sw
char key_on[20];
char key_count[20];
char key_down[20];
unsigned char r_enc;
struct point point[POINT_COUNT];
struct yard yard[YARD_COUNT];
struct stop_position stop_pos[STOP_POS_COUNT];
struct ContPanel cont_panel[TR_COUNT];
//Curser用
#define CUR_MAX 6
char curser_pos;
char SetPos_y[] = {0, 1, 1, 0, 1, 1};
char SetPos_x[] = {2, 2, 4, 9, 9, 11};
char cont_sel;
char disp_mode;
char disp_page;
#define PAGE_MAX 3
int Brake;
char speed_mode;
char test1;
char test2;
#define EEP_PAGE 32
unsigned char eep_data[256];
unsigned char eep_page_data[34]; //(2+32)
unsigned char prg_num;
unsigned char repeat;
unsigned char count_dwn;
unsigned char disp_pos; //debug monitor
unsigned char point_test;
lcd.c (SourceFiles appに追加)
//
//2021_0418
//
#include "system/common/sys_common.h"
#include "app.h"
#include "system_definitions.h"
#define ADR 0x7C
#define PIC_ADR 0x20 //PIC16F1827 slave
void LCD_cmd(char);
void LCD_int(void);
void LCD_str(char *);
void LCD_dat(char);
void LCD_hex(char);
void LCD_posyx(char, char);
void LCD_dec(int, char);
void PIC_dat(char, unsigned char, unsigned char, unsigned char);
unsigned char EEP_Read(int, unsigned char, unsigned char);
void EEP_Write(int, char, unsigned char);
void BSP_DelayMs(unsigned short);
void BSP_DelayUs(unsigned short);
uint8_t data[5];
uint8_t r_data[256];
//遅延調整用関数(ms)
void BSP_DelayMs(unsigned short milliseconds) {
unsigned long time;
time = _CP0_GET_COUNT(); //Read Core Timer
time += (SYS_CLK_FREQ / 2 / 1000) * milliseconds; //calc the Stop Time
while ((long) (time - _CP0_GET_COUNT()) > 0) {
};
}
//遅延調整用関数(μs)
void BSP_DelayUs(unsigned short microseconds) {
unsigned long time;
time = _CP0_GET_COUNT(); //Read Core Timer
time += (SYS_CLK_FREQ / 2 / 1000000) * microseconds; //calc the Stop Time
while ((long) (time - _CP0_GET_COUNT()) > 0) {
};
}
void LCD_cmd(char cmd) {
data[0] = 0x80;
data[1] = cmd;
bhi2c = DRV_I2C_Transmit(hi2c, ADR, data, 2, NULL); //I2C送信
while (DRV_I2C_TransferStatusGet(hi2c, bhi2c) != DRV_I2C_BUFFER_EVENT_COMPLETE); /*I2C完了待ち*/
if (cmd & 0xFC) // LCDのコマンドにより待ち時間が違う
BSP_DelayUs(60); // 60usec
else
BSP_DelayMs(3); // 3msec
}
void LCD_int(void) {
BSP_DelayMs(100);
LCD_cmd(0x38);
LCD_cmd(0x39);
LCD_cmd(0x14);
LCD_cmd(0x73); //7A(forAQM1602)
LCD_cmd(0x56); //54(forAQM1602)
LCD_cmd(0x6C);
BSP_DelayMs(200);
LCD_cmd(0x0C); //Disp ON/OFF
LCD_cmd(0x01); // Clear Display
BSP_DelayUs(1100);
}
//文字列表示
void LCD_str(char *str) {
while (*str) //0x00まで繰り返し
LCD_dat(*str++); //1文字表示
}
//1文字表示
void LCD_dat(char chr) {
data[0] = 0x40;
data[1] = chr;
//I2C送信
bhi2c = DRV_I2C_Transmit(hi2c, ADR, data, 2, NULL);
while (DRV_I2C_TransferStatusGet(hi2c, bhi2c) != DRV_I2C_BUFFER_EVENT_COMPLETE);
BSP_DelayUs(60); // 60usec
}
//-------- 16進文字変換表示 ----------------
void LCD_hex(char c) {
const char hexch[] = "0123456789ABCDEF";
LCD_dat(hexch[c >> 4]); //上位4bit表示
LCD_dat(hexch[c & 0xF]); //下位4bit表示
}
//--------3桁 10進文字表示 ----------------
void LCD_dec(int i, char c) {
const char decch[] = "0123456789 ";
char n[3];
n[2] = i / 100;
n[1] = (i % 100) / 10;
n[0] = i % 10;
if (n[2] == 0) {
n[2] = 10; //100の桁は0ならスペース
if (n[1] == 0) {
n[1] = 10; //100の桁0で10の桁0ならスペース
}
}
if (c > 2) LCD_dat(decch[n[2]]);
if (c > 1) LCD_dat(decch[n[1]]);
LCD_dat(decch[n[0]]);
}
//-------- カーソル位置指定 --------------------------------------
void LCD_posyx(char ypos, char xpos) {
unsigned char pcode;
switch (ypos & 0x03) { // 縦位置を取得
case 0: pcode = 0x80;
break; // 1行目
case 1: pcode = 0xC0;
break; // 2行目
case 2: pcode = 0x94;
break; // 3行目
case 3: pcode = 0xD4;
break; // 4行目
}
LCD_cmd(pcode += xpos); // 横位置を加える
}
void PIC_dat(char start, unsigned char d1, unsigned char d2, unsigned char adr) {
data[0] = start;
data[1] = d1;
data[2] = d2;
//I2C送信
bhi2c = DRV_I2C_Transmit(hi2c, adr, data, 3, NULL);
while (DRV_I2C_TransferStatusGet(hi2c, bhi2c) != DRV_I2C_BUFFER_EVENT_COMPLETE);
BSP_DelayUs(60); // 60usec
}
void EEP_Write(int adr, char page, unsigned char i2c_adr) {
char count = 3; //1byte write(2+1)
if (page) count = 34; //page write(2+32) 24LC64は1page32byte
eep_page_data[0] = adr >> 8;
eep_page_data[1] = adr & 0xFF;
//I2C送信
bhi2c = DRV_I2C_Transmit(hi2c, i2c_adr, eep_page_data, count, NULL);
while (DRV_I2C_TransferStatusGet(hi2c, bhi2c) != DRV_I2C_BUFFER_EVENT_COMPLETE);
BSP_DelayMs(10); // 10msec
}
unsigned char EEP_Read(int adr, unsigned char count, unsigned char i2c_adr) {
data[0] = adr >> 8;
data[1] = adr & 0xFF;
//I2C送信
bhi2c = DRV_I2C_Transmit(hi2c, i2c_adr, data, 2, NULL);
while (DRV_I2C_TransferStatusGet(hi2c, bhi2c) != DRV_I2C_BUFFER_EVENT_COMPLETE);
BSP_DelayUs(60); // 60usec
//DRV_I2C_BUFFER_HANDLE DRV_I2C_Receive ( DRV_HANDLE drvhandle, uint16_t deviceaddress,
// void *rxBuffer, size_t size, void * context)
bhi2c = DRV_I2C_Receive(hi2c, i2c_adr, eep_data, count, NULL);
//DRV_I2C_TransmitThenReceive ( DRV_HANDLE drvhandle, uint16_t deviceaddress,
// void *txBuffer, size_t wsize,
// void *rxBuffer, size_t rsize, void * context);
//bhi2c = DRV_I2C_TransmitThenReceive(hi2c, adr + 1, data, 0, r_data, 1, NULL);
while (DRV_I2C_TransferStatusGet(hi2c, bhi2c) != DRV_I2C_BUFFER_EVENT_COMPLETE);
BSP_DelayUs(60); // 60usec
return eep_data[0];
}
/*******************************************************************************
End of File
*/
timer_int.c (SourceFiles appに追加)
//
//
//2020_0829
//
#include "system/common/sys_common.h"
#include "app.h"
#include "system_definitions.h"
void KeyIn(char);
void timer_int_func() {
unsigned char n, p;
static char enc_c[2];
static char enc_on[2];
unsigned char sw_pos = int_count++ >> 2 & 0b11;
_RB2 = 0;
_RA2 = 0;
_RB3 = 0;
_RA3 = 0;
// PORTB &= 0b11; //RB2,3=0
// PORTA &= 0b11; //RA2,3=0
switch (sw_pos) {
case 0:
_RB2 = 1;
break;
case 1:
_RB3 = 1;
break;
case 2:
_RA2 = 1;
break;
case 3:
_RA3 = 1;
break;
}
KeyIn(sw_pos); //KeyInput
//ロータリーエンコーダ入力
if (_RB11 == 0) {
if (enc_c[0]++ > 1) {
enc_c[0] = 1;
if (enc_on[0] == 0) {
enc_on[0] = 1;
if (_RB10 == 1) {
r_enc--;
if (train[cont_sel].mascon > 0)
train[cont_sel].mascon--;
}
}
}
} else if (--enc_c[0] < 0) {
enc_c[0] = 0;
enc_on[0] = 0;
}
if (_RB10 == 0) {
if (enc_c[1]++ > 1) {
enc_c[1] = 1;
if (enc_on[1] == 0) {
enc_on[1] = 1;
if (_RB11 == 1) {
r_enc++;
if (train[cont_sel].mascon < 100)
train[cont_sel].mascon++;
}
}
}
} else if (--enc_c[1] < 0) {
enc_c[1] = 0;
enc_on[1] = 0;
}
// if (enc_rise[0] == 1) {
// enc_rise[0] = 0;
// r_enc++;
// }
//if (int_count++ & 0x3F)return;
//以下64回に1回実行
}
void timer_int_func_rs() {
unsigned char n, p;
//ヘッダーとして&H55,&HAAを送る
tx_data[0] = 0x55;
tx_data[1] = 0xAA;
for (n = 0; n < TR_COUNT; n++) {
p = n * TX_DATA_BYTE + 2;
union byte_access send_speed;
send_speed.INT = train[n].speed;
tx_data[p] = send_speed.BYTE.L;
tx_data[p + 1] = train[n].NOW.BYTE;
tx_data[p + 2] = train[n].BEFORE.BYTE;
tx_data[p + 3] = train[n].NEXT.BYTE;
tx_data[p + 4] = train[n].STATUS.BYTE;
tx_data[p + 5] = train[n].point;
tx_data[p + 6] = train[n].yard;
}
// 送信用メモリデータをPCに転送します
for (n = 0; n < TX_BYTE; n++) {
DRV_USART_WriteByte(DRV_USART_INDEX_0, tx_data[n]);
}
//ADC読み込み
PLIB_ADC_MuxChannel0InputPositiveSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_POSITIVE_AN0); //AN0:mainマスコンVR
PLIB_ADC_SamplingStart(ADC_ID_1);
while (!PLIB_ADC_ConversionHasCompleted(ADC_ID_1));
adc_ret.INT = PLIB_ADC_ResultGetByIndex(ADC_ID_1, 0);
//ブレーキVR読み込み
PLIB_ADC_MuxChannel0InputPositiveSelect(DRV_ADC_ID_1, ADC_MUX_A, ADC_INPUT_POSITIVE_AN1); //AN1:ブレーキVR
PLIB_ADC_SamplingStart(ADC_ID_1);
while (!PLIB_ADC_ConversionHasCompleted(ADC_ID_1));
adc_brk_ret.INT = PLIB_ADC_ResultGetByIndex(ADC_ID_1, 0);
}
void KeyIn(char row) {
char p, n, key;
for (p = 0; p < 5; p++) {
n = row * 5 + p;
if (p < 4) {
key = PORTB & EnableBit[p + 4];
} else {
key = _RA4;
}
if (key) {//RB4-
if (key_count[n]++ > 3) {
key_count[n] = 3;
if (!key_on[n]) {
key_on[n] = 1;
key_down[n] = 1;
}
}
} else if (--key_count[n] < 0) {
key_count[n] = 0;
key_on[n] = 0;
}
}
}
/* *****************************************************************************
End of File
*/
app.cの APP_Tasks 以下を挿げ替えます。
//
//2021_0829
/******************************************************************************
Function:
void APP_Tasks ( void )
Remarks:
See prototype in app.h.
*/
void ini_train(char);
void train_set(unsigned char, union POSITION p1);
void section_chg(unsigned char);
void reverse(unsigned char);
int speed_up_down(char, int, char);
int stoppage_time(char, int);
unsigned char safe_check(unsigned char);
void point_set(unsigned char, unsigned char, union POSITION, union POSITION);
union POSITION point_pos(unsigned char, union POSITION);
POINT_SAFE point_safe_check(unsigned char, union POSITION);
union POSITION position_set(unsigned char, unsigned char, unsigned char, unsigned char);
void point_process(void);
bool point_exit_position(unsigned char, union POSITION);
void yard_process(void);
void yard_set(unsigned char, union POSITION, unsigned char, unsigned char, unsigned char, unsigned char);
union POSITION next_position(union POSITION);
void LcdDisp(void);
void KeyCont(void);
char SelLED(char);
char yard_line_num(char, char, char, char);
void yard_set_line(char, char, char);
bool yard_exit_pos(unsigned char, union POSITION);
void stop_pos_set(char, union POSITION, char);
void stop_pos_process(void);
void rec_play(void);
void SavePlayList(unsigned char);
void LoadPlayList(unsigned char);
void DelPlayList(unsigned char);
unsigned char ExistList(unsigned char);
unsigned char NextList(unsigned char, char);
void ClrRecList(void);
POINT_SAFE yard_safe_check(unsigned char, union POSITION);
void APP_Tasks(void) {
/* Check the application's current state. */
switch (appData.state) {
/* Application's initial state. */
case APP_STATE_INIT:
{
bool appInitialized = true;
char n;
DRV_ADC_Open(); //Enable ADC
//USART
if (handleUSART0 == DRV_HANDLE_INVALID) {
handleUSART0 = DRV_USART_Open(0, DRV_IO_INTENT_READWRITE | DRV_IO_INTENT_NONBLOCKING);
appInitialized &= (DRV_HANDLE_INVALID != handleUSART0);
}
//I2C Open
hi2c = DRV_I2C_Open(DRV_I2C_INDEX_0, DRV_IO_INTENT_READWRITE | DRV_IO_INTENT_NONBLOCKING);
if (hi2c != DRV_HANDLE_INVALID) {
//LCD初期化
LCD_int();
LCD_str("PC_REM");
LCD_cmd(0x0F);
}
ini_train(-1);
//列車A相
//train[0].mascon = 0x18; //スピードを変える時はここを変更
//union POSITION p1 = position_set(0, 1, 0, 0); //rose
//train_set(0, p1); //n,rosen,section,dir,sou
//train[0].STATUS.BIT.SP_MANU = 1;
for (n = 0; n < TR_COUNT; n++) {
train[n].mascon = 0;
cont_panel[n].point_num = -1;
}
//列車B相
//スピードを変える時はここを変更
//train[2].mascon = 0;
//train_set(1, 0, 5, 0, 1); //n,rosen,section,dir,sou
//ポイント(0) = New PointClass(New 位置情報(4, 0, 0, 0), New 位置情報(5, 1, 1, 0), 0)
//ポイント(1) = New PointClass(New 位置情報(4, 1, 0, 0), New 位置情報(5, 0, 1, 0), 0)
//区,路,向,sou
//ポイント(0) = New PointClass(New 位置情報(1, 0, 0, 0), New 位置情報(3, 1, 1, 0), 0)
//ポイント(1) = New PointClass(New 位置情報(2, 1, 0, 0), New 位置情報(2, 0, 1, 0), 0)
//ポイント(2) = New PointClass(New 位置情報(0, 1, 0, 0), New 位置情報(0, 2, 1, 0), 1)
//ポイント(3) = New PointClass(New 位置情報(3, 2, 0, 0), New 位置情報(7, 0, 1, 0), 2)
//ポイント情報設定
union POSITION p1;
union POSITION p2;
//TEST レイアイウト
// p1 = position_set(0, 4, 0, 0); //rosen,section,dir,sou
// p2 = position_set(1, 5, 1, 0);
// point_set(0, 0, p1, p2);
// p1 = position_set(1, 4, 0, 0);
// p2 = position_set(0, 5, 1, 0);
// point_set(1, 0, p1, p2);
//大 レイアイウト
p1 = position_set(0, 1, 0, 0); //rosen,section,dir,sou
p2 = position_set(1, 3, 1, 0);
point_set(0, 0, p1, p2);
p1 = position_set(1, 2, 0, 0);
p2 = position_set(0, 2, 1, 0);
point_set(1, 0, p1, p2);
//ポイント(2) = New PointClass(New 位置情報(0, 1, 0, 0), New 位置情報(0, 2, 1, 0), 1)
p1 = position_set(1, 0, 0, 0);
p2 = position_set(2, 0, 1, 0);
point_set(2, 1, p1, p2);
//ポイント(3) = New PointClass(New 位置情報(3, 2, 0, 0), New 位置情報(7, 0, 1, 0), 2)
p1 = position_set(2, 3, 0, 0);
p2 = position_set(0, 7, 1, 0);
point_set(3, 2, p1, p2);
//yard(0) = New YardClass(New 位置情報(7, 1, 1, 0), 3, "11010101", "01010001", 0)
//p1 = position_set(1, 1, 0, 0);
p1 = position_set(1, 7, 1, 0);
yard_set(0, p1, 3, 0b11010101, 0b1010001, 0); //n, p1, point, line, exist, type
p1 = position_set(0, 0, 0, 0);
yard_set(1, p1, 4, 0b11, 0b11, 1); //yard(1) = New YardClass(New 位置情報(0, 0, 0, 0), 4, "11", "01", 1)
//停止位置設定
//p1 = position_set(0, 5, 0, 0);
//stop_pos_set(0, p1, -1);
//行き止まり位置
p1 = position_set(2, 0, 1, 0); //車止位置(0) = New 停止位置class(New 位置情報(0, 2, 1, 0), 1)
stop_pos_set(0, p1, 1); //num,pos,point
p1 = position_set(2, 3, 0, 0); //車止位置(1) = New 停止位置class(New 位置情報(3, 2, 0, 0), 2)
stop_pos_set(1, p1, 2);
disp_mode = 0;
disp_page = 0;
speed_mode = 0;
count_dwn = 0;
DRV_TMR0_Start(); //TimerStart
DRV_TMR1_Start(); //TimerStart
if (appInitialized) {
appData.state = APP_STATE_SERVICE_TASKS;
}
break;
}
case APP_STATE_SERVICE_TASKS:
{
unsigned char n, p;
unsigned char ret;
union byte_access time_out;
long count;
rx_data[0] = 0;
rx_data[1] = 0;
time_out.INT = 0;
U1STAbits.OERR = 0; //受信バッファ・エラークリア
ret = 0;
while (ret != 0x55) {
//0x55が来るまでずーと待つ
while (!DRV_USART_ReceiverBufferIsEmpty(DRV_USART_INDEX_0)) {
ret = DRV_USART_ReadByte(DRV_USART_INDEX_0);
}
}
for (n = 1; n < RX_BYTE; n++) {
count = 0;
while (DRV_USART_ReceiverBufferIsEmpty(DRV_USART_INDEX_0)) {
if (count++ > 0xfffff)break;
}
if (count > 0xfffff)break; //TimeOutで外へ
rx_data[n] = DRV_USART_ReadByte(DRV_USART_INDEX_0);
}
//区間変化
for (n = 0; n < TR_COUNT; n++) {
p = n * RX_DATA_BYTE + 2;
if (rx_data[p + 2] == 0x80) {
if (train[n].STATUS.BIT.CHG_RCV == 0) {
section_chg(n);
train[n].STATUS.BIT.CHG_RCV = 1;
//Point SW
if (train[n].point_state == P_SW_ON) {
train[n].point_state = SWITCH_REQ;
}
//YARD SW
if (train[n].yard_state == Y_SW_ON) {
train[n].yard_state = YARD_REQ;
}
//Revers Request
if (train[n].revers_req == 1) {
train[n].STATUS.BIT.REV = 1;
train[n].revers_req = 0;
}
}
} else {
train[n].STATUS.BIT.CHG_RCV = 0;
}
//return speed
train[n].speed_ret.BYTE.L = rx_data[p + 1];
train[n].power.BYTE.H = rx_data[p + 5];
train[n].power.BYTE.L = rx_data[p + 6];
//Point CLR
if (train[n].point != 0) {
if (rx_data[p + 3] == train[n].point) {
train[n].point = 0;
}
}
//Yard CLR
if (train[n].yard != 0) {
if (rx_data[p + 4] == train[n].yard) {
train[n].yard = 0;
}
}
}
KeyCont();
rec_play(); //記録再生
point_process(); //ポイント処理
yard_process(); //YARD処理
stop_pos_process(); //停止位置処理
char time = 0;
#define DEF_BRK 20
#define BRAKE 100
#define SLOW_BRAKE 30
#define SLOW_SPEED 0x2c
#define SLOW_SPEED_P 0x38
#define SLOW_SPEED_Y 0x2c
int slow_speed = SLOW_SPEED;
for (n = 0; n < TR_COUNT; n++) {
if (train[n].NOW.BYTE != 0x38) {
//安全確認
switch (safe_check(n)) {
case STOP:
//停止
train[n].STATUS.BIT.SAFE = 0;
train[n].STATUS.BIT.SLOW = 0;
break;
case SLOW_POINT://point speed
slow_speed = SLOW_SPEED_P;
train[n].STATUS.BIT.SAFE = 1;
train[n].STATUS.BIT.SLOW = 1;
break;
case SLOW_YARD://yard speed
slow_speed = SLOW_SPEED_Y;
train[n].STATUS.BIT.SAFE = 1;
train[n].STATUS.BIT.SLOW = 1;
break;
case SLOW:
//減速
train[n].STATUS.BIT.SAFE = 1;
train[n].STATUS.BIT.SLOW = 1;
break;
case STOP_REV:
//向き合い停止
train[n].STATUS.BIT.SAFE = 0;
train[n].STATUS.BIT.SLOW = 0;
train[n].STATUS.BIT.REV = 1; //逆転
break;
case GO:
//安全
train[n].STATUS.BIT.SAFE = 1;
train[n].STATUS.BIT.SLOW = 0;
break;
}
//SpeedMode==DIRECT
if (speed_mode == 2)
train[0].STATUS.BIT.SP_MANU = 1;
else
train[0].STATUS.BIT.SP_MANU = 0;
//REVERS
if (train[n].STATUS.BIT.REV == 1) {
//逆転命令
//減速
if (speed_up_down(n, 0, DEF_BRK) == 0) {
//完全停止
if (stoppage_time(n, 10) == 0) {
//一時停車後逆転
reverse(n);
}
}
} else if (train[n].point_state == WAITING) {
//ポイント通過待ち
//停止
speed_up_down(n, 0, DEF_BRK);
} else if (train[n].yard_state == YARD_STOP) {
train[n].STATUS.BIT.SAFE = 0;
if (speed_up_down(n, 0, BRAKE) == 0) {
time = stoppage_time(n, 10);
if (time == 0) {
train[n].yard_state = YARD_STOP_COMP;
}
}
} else if (train[n].yard_state == POINT_RET) {
time = stoppage_time(n, 10);
if (time == 0) {
train[n].yard_state = POINT_RET_COMP;
}
} else {
if (train[n].STATUS.BIT.SAFE == 1) {
//安全
if (train[n].STATUS.BIT.SLOW == 1) {
//SLOW
if (train[n].mascon > slow_speed) {
speed_up_down(n, slow_speed, SLOW_BRAKE);
} else {
speed_up_down(n, train[n].mascon, DEF_BRK);
}
//speed direct modeの時SPEED AUTOに戻す。
if (speed_mode == 2) train[0].STATUS.BIT.SP_MANU = 0;
} else {
//加速
if (n == 0) {
if (speed_mode == 1)//マニュアルスピードの時ブレーキで減速
speed_up_down(n, train[n].mascon, -1);
else
speed_up_down(n, train[n].mascon, DEF_BRK);
} else {
speed_up_down(n, train[n].mascon, DEF_BRK);
}
}
} else {
//停止
speed_up_down(n, 0, BRAKE);
}
}
}
}
#define mascon_max 100
#define brake_max 30
if (!(rec_status == 2))//PlayModeはマスコンきかない
train[0].mascon = (adc_ret.INT >> 4) * mascon_max / 0x3F;
Brake = (adc_brk_ret.INT >> 4) * brake_max / 0x3F; //ブレーキ
Brake = brake_max - Brake; //値反転
//train[0].speed = train[0].mascon;
for (n = 2; n < 15; n++) {
//LCD_hex(rx_data[n]);
}
LcdDisp();
// LCD_posyx(0, 8);
// LCD_dec(r_enc, 2);
for (n = 0; n < TR_COUNT; n++) {
train[n].power.INT = train[n].power.INT * 20 / 0xF0; //LED MAX
train[n].speed_ret.INT = train[n].speed_ret.INT * 20 / 100; //LED MAX
}
//pic16f1827 slave
//---speed meter---
unsigned char led_pow = train[0].power.BYTE.L;
if (train[0].STATUS.BIT.SP_MANU)
led_pow = train[0].speed * 20 / 100;
if (train[0].NOW.BYTE == 0x38)led_pow = 0;
PIC_dat(0, train[0].speed_ret.BYTE.L, led_pow, 0x20);
led_pow = train[cont_sel].power.BYTE.L;
if (train[cont_sel].STATUS.BIT.SP_MANU)
led_pow = train[cont_sel].speed * 20 / 100;
if (train[cont_sel].NOW.BYTE == 0x38)led_pow = 0;
PIC_dat(0, train[cont_sel].speed_ret.BYTE.L, led_pow, 0x24);
//----demo----
//PIC_dat(0, 10, 13, 0x20);
//PIC_dat(0, 13, 10, 0x24);
//MAIN Cont LED
unsigned char led1 = cont_panel[0].LED.REVERS + cont_panel[0].LED.POINT * 2
+ cont_panel[0].LED.YARD * 4;
//SUB Cont LED
led1 += cont_panel[cont_sel].LED.REVERS * 8 + cont_panel[cont_sel].LED.POINT * 16
+ cont_panel[cont_sel].LED.YARD * 64;
unsigned char led2 = SelLED(cont_sel);
PIC_dat(0, led1, led2, 0x22);
break;
}
/* TODO: implement your application state machine.*/
/* The default state should never be executed. */
default:
{
/* TODO: Handle error in application's state machine. */
break;
}
}
}
char SelLED(char i) {
if (i >= 2) i++;
return EnableBit[i - 1];
}
void LcdDisp() {
char n;
switch (disp_mode) {
case 0:
LCD_posyx(0, 0);
LCD_str("P:");
if (cont_panel[0].point_num < 0)
LCD_str("N"); //NextPoint
else
LCD_dec(cont_panel[0].point_num, 1);
//LCD_str(" No:");
//LCD_dec(train[cont_sel].mascon, 3);
//LCD_hex(adc_brk_ret.BYTE.H);
//LCD_hex(adc_brk_ret.BYTE.L);
//LCD_dec(cont_sel, 1);
LCD_str(" P:");
if (cont_panel[cont_sel].point_num < 0)
LCD_str("N"); //NextPoint
else
LCD_dec(cont_panel[cont_sel].point_num, 1);
LCD_str(" SPD");
LCD_posyx(1, 0);
LCD_str("Y:");
LCD_dec(cont_panel[0].yard, 1);
LCD_str("-");
if (cont_panel[0].line < 9)
LCD_dec(cont_panel[0].line, 1);
else
LCD_str("X"); //不可表示
LCD_str(" Y:");
LCD_dec(cont_panel[cont_sel].yard, 1);
LCD_str("-");
if (cont_panel[cont_sel].line < 9)
LCD_dec(cont_panel[cont_sel].line, 1);
else
LCD_str("X"); //不可表示
LCD_str(" ");
LCD_dec(train[cont_sel].mascon, 3);
//LCD_hex(test2);
//LCD_hex(test1);
//Curser位置移動
LCD_posyx(SetPos_y[curser_pos], SetPos_x[curser_pos]);
break;
case 1:
switch (disp_page) {
case 0:
LCD_posyx(0, 0);
switch (speed_mode) {
case 0:
LCD_str("SPEED_AUTO ");
break;
case 1:
LCD_str("SPEED_MANUAL ");
break;
case 2:
LCD_str("SPEED_DIRECT ");
break;
}
LCD_posyx(1, 0);
LCD_str(" ");
break;
case 1:
LCD_posyx(0, 0);
// if (rec_status == 1)
// LCD_str("RECORDING ");
// else
// LCD_str("REC_STOP ");
LCD_str("PLAY MODE ");
LCD_posyx(1, 0);
LCD_str("REC MODE ");
break;
case 2:
LCD_posyx(0, 0);
if (rec_status == 0)
LCD_str("ERACE MODE ");
else
LCD_str(" ");
LCD_posyx(1, 0);
LCD_str("POINT TEST ");
break;
case 3:
LCD_posyx(0, 0);
LCD_str("D:");
LCD_dec(train[0].NOW.BIT.DIR, 1);
LCD_str(" R:");
LCD_dec(train[0].NOW.BIT.ROSEN, 1);
LCD_str(" K:");
LCD_dec(train[0].NOW.BIT.KUKAN, 1);
LCD_str(" S:");
LCD_dec(train[0].NOW.BIT.SOU, 1);
LCD_posyx(1, 0);
LCD_str("D:");
LCD_dec(train[1].NOW.BIT.DIR, 1);
LCD_str(" R:");
LCD_dec(train[1].NOW.BIT.ROSEN, 1);
LCD_str(" K:");
LCD_dec(train[1].NOW.BIT.KUKAN, 1);
LCD_str(" S:");
LCD_dec(train[1].NOW.BIT.SOU, 1);
break;
case 4:
LCD_posyx(0, 0);
for (n = disp_pos; n < disp_pos + 6; n++) {
LCD_hex(rec_list[n].pos.BYTE);
//LCD_hex(rec_list[n].speed);
}
LCD_dec(Brake, 3);
//LCD_dec(debug1.BYTE.H, 2);
//LCD_dec(debug1.BYTE.L, 2);
LCD_str(" ");
LCD_posyx(1, 0);
LCD_hex(step);
for (n = disp_pos; n < disp_pos + 6; n++) {
LCD_hex(rec_list[n].point);
}
//LCD_str(" ");
break;
}
break;
case 10://階層2 PLAY MODE
if (ExistList(prg_num) == 0)
prg_num = NextList(prg_num, -1);
if (rec_status == 0) {
//1行目
LCD_posyx(0, 0);
LCD_str("PLAY PRG No.");
LCD_dec(prg_num, 2);
//2行目
LCD_posyx(1, 0);
LCD_str("PLAY CANCEL");
} else if (rec_status == 2) {
//1行目
LCD_posyx(0, 0);
LCD_str("PLAY:");
LCD_dec(prg_num, 2);
LCD_str(" ");
LCD_dec(step, 2);
LCD_str("/");
LCD_dec(rec_list[0].pos.BYTE, 2);
LCD_str(" ");
LCD_dec(count_dwn, 2);
//2行目
LCD_posyx(1, 0);
if (repeat) {
LCD_str("STOP RPT OFF");
//LCD_dec(count_dwn, 2);
} else {
LCD_str("STOP RPT ON");
}
}
break;
case 11://階層2 REC MODE
LCD_posyx(0, 0);
LCD_str("REC MODE ");
LCD_posyx(1, 0);
LCD_str("START CANCEL");
break;
case 12://階層2 REC MODE
LCD_posyx(0, 0);
LCD_str("NOW RECORDIG... ");
LCD_posyx(1, 0);
LCD_str("STOP ");
LCD_dec(step, 2);
LCD_hex(rec_list[step].pos.BYTE);
LCD_hex(rec_list[step].yard.BYTE);
LCD_hex(rec_list[step].point.BYTE);
break;
case 13://階層3 REC END & SAVE?
LCD_posyx(0, 0);
LCD_str("SAVE PRG No.");
LCD_dec(prg_num, 2);
LCD_posyx(1, 0);
if (ExistList(prg_num))
LCD_str("(O/W)? CANCEL");
else
LCD_str("SAVE? CANCEL");
break;
case 14://階層2 ERACE
LCD_posyx(0, 0);
LCD_str("ERACE PRG No.");
LCD_dec(prg_num, 2);
LCD_posyx(1, 0);
LCD_str("OK? CANCEL");
break;
case 15://階層2 POINT TEST
LCD_posyx(0, 0);
LCD_str("POINT TEST ");
LCD_dec(point_test, 2);
LCD_posyx(1, 0);
LCD_str("CHG BACK");
break;
}
}
void KeyCont() {
//sel Button
if (cont_sel == 0) cont_sel = 1;
if (key_down[3] == 1) {
key_down[3] = 0;
if (++disp_mode > 1) disp_mode = 0;
}
//SubCont select SW
char n;
for (n = 0; n < TR_COUNT - 1; n++) {
if (key_down[n + 15] == 1) {
key_down[n + 15] = 0;
cont_sel = n + 1;
}
}
//Reverse SW
if (key_down[5] == 1) {
key_down[5] = 0;
if (train[0].NOW.BYTE == 0x38) {
//停車時 YARD出発方向設定の為
if (cont_panel[0].LED.REVERS == 0) {
cont_panel[0].LED.REVERS = 1;
} else {
cont_panel[0].LED.REVERS = 0;
}
} else {
//走行時
train[0].revers_req = 1;
//train[0].STATUS.BIT.REV = 1; //逆転
cont_panel[0].LED.REVERS = 1;
}
}
if (key_down[10] == 1) {
key_down[10] = 0;
if (train[cont_sel].NOW.BYTE == 0x38) {
//停車時 YARD出発方向設定の為
if (cont_panel[cont_sel].LED.REVERS == 0) {
cont_panel[cont_sel].LED.REVERS = 1;
} else {
cont_panel[cont_sel].LED.REVERS = 0;
}
} else {
//走行時
train[cont_sel].revers_req = 1;
//train[cont_sel].STATUS.BIT.REV = 1; //逆転
cont_panel[cont_sel].LED.REVERS = 1;
}
}
//Point SW
if (key_down[6] == 1) {
key_down[6] = 0;
if (train[0].point_state == NONE) {
cont_panel[0].LED.POINT = 1;
train[0].point_state = P_SW_ON;
} else if (train[0].point_state == SWITCH_REQ || train[0].point_state == P_SW_ON) {
cont_panel[0].LED.POINT = 0;
train[0].point_state = NONE;
}
}
if (key_down[11] == 1) {
key_down[11] = 0;
if (train[cont_sel].point_state == NONE) {
cont_panel[cont_sel].LED.POINT = 1;
train[cont_sel].point_state = P_SW_ON;
} else if (train[cont_sel].point_state == SWITCH_REQ || train[cont_sel].point_state == P_SW_ON) {
cont_panel[cont_sel].LED.POINT = 0;
train[cont_sel].point_state = NONE;
}
}
//Yard SW
if (key_down[7] == 1) {
key_down[7] = 0;
if (train[0].yard_state == YARD_NONE) {
cont_panel[0].LED.YARD = 1;
if (train[0].NOW.BYTE == 0x38)
train[0].yard_state = START_REQ; //登録なし
else
train[0].yard_state = Y_SW_ON; //走行中
//cont_panel[0].line = 7;
} else if (train[0].yard_state == YARD_REQ || train[0].yard_state == Y_SW_ON) {
cont_panel[0].LED.YARD = 0;
train[0].yard_state = YARD_NONE;
}
}
if (key_down[12] == 1) {
key_down[12] = 0;
if (train[cont_sel].yard_state == YARD_NONE) {
cont_panel[cont_sel].LED.YARD = 1;
if (train[cont_sel].NOW.BYTE == 0x38)
train[cont_sel].yard_state = START_REQ; //登録なし
else
train[cont_sel].yard_state = Y_SW_ON; //走行中
//cont_panel[cont_sel].line = 7;
} else if (train[cont_sel].yard_state == YARD_REQ || train[cont_sel].yard_state == Y_SW_ON) {
cont_panel[cont_sel].LED.YARD = 0;
train[cont_sel].yard_state = YARD_NONE;
}
}
switch (disp_mode) {
case 0://操作MODE
//Right Button
if (key_down[0] == 1) {
key_down[0] = 0;
if (++curser_pos >= CUR_MAX) curser_pos = 0;
//EEPROM TEST
//PIC_dat(0, 0, test1, 0xA0);
// for (n = 0; n < 32; n++) {
// eep_page_data[n + 2] = n;
// }
// EEP_Write(0, 1, 0xA0);
//
// for (n = 0; n < 32; n++) {
// eep_page_data[n + 2] = n + 32;
// }
// EEP_Write(32, 1, 0xA0);
//LoadPlayList();
test2 = 0;
}
//Left Button
if (key_down[2] == 1) {
key_down[2] = 0;
if (--curser_pos < 0) curser_pos = CUR_MAX - 1;
test1 = EEP_Read(test2++, 64, 0xA0);
}
//UP Button
if (key_down[1] == 1) {
key_down[1] = 0;
switch (curser_pos) {
case 0:
if (++cont_panel[0].point_num > POINT_COUNT - 1) cont_panel[0].point_num = -1;
break;
case 1:
if (++cont_panel[0].yard > YARD_COUNT - 1) cont_panel[0].yard = YARD_COUNT - 1;
cont_panel[0].line = yard_line_num(cont_panel[0].yard, 0, cont_panel[0].line, 0);
break;
case 2:
//if (++cont_panel[0].line > 5) cont_panel[0].line = 5;
cont_panel[0].line = yard_line_num(cont_panel[0].yard, 1, cont_panel[0].line, 0);
break;
case 3:
if (++cont_panel[cont_sel].point_num > POINT_COUNT - 1) cont_panel[cont_sel].point_num = -1;
break;
case 4:
if (++cont_panel[cont_sel].yard > YARD_COUNT - 1) cont_panel[cont_sel].yard = YARD_COUNT - 1;
cont_panel[cont_sel].line = yard_line_num(cont_panel[cont_sel].yard, 0, cont_panel[cont_sel].line, cont_sel);
break;
case 5:
//if (++cont_panel[cont_sel].line > 5) cont_panel[cont_sel].line = 5;
cont_panel[cont_sel].line = yard_line_num(cont_panel[cont_sel].yard, 1, cont_panel[cont_sel].line, cont_sel);
break;
}
}
//Down Button
if (key_down[4] == 1) {
key_down[4] = 0;
switch (curser_pos) {
case 0:
if (--cont_panel[0].point_num < -1) cont_panel[0].point_num = -1;
break;
case 1:
if (--cont_panel[0].yard < 0) cont_panel[0].yard = 0;
cont_panel[0].line = yard_line_num(cont_panel[0].yard, 0, cont_panel[0].line, 0);
break;
case 2:
//if (--cont_panel[0].line < 0) cont_panel[0].line = 0;
cont_panel[0].line = yard_line_num(cont_panel[0].yard, -1, cont_panel[0].line, 0);
break;
case 3:
if (--cont_panel[cont_sel].point_num < -1) cont_panel[cont_sel].point_num = -1;
break;
case 4:
if (--cont_panel[cont_sel].yard < 0) cont_panel[cont_sel].yard = 0;
cont_panel[cont_sel].line = yard_line_num(cont_panel[cont_sel].yard, 0, cont_panel[cont_sel].line, cont_sel);
break;
case 5:
//if (--cont_panel[cont_sel].line < 0) cont_panel[cont_sel].line = 0;
cont_panel[cont_sel].line = yard_line_num(cont_panel[cont_sel].yard, -1, cont_panel[cont_sel].line, cont_sel);
break;
}
}
break;
case 1:
//----------disp mode1----------
//Right Button
if (key_down[0] == 1) {
key_down[0] = 0;
if (disp_page < PAGE_MAX)
disp_page++;
}
//Left Button
if (key_down[2] == 1) {
key_down[2] = 0;
if (--disp_page < 0)disp_page = 0;
}
switch (disp_page) {
case 0://----SPEED MODE------
//Down Button
if (key_down[4] == 1) {
key_down[4] = 0;
if (++speed_mode > 2)speed_mode = 2; //speed_mode auto/manu
}
//Up Button
if (key_down[1] == 1) {
key_down[1] = 0;
if (--speed_mode < 0)speed_mode = 0; //speed_mode auto/manu
}
break;
case 1://-----Play/Rec ModeSelect-----
if (rec_status == 0) {//通常
//Up Button PLAY MODE
if (key_down[1] == 1) {
key_down[1] = 0;
disp_mode = 10; //DISP PLAY MODE
}
//Down Button REC MODE
if (key_down[4] == 1) {
key_down[4] = 0;
disp_mode = 11; //DISP REC MODE
}
} else if (rec_status == 2) {
//Playing
disp_mode = 10; //PlayMode
} else if (rec_status == 1) {
//Recording
disp_mode = 12; //NoeRecording
}
break;
case 2://ERACE MODE Select
if (rec_status == 0) {//通常
//Up Button ERACE MODE
if (key_down[1] == 1) {
key_down[1] = 0;
disp_mode = 14; //DISP ERACE MODE
}
//Down Button POINT TEST
if (key_down[4] == 1) {
key_down[4] = 0;
disp_mode = 15; //POINT TEST
}
}
break;
case 4://Debug Monitor
if (rec_status == 0) {//通常
//Up Button ERACE MODE
if (key_down[1] == 1) {
key_down[1] = 0;
disp_pos++;
}
//Down Button AUX
if (key_down[4] == 1) {
key_down[4] = 0;
if (disp_pos > 0)disp_pos--;
}
}
break;
}
break;
case 10://PLAY MODE
//階層2
//R Button //Cancel Repeat
if (key_down[0] == 1) {
key_down[0] = 0;
if (rec_status == 0) {
//CANCEL
disp_mode = 1; //表示戻し
} else if (rec_status == 2) {
//REPEAT
if (repeat)repeat = 0;
else repeat = 1;
}
}
//L Button PLAY START STOP
if (key_down[2] == 1) {
key_down[2] = 0;
if (rec_status == 0) {
//START
LoadPlayList(prg_num);
rec_status = 2;
} else if (rec_status == 2) {
//STOP
rec_status = 0;
}
}
//Up Button PRG No. +
if (key_down[1] == 1) {
key_down[1] = 0;
prg_num = NextList(prg_num, 1);
}
//Down Button Prg No. -
if (key_down[4] == 1) {
key_down[4] = 0;
prg_num = NextList(prg_num, -1);
}
break;
case 11://REC MODE
//階層2
if (rec_status == 0) {
//R Button
if (key_down[0] == 1) {
key_down[0] = 0;
//CANCEL
disp_mode = 1; //表示戻し
}
//L Button REC START
if (key_down[2] == 1) {
key_down[2] = 0;
rec_status = 1;
ClrRecList();
//disp_mode = 12; //DISP NOW RECORDING
}
} else if (rec_status == 1) {
disp_mode = 12; //DISP NOW RECORDING
}
break;
case 12://NOW RECORDING
//L Button REC STOP
if (key_down[2] == 1) {
key_down[2] = 0;
if (rec_status == 1) rec_status = 0;
disp_mode = 13; //REC END SAVE?
}
break;
case 13://REC END SAVE?
//階層3
//R Button
if (key_down[0] == 1) {
key_down[0] = 0;
//CANCEL
disp_mode = 1; //表示戻し
}
//L Button
if (key_down[2] == 1) {
key_down[2] = 0;
//Save Play List
SavePlayList(prg_num);
disp_mode = 1; //表示戻し
}
//Up Button PRG No. +
if (key_down[1] == 1) {
key_down[1] = 0;
prg_num++;
}
//Down Button Prg No. -
if (key_down[4] == 1) {
key_down[4] = 0;
if (prg_num > 0) prg_num--;
}
break;
case 14://ERACE MODE
//階層2
//R Button
if (key_down[0] == 1) {
key_down[0] = 0;
//CANCEL
disp_mode = 1; //表示戻し
}
//L Button
if (key_down[2] == 1) {
key_down[2] = 0;
//Delete Play List
DelPlayList(prg_num);
disp_mode = 1; //表示戻し
}
//Up Button PRG No. +
if (key_down[1] == 1) {
key_down[1] = 0;
prg_num = NextList(prg_num, 1);
}
//Down Button Prg No. -
if (key_down[4] == 1) {
key_down[4] = 0;
prg_num = NextList(prg_num, -1);
}
break;
case 15://POINT TEST
//階層2
//R Button
if (key_down[0] == 1) {
key_down[0] = 0;
//point 戻し
train[0].point = 0x80 + point_test;
//disp_mode = 1; //表示戻し
}
//L Button
if (key_down[2] == 1) {
key_down[2] = 0;
//point 切り替え
train[0].point = 0xC0 + point_test;
//disp_mode = 1; //表示戻し
}
//Up Button point No. +
if (key_down[1] == 1) {
key_down[1] = 0;
point_test++;
}
//Down Button point No. -
if (key_down[4] == 1) {
key_down[4] = 0;
if (point_test > 0)point_test--;
}
break;
}
}
void ini_train(char i) {
char n, st, ed;
if (i == -1) {
//全ての列車初期化
st = 0;
ed = TR_COUNT;
} else {
//指定の列車を初期化
st = i;
ed = i + 1;
}
for (n = st; n < ed; n++) {
train[n].BEFORE.BYTE = 0x38;
train[n].NOW.BYTE = 0x38;
train[n].NEXT.BYTE = 0x38;
train[n].ANEXT.BYTE = 0x38;
train[n].STATUS.BYTE = 0;
train[n].speed = 0;
train[n].henka = 0;
}
}
//void train_set(unsigned char n, unsigned char rosen, unsigned char sec, unsigned char dir, unsigned char sou)
void train_set(unsigned char n, union POSITION p1) {
// train[n].NOW.BIT.ROSEN = rosen;
// train[n].NOW.BIT.KUKAN = sec;
// train[n].NOW.BIT.DIR = dir;
// train[n].NOW.BIT.SOU = sou;
train[n].NOW.BIT.ROSEN = p1.BIT.ROSEN;
train[n].NOW.BIT.KUKAN = p1.BIT.KUKAN;
train[n].NOW.BIT.DIR = p1.BIT.DIR;
train[n].NOW.BIT.SOU = p1.BIT.SOU;
train[n].BEFORE.BYTE = train[n].NOW.BYTE;
train[n].NEXT.BYTE = train[n].NOW.BYTE;
train[n].ANEXT.BYTE = train[n].NOW.BYTE;
if (p1.BIT.DIR) {
//逆転
train[n].BEFORE.BIT.KUKAN++;
train[n].NEXT.BIT.KUKAN--;
train[n].ANEXT.BIT.KUKAN = train[n].NOW.BIT.KUKAN - 2;
} else {
//正転
train[n].BEFORE.BIT.KUKAN--;
train[n].NEXT.BIT.KUKAN++;
train[n].ANEXT.BIT.KUKAN += 2;
}
train[n].STATUS.BIT.CHG = 1;
train[n].STATUS.BIT.SAFE = 1;
}
//位置情報設定用
union POSITION position_set(unsigned char line, unsigned char section,
unsigned char dir, unsigned char phase) {
union POSITION ret;
ret.BIT.ROSEN = line;
ret.BIT.KUKAN = section;
ret.BIT.DIR = dir;
ret.BIT.SOU = phase;
return ret;
}
//ポイント位置設定
void point_set(unsigned char n, unsigned char num, union POSITION p1, union POSITION p2) {
point[n].approach = p1;
point[n].exit = p2;
point[n].num = num;
}
void yard_set(unsigned char n, union POSITION p1, unsigned char point, unsigned char line, unsigned char exist, unsigned char type) {
// 進入位置 = 位置.copy
// 停止位置 = 位置.copy
// 出口位置 = 位置.copy
//
// 停止位置.逆転()
// 停止位置.次区間() '停止位置は発車位置の逆の次区間
//
// 停止位置1 = 停止位置.copy
// 出口位置1 = 出口位置.copy
//
// 進入位置2 = 停止位置.copy
// 進入位置2.逆転()
// 発車位置2 = 停止位置.copy
//
// 停止位置2 = 発車位置.copy
// 出口位置2 = 発車位置2.copy
// 出口位置2.次区間()
yard[n].start = p1; //発車位置 = 位置.copy '位置は発車位置
//yard[n].start.BIT.DIR = ~p1.BIT.DIR;
yard[n].approach = p1;
yard[n].approach.BIT.DIR = ~p1.BIT.DIR; //進入位置.逆転() '進入位置は発車位置の逆転
yard[n].exit = next_position(yard[n].start); //出口位置.次区間() '出口位置は発車位置の次区間
//yard[n].start_b = p1;
yard[n].start_b = next_position(yard[n].approach); //発車位置Bは進入位置の次区間
//yard[n].approach_b = next_position(yard[n].approach);
yard[n].approach_b = yard[n].start_b; //進入位置Bは発車位置Bの逆転
yard[n].approach_b.BIT.DIR = p1.BIT.DIR;
yard[n].exit_b = next_position(yard[n].start_b); //出口位置.次区間() '出口位置は発車位置の次区間
yard[n].point_num = point;
yard[n].line = line;
yard[n].exist = exist;
yard[n].type = type;
if (type == 0) {
yard[n].approach_b.BYTE = 0xFF;
}
}
void yard_set_line(char n, char p, char mode) {
if (mode)
yard[n].exist |= EnableBit[p];
else
yard[n].exist &= ~EnableBit[p];
}
char yard_line_num(char n, char s, char p, char t) {
//n:yard um s:+- p:pos t:train_num
char pos = p + s;
pos &= 0b111;
unsigned char bit_p = EnableBit[pos];
//avl空き線
unsigned char avl = yard[n].line ^ yard[n].exist;
unsigned char line;
char mode = 0;
if (train[t].NOW.BYTE != 0x38) mode = 1;
if (mode)
line = avl;
else
line = yard[n].exist;
if (!line)return 9; //該当なし
while (!(line & bit_p)) {
if (s < 0) {
bit_p >>= 1;
if (bit_p == 0)bit_p = 0x80;
} else {
bit_p <<= 1;
if (bit_p == 0)bit_p = 1;
}
}
char c = 0;
while (!(bit_p == 1)) {
bit_p >>= 1;
c++;
}
return c;
}
//出口位置かどうか
bool point_exit_position(unsigned char n, union POSITION p) {
p.BIT.SOU = 0; //相マスク
p.BIT.DIR = ~p.BIT.DIR;
if (p.BIT.DIR == 0) {
if (point[n].approach.BYTE == p.BYTE)
return true;
else
return false;
} else {
if (point[n].exit.BYTE == p.BYTE)
return true;
else
return false;
}
}
int speed_up_down(char n, int speed, char k) {
//列車(n).speed += (列車(n).設定speed - 列車(n).speed) * 加速
char down;
int def = speed - train[n].speed;
int d;
char brk = 0;
if (k > 0) {
down = k;
if (def > 0)down = 30;
d = def * down / 100;
if (def < 0 && d>-1) d = def;
train[n].speed += d;
} else {
//Mnual Brake
brk = Brake;
if (def < 0) {
train[n].speed -= brk;
if (train[n].speed < 0)
train[n].speed = 0;
} else {
down = 30;
d = def * down / 100;
train[n].speed += d;
}
}
return train[n].power.INT;
return train[n].power.INT;
}
void section_chg(unsigned char n) {
train[n].BEFORE.BYTE = train[n].NOW.BYTE;
train[n].NOW.BYTE = train[n].NEXT.BYTE;
train[n].NEXT.BYTE = train[n].ANEXT.BYTE;
if (train[n].NOW.BIT.DIR) {
train[n].ANEXT.BIT.KUKAN--; //逆転
} else {
train[n].ANEXT.BIT.KUKAN++; //正転
}
//
train[n].STATUS.BIT.CHG = 1;
}
void reverse(unsigned char n) {
unsigned char before;
unsigned char dir = train[n].NOW.BIT.DIR;
if (dir) {
dir = 0;
} else {
dir = 1;
}
train[n].NOW.BIT.DIR = dir;
train[n].BEFORE.BIT.DIR = dir;
before = train[n].BEFORE.BYTE;
train[n].BEFORE.BYTE = train[n].NOW.BYTE;
train[n].NOW.BYTE = before;
train[n].NEXT.BYTE = before;
train[n].ANEXT.BYTE = before;
if (dir) {
//逆転
train[n].NEXT.BIT.KUKAN--;
train[n].ANEXT.BIT.KUKAN = train[n].NOW.BIT.KUKAN - 2;
} else {
//正転
train[n].NEXT.BIT.KUKAN++;
train[n].ANEXT.BIT.KUKAN += 2;
}
train[n].STATUS.BIT.REV = 0;
train[n].STATUS.BIT.SAFE = 1;
train[n].STATUS.BIT.CHG = 1;
cont_panel[n].LED.REVERS = 0;
}
int stoppage_time(char n, int t) {
//停車時間
static int timer[TR_COUNT + 1]; //
if (timer[n]-- == 0)
timer[n] = t; //停車時間
return timer[n];
}
unsigned char safe_check(unsigned char m) {
//安全確認
unsigned char n;
unsigned char ret = GO;
for (n = 0; n < TR_COUNT; n++) {
if (n != m) {
//次位置が他の列車の現、前、次位置と同じなら停止
if ((train[m].NEXT.BYTE & 0x3f) == (train[n].NOW.BYTE & 0x3f)) {
ret = STOP;
break;
}
if ((train[m].NEXT.BYTE & 0x3f) == (train[n].BEFORE.BYTE & 0x3f)) {
ret = STOP;
break;
}
if ((train[m].NEXT.BYTE & 0x3f) == (train[n].NEXT.BYTE & 0x3f)) {
ret = STOP;
break;
}
//次々位置が他の列車の現、前、次位置と同じなら減速
if ((train[m].ANEXT.BYTE & 0x3f) == (train[n].NOW.BYTE & 0x3f)) ret = SLOW;
if ((train[m].ANEXT.BYTE & 0x3f) == (train[n].BEFORE.BYTE & 0x3f)) ret = SLOW;
if ((train[m].ANEXT.BYTE & 0x3f) == (train[n].NEXT.BYTE & 0x3f)) ret = SLOW;
}
}
//停止の時、相手と方向が逆の時は優先順位が低いほうが逆転
if (ret == 1) {
if ((m > n) && (train[m].NOW.BIT.DIR != train[n].NOW.BIT.DIR)) {
ret = STOP_REV;
}
}
//STOP位置
for (n = 0; n < STOP_POS_COUNT; n++) {
if (stop_pos[n].point_num < 0) {// If p.ポイント番号 < 0 Then
//ポイントのない停止位置
if ((train[m].NOW.BYTE & 0xBF) == stop_pos[n].pos.BYTE) {// If 列車(n).現位置 = p.位置 Then
//現位置なら停止
return STOP; // 停止 = True
} else if ((train[m].NEXT.BYTE & 0xBF) == stop_pos[n].pos.BYTE) {// ElseIf 列車(n).次位置 = p.位置 Then
//'次位置なら減速
return SLOW_POINT; // 減速 = True
}
}
}
//通過形ヤードで空き線なしは通過不可
for (n = 0; n < YARD_COUNT; n++) {//For Each p As YardClass In yard
if (yard[n].type == 1) {//If p.type = 1 Then
//通過形ヤードの時
if (yard[n].exist == yard[n].line) {//If p.空線.Length = 0 Then
//空線なしの時
//If (列車(n).現位置 = p.進入位置) Or (列車(n).現位置 = p.進入位置2) Then
if ((train[m].NOW.BYTE & 0xbf) == yard[n].approach.BYTE ||
(train[m].NOW.BYTE & 0xbf) == yard[n].approach_b.BYTE) {
return STOP_REV; //逆転
}
}
}
}
//YARD進入待ち
if (train[m].yard_state == YARD_APR_WAIT) return STOP;
//Yard,Point進入 減速
if (train[m].yard_state == YARD_COMP || train[m].yard_state == POINT_COMP) {
return SLOW_YARD; //減速
}
if (train[m].point_state == SWITCHING) return SLOW_POINT; //減速
return ret;
}
POINT_SAFE yard_safe_check(unsigned char n, union POSITION pos) {
unsigned char c;
for (c = 0; c < TR_COUNT; c++) {
if (c != n) {
//位置が他の列車の現、前、次位置と同じなら非安全
if (pos.BIT.ROSEN == train[c].NOW.BIT.ROSEN && pos.BIT.KUKAN == train[c].NOW.BIT.KUKAN)
return WAIT_PASS;
if (pos.BIT.ROSEN == train[c].BEFORE.BIT.ROSEN && pos.BIT.KUKAN == train[c].BEFORE.BIT.KUKAN)
return WAIT_PASS;
if (pos.BIT.ROSEN == train[c].NEXT.BIT.ROSEN && pos.BIT.KUKAN == train[c].NEXT.BIT.KUKAN)
return WAIT_PASS;
if (pos.BIT.ROSEN == train[c].ANEXT.BIT.ROSEN && pos.BIT.KUKAN == train[c].ANEXT.BIT.KUKAN)
return WAIT_PASS;
}
}
return SAFE;
}
//ポイント位置かどうか
union POSITION point_pos(unsigned char p, union POSITION pos) {
//出口位置を返す
union POSITION ret;
char sou = pos.BIT.SOU;
pos.BIT.SOU = 0;
if (pos.BYTE == point[p].approach.BYTE) {
ret = point[p].exit;
ret.BIT.DIR = ~ret.BIT.DIR;
ret.BIT.SOU = sou;
return ret;
}
if (pos.BYTE == point[p].exit.BYTE) {
ret = point[p].approach;
ret.BIT.DIR = ~ret.BIT.DIR;
ret.BIT.SOU = sou;
return ret;
}
ret.BYTE = 0xff; //ポイント位置でない
return ret;
}
//次の区間
union POSITION next_position(union POSITION p) {
union POSITION ret = p;
unsigned char section = p.BIT.KUKAN;
if (p.BIT.DIR == 0) {//If 方向 = 0 Then
section = (section + 1)& 0b111; // 区間 = (区間 + 1) And &H7
} else {
section = (section - 1)& 0b111; // 区間 = (区間 - 1) And &H7
}
ret.BIT.KUKAN = section;
return ret;
}
//ポイント処理
void point_process() {
unsigned char n, p;
union POSITION next_pos;
for (n = 0; n < TR_COUNT; n++) {
switch (train[n].point_state) {//point処理状況
case SWITCH_REQ://Case p処理.切替要求, p処理.通過待ち
case WAITING:
//Point位置確認
for (p = 0; p < POINT_COUNT; p++) {
next_pos = point_pos(p, train[n].NOW); //Dim 次位置 As 位置情報 = ポイント(p).進入位置(列車(n).現位置)
//ポイント番号確認
//Select Case Remcon(n).point_num
//Case -1, ポイント(p).番号 '-1は次のポイント
//If Not 次位置 Is Nothing Then
if (next_pos.BYTE != 0xff) {
//debug1.BYTE.L = point_safe_check(n, next_pos);
switch (point_safe_check(n, next_pos)) {//Select Case ポイント安全確認(n, 次位置)
case SAFE://Case "安全"
//ポイント切り替え
train[n].point = 0xC0 + point[p].num; //列車(n).ポイント = &HC0 + ポイント(p).番号
train[n].NEXT = next_pos; //列車(n).次位置 = 次位置.copy
//次位置.次区間()
train[n].ANEXT = next_position(next_pos); //列車(n).次々位置 = 次位置.copy
train[n].STATUS.BIT.CHG = 1; //列車(n).区間変化 = True
//
train[n].point_state = SWITCHING; //列車(n).point処理状況 = p処理.切替中
train[n].point_num = p; //列車(n).ポイント番号 = p
//Remcon(n).CheckBox2.Enabled = False 'ポイントボタン不可
//Remcon(n).DomainUpDown1.Enabled = False
break;
case IMPOSSIBLE://Case "不可"
train[n].point_state = NONE;
cont_panel[n].LED.POINT = 0;
break;
case WAIT_PASS://Case "通過待ち"
train[n].point_state = WAITING; //列車(n).point処理状況 = p処理.通過待ち
break;
}
}
}
// case WAITING:
// break;
case SWITCHING://Case p処理.切替中
//出口位置確認
if (point_exit_position(train[n].point_num, train[n].BEFORE)) { //If ポイント(列車(n).ポイント番号).出口位置(列車(n).現位置) Then
//ポイント戻し
train[n].point = 0x80 + point[train[n].point_num].num; //列車(n).ポイント = &H80 + ポイント(列車(n).ポイント番号).番号
train[n].point_state = NONE; //列車(n).point処理状況 = p処理.なし
cont_panel[n].LED.POINT = 0;
//Remcon(n).CheckBox2.Enabled = True 'ポイントボタン可
//Remcon(n).DomainUpDown1.Enabled = True 'ポイント選択可
//Remcon(n).CheckBox2.Checked = False 'ポイントボタン戻し
// End If
}
break;
}
}
// Yard処理(n)
}
bool yard_approach_pos(unsigned char n, union POSITION pos, unsigned char p) {
// Dim n = ポイント番号 - 3
//
// Dim p = 番号位置変換(pos)
//
pos.BIT.SOU = 0;
if (yard[n].type == 0) {//If type = 0 Then
if (pos.BYTE == yard[n].approach.BYTE) {
yard[n].y_cont = 0x88 + n * 0x10 + p; //y制御Byte = &H88 + n * &H10 + p
yard[n].p_cont = 0xc0 + yard[n].point_num; //p制御Byte = &HC0 + ポイント番号
return true; // Return 位置 = 進入位置
}
} else {
// If 位置 = 進入位置 Then
if (pos.BYTE == yard[n].approach.BYTE) {
// 停止位置 = 停止位置1.copy
yard[n].y_cont = 0x80 + n * 0x10 + p * 2 + 1; //y制御Byte = &H80 + n * &H10 + &H1 + p * 2
//pos=0で戻し側 pos=1で切り替え側
yard[n].p_cont = 0x80 + p * 0x40 + yard[n].point_num; //p制御Byte = &H80 + p * &H40 + ポイント番号
return true; // Return True
} else {
if (pos.BYTE == yard[n].approach_b.BYTE) {// ElseIf 位置 = 進入位置2 Then
// '逆進入
// 停止位置 = 停止位置2.copy
yard[n].y_cont = 0x80 + n * 0x10 + p * 2; //y制御Byte = &H80 + n * &H10 + p * 2
//pos=0で戻し側 pos=1で切り替え側
yard[n].p_cont = 0x80 + p * 0x40 + yard[n].point_num; //p制御Byte = &H80 + p * &H40 + ポイント番号
return true; // Return True
}
}
}
return false;
}
bool yard_stop_pos(unsigned char n, union POSITION pos) {
union POSITION next_pos = next_position(yard[n].approach);
union POSITION next_pos_b = next_position(yard[n].approach_b);
pos.BIT.SOU = 0;
if (pos.BYTE == next_pos.BYTE) {
return true;
}
if (yard[n].type == 1) {
if (pos.BIT.DIR == 1) {
if (pos.BYTE == next_pos.BYTE) {
return true;
}
} else {
if (pos.BYTE == next_pos_b.BYTE) {
return true;
}
}
}
return false;
}
bool yard_exit_pos(unsigned char n, union POSITION pos) {
pos.BIT.SOU = 0;
if (yard[n].type == 0) {
//type 0
if (pos.BYTE == yard[n].exit.BYTE) {
return true;
}
} else {
//type 1
if (pos.BIT.DIR == 0) {
if (pos.BYTE == yard[n].exit.BYTE) {
return true;
}
} else {
if (pos.BYTE == yard[n].exit_b.BYTE) {
return true;
}
}
}
return false;
}
void yard_start_proc(unsigned char n, unsigned char pos, unsigned char d) {
// Dim n = ポイント番号 - 3
//
// Dim p = 番号位置変換(pos)
//
// If type = 0 Then
// y制御Byte = &H88 + n * &H10 + p
// p制御Byte = &HC0 + ポイント番号
// Else
// y制御Byte = &H80 + n * &H10 + p * 2 '*4
// p制御Byte = &H80 + p * &H40 + ポイント番号
//
// If d = 1 Then
// 出口位置 = 出口位置2.copy
// Else
// 出口位置 = 出口位置1.copy
// End If
// End If
if (yard[n].type == 0) {//If type = 0 Then
yard[n].y_cont = 0x88 + n * 0x10 + pos; //y制御Byte = &H88 + n * &H10 + p
yard[n].p_cont = 0xc0 + yard[n].point_num; //p制御Byte = &HC0 + ポイント番号
} else {
yard[n].y_cont = 0x80 + n * 0x10 + pos * 2; //y制御Byte = &H80 + n * &H10 + p * 2 '*4
//pos=0で戻し側 pos=1で切り替え側
yard[n].p_cont = 0x80 + pos * 0x40 + yard[n].point_num; //p制御Byte = &H80 + p * &H40 + ポイント番号
}
yard_set_line(n, pos, 0); //列車登録削除
}
void yard_end_proc(unsigned char n) {
yard[n].p_cont ^= 0x40; //p制御Byte = p制御Byte Xor &H40
if (yard[n].type == 0) {//If type = 0 Then
yard[n].y_cont &= 0xF0; //y制御Byte = y制御Byte And &HF0
} else {
// '反対側の線に切り替え
// y制御Byte = y制御Byte Xor &H2
yard[n].y_cont ^= 0x2;
}
}
void yard_start_end_proc(unsigned char n) {
if (yard[n].type == 0) {//If type = 0 Then
yard[n].y_cont &= 0xF0; //y制御Byte = y制御Byte And &HF0
yard[n].p_cont ^= 0x40; //p制御Byte = p制御Byte Xor &H40
} else {
if (yard[n].exist == 0) {//If 列車 <> 3 Then !=0b11
//0側空くときは0側へ切り替え (両側空きになるとき)
yard[n].y_cont &= 0xF8; //y制御Byte = y制御Byte And &HF8 '***
yard[n].p_cont &= 0xBF; //p制御Byte = p制御Byte And &HBF
}
//片側のみ空くときは何もしない。
}
}
void yard_process() {
unsigned char n, p;
union POSITION next_pos;
for (n = 0; n < TR_COUNT; n++) {
switch (train[n].yard_state) {
case YARD_REQ://Case y処理.Yard要求
case YARD_APR_WAIT://進入待ち
p = cont_panel[n].yard; //Dim p = Remcon(n).NumericUpDown1.Value - 1
//If 列車(n).区間変化 Then
if (yard_approach_pos(p, train[n].NOW, cont_panel[n].line)) {//If yard(p).進入位置確認(列車(n).現位置, Val(Remcon(n).DomainUpDown2.Text)) Then
if (yard_safe_check(n, train[n].NEXT) == SAFE) {//安全確認
//yard切り替え
//train[n].yard = 0x88 + p * 0x10 + cont_panel[n].line; //列車(n).yard = yard(p).y制御Byte
train[n].yard = yard[p].y_cont;
train[n].yard_state = YARD_COMP; //列車(n).yard処理状況 = y処理.Yard切替完了
train[n].yard_num = p; // 列車(n).yard番号 = p
// Remcon(n).Yard_Cont = False 'yard cont desable
} else {
train[n].yard_state = YARD_APR_WAIT;
}
}
break;
case YARD_COMP:
//Case y処理.Yard切替完了
//ポイント切り替え
if (train[n].yard == 0) {//列車(n).yard = 0 Then 'yard 切り替え確認
//train[n].point = 0xc0 + yard[train[n].yard_num].point_num; //列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
train[n].point = yard[train[n].yard_num].p_cont; //列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
train[n].yard_state = POINT_COMP; //列車(n).yard処理状況 = y処理.Yardポイント切替完了
}
break;
// Case y処理.Yardポイント切替完了
case POINT_COMP:
if (yard_stop_pos(train[n].yard_num, train[n].NOW)) {//If 列車(n).現位置 = yard(列車(n).yard番号).停止位置 Then
//yard停止
train[n].yard_state = YARD_STOP; //列車(n).yard処理状況 = y処理.Yard停止
}
break;
case YARD_STOP_COMP:// Case y処理.Yard完全停止
// 'Yardポイント戻し
yard_end_proc(train[n].yard_num); //yard(列車(n).yard番号).Yard終了処理()
//train[n].point = 0x80 + yard[train[n].yard_num].point_num; //列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
train[n].point = yard[train[n].yard_num].p_cont; //列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
train[n].yard_state = POINT_RET; //列車(n).yard処理状況 = y処理.Yardポイント戻し完了
// 'Timer2.Interval = 1000
// 'Timer2.Enabled = True 'ポイント切り替え待ち
// TM(n) = 10
break;
// Case y処理.Yardポイント戻し完了
case POINT_RET_COMP:
// If TM(n) = 0 Then
// 'TM(n) = False
// 'yard戻し
//train[n].yard = train[n].yard = 0x88 + train[n].yard_num * 0x10;
train[n].yard = yard[train[n].yard_num].y_cont; // 列車(n).yard = yard(列車(n).yard番号).y制御Byte
// 列車(n).yard処理状況 = y処理.Yard終了
train[n].yard_state = YARD_END;
// End If
break;
case YARD_END:// Case y処理.Yard終了
if (train[n].yard == 0) {//If 列車(n).yard = 0 Then 'yard 切り替え確認
yard_set_line(train[n].yard_num, cont_panel[n].line, 1); //yard(列車(n).yard番号).列車Set(True) = Val(Remcon(n).DomainUpDown2.Text)
ini_train(n); //列車(n) = New train() '列車Disable
train[n].STATUS.BIT.CHG = 1;
cont_panel[n].LED.YARD = 0; // Remcon(n).Yard_Cont = True 'yard cont enable
// RaiseEvent yard_chg()
train[n].yard_state = YARD_NONE;
}
break;
//
// Case y処理.Yard発車要求
case START_REQ:
p = cont_panel[n].yard; // Dim p = Remcon(n).NumericUpDown1.Value - 1
//yard切り替え
if (yard[p].type == 1) {// If yard(p).type = 1 Then
if (cont_panel[n].LED.REVERS == 1) {//If Remcon(n).CheckBox4.Checked Then '発車方向
//列車(n) = New train(yard(p).発車位置2)
train_set(n, yard[p].start_b);
} else {
//列車(n) = New train(yard(p).発車位置)
train_set(n, yard[p].start);
}
} else {
//列車(n) = New train(yard(p).発車位置)
train_set(n, yard[p].start);
}
// If Yard安全確認(n) Then
switch (point_safe_check(n, train[n].NOW)) {
case SAFE:
if (point_safe_check(n, train[n].BEFORE) == SAFE) {//前位置も確認
// If Remcon(n).CheckBox4.Checked Then
// '逆転戻し
// Remcon(n).CheckBox4.Checked = False
// End If
//
cont_panel[n].LED.REVERS = 0;
yard_start_proc(p, cont_panel[n].line, train[n].NOW.BIT.DIR); //yard(p).Yard発車処理(Val(Remcon(n).DomainUpDown2.Text), 列車(n).現位置.方向)
//yard_line_num(p, 0, cont_panel[n].line, n);
train[n].yard = yard[p].y_cont; //列車(n).yard = yard(p).y制御Byte
train[n].yard_state = START_REQ_ACK; //列車(n).yard処理状況 = y処理.Yard発車要求受付
train[n].yard_num = p; //列車(n).yard番号 = p
// Remcon(n).Yard_Cont = False 'yard cont desable
} else {
//WAIT_PASS
ini_train(n);
}
break;
case IMPOSSIBLE:
case WAIT_PASS:
// Else
ini_train(n); //列車(n) = New train() '列車Disable
//列車(n).yard処理状況 = y処理.Yard発車要求
// End If
break;
}
break;
// Case y処理.Yard発車要求受付
case START_REQ_ACK:
//ポイント切り替え
if (train[n].yard == 0) {//If 列車(n).yard = 0 Then 'yard 切り替え確認
train[n].point = yard[train[n].yard_num].p_cont; //列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
train[n].yard_state = READY_START; //列車(n).yard処理状況 = y処理.Yard発車準備完了
}
break;
case READY_START:// Case y処理.Yard発車準備完了
// If 列車(n).現位置 = yard(列車(n).yard番号).出口位置 Then
//if (train[n].NOW.BYTE == yard[train[n].yard_num].exit.BYTE) {
if (yard_exit_pos(train[n].yard_num, train[n].NOW)) {
// If 列車(n).ポイント = 0 Then
if (train[n].point == 0) {
//Yardポイント戻し
yard_start_end_proc(train[n].yard_num); //yard(列車(n).yard番号).Yard発車終了処理()
train[n].point = yard[train[n].yard_num].p_cont; //列車(n).ポイント = yard(列車(n).yard番号).p制御Byte
train[n].yard_state = EXIT_POS; //列車(n).yard処理状況 = y処理.Yard発車出口
// 'Timer2.Interval = 1000
// 'Timer2.Enabled = True 'ポイント切り替え待ち
// TM(n) = 10
}
}
break;
case EXIT_POS:// Case y処理.Yard発車出口
if (stoppage_time(n, 10) == 0) {//If TM(n) = 0 Then
// 'TM(n) = False
//yard戻し
train[n].yard = yard[train[n].yard_num].y_cont; //列車(n).yard = yard(列車(n).yard番号).y制御Byte
// yard(列車(n).yard番号).列車Set(False) = Val(Remcon(n).DomainUpDown2.Text)
train[n].yard_state = YARD_NONE; //列車(n).yard処理状況 = y処理.なし
// Remcon(n).Yard_Cont = True
// RaiseEvent yard_chg()
cont_panel[n].LED.YARD = 0;
//
// End If
}
break;
}
}
}
//Sub 相変更()
void change_phase(unsigned char n) {
if (train[n].NOW.BIT.SOU == 0) {// If 現位置.相 = 0 Then
train[n].NOW.BIT.SOU = 1; // 現位置.相 = 1
train[n].BEFORE.BIT.SOU = 1; // 前位置.相 = 1
train[n].NEXT.BIT.SOU = 1; // 次位置.相 = 1
train[n].ANEXT.BIT.SOU = 1; // 次々位置.相 = 1
} else {//Else
train[n].NOW.BIT.SOU = 0; // 現位置.相 = 0
train[n].BEFORE.BIT.SOU = 0; // 前位置.相 = 0
train[n].NEXT.BIT.SOU = 0; // 次位置.相 = 0
train[n].ANEXT.BIT.SOU = 0; // 次々位置.相 = 0
}
// 相変更FLAG = True
train[n].STATUS.BIT.CHG = 1; // 区間変化 = True
//
// End Sub
}
// Function ポイント安全確認(ByVal n As Integer, ByVal 位置 As 位置情報) As String
POINT_SAFE point_safe_check(unsigned char n, union POSITION pos) {
unsigned char opponent = 0; // Dim 相手 As Integer
unsigned char opponent_train_count = 0; // Dim 相手路線列車数 As Integer
unsigned char c;
unsigned char unsafe = 0; // Dim 停止 As Boolean
for (c = 0; c < TR_COUNT; c++) {
if (c != n) {
//位置が他の列車の現、前、次位置と同じなら非安全
if (pos.BIT.ROSEN == train[c].NOW.BIT.ROSEN && pos.BIT.KUKAN == train[c].NOW.BIT.KUKAN)
unsafe = 1;
if (pos.BIT.ROSEN == train[c].BEFORE.BIT.ROSEN && pos.BIT.KUKAN == train[c].BEFORE.BIT.KUKAN)
unsafe = 1;
if (pos.BIT.ROSEN == train[c].NEXT.BIT.ROSEN && pos.BIT.KUKAN == train[c].NEXT.BIT.KUKAN)
unsafe = 1;
if (pos.BIT.ROSEN == train[c].ANEXT.BIT.ROSEN && pos.BIT.KUKAN == train[c].ANEXT.BIT.KUKAN)
unsafe = 1;
//相手路線の列車数確認
if (pos.BIT.ROSEN == train[c].NOW.BIT.ROSEN) {
opponent_train_count++; //相手路線列車数 += 1
opponent = c; //相手 = m
}
}
}
debug1.BYTE.H = opponent_train_count;
debug1.BYTE.L = opponent;
//
//路線に列車が2台いるときはポイント切り替え不可
if (opponent_train_count >= 2) return IMPOSSIBLE; // If 相手路線列車数 >= 2 Then Return "不可"
debug1.BYTE.L = 2;
//
if (unsafe == 1) return WAIT_PASS; // If 停止 Then Return "通過待ち"
debug1.BYTE.L = 3;
//
//列車が1台いるときは相手の相を確認
if (opponent_train_count == 1) {//If 相手路線列車数 = 1 Then
//相が同じなら相手の相を変更
if (train[opponent].NOW.BIT.SOU == train[n].NOW.BIT.SOU) {//If 列車(相手).現位置.相 = 列車(n).現位置.相 Then
if (opponent < n) {
if (train[opponent].NOW.BIT.DIR != train[n].NOW.BIT.DIR) {//相手の優先順位高く方向が違う時はポイント不可
return IMPOSSIBLE;
}
}
change_phase(opponent); //列車(相手).相変更()
}
// End If
}
debug1.BYTE.L = 5;
return SAFE; //Return "安全"
}
void stop_pos_process() {
char n, m;
for (n = 0; n < TR_COUNT; n++) {//For n = 0 To 列車数 - 1
if (train[n].point_state == NONE) {//If 列車(n).point処理状況 = p処理.なし Then
for (m = 0; m < STOP_POS_COUNT; m++) {//For Each p As 停止位置class In 車止位置
if ((train[n].NOW.BYTE & 0xbf) == stop_pos[m].pos.BYTE) {//If 列車(n).現位置 = p.位置 Then
if (stop_pos[m].point_num >= 0) {//If p.ポイント番号 >= 0 Then
//ポイント切り替えON
cont_panel[n].LED.POINT = 1; //Remcon(n).CheckBox2.Checked = True
train[n].point_state = SWITCH_REQ; //列車(n).point処理状況 = p処理.切替要求
cont_panel[n].point_num = stop_pos[m].point_num; //Remcon(n).DomainUpDown2.Text = p.ポイント番号
}
}
}
}
}
}
void stop_pos_set(char n, union POSITION p, char point) {
stop_pos[n].pos = p;
stop_pos[n].point_num = point;
}
void rec_play() {
static char rise_edge;
//区間変化
if (train[0].STATUS.BIT.CHG_RCV == 1) {
if (!rise_edge) {
rise_edge = 1;
}
} else {
rise_edge = 0;
}
switch (rec_status) {
case 0:
step = 0;
step_stop = 0;
break;
case 1:
//RecMode
if (rise_edge == 1) {//区間変化
rise_edge = 2;
if (step < 127) step++;
rec_list[step].pos.BYTE = train[0].NOW.BYTE;
rec_list[step].speed = train[0].mascon;
//Yard SW ON?
if (train[0].yard_state == YARD_REQ) {
rec_list[step].yard.BIT.YARD = cont_panel[0].yard;
rec_list[step].yard.BIT.LINE = cont_panel[0].line;
rec_list[step].yard.BIT.ENABLE = 1; //EnaleBit
}
//POINT SW ON?
if (train[0].point_state == SWITCH_REQ) {
rec_list[step].point.BIT.POINT_NUM = cont_panel[0].point_num;
rec_list[step].point.BIT.ENABLE = 1; //EnaleBit
}
//Revers
if (train[0].STATUS.BIT.REV == 1) {
rec_list[step].point.BIT.REVERS = 1;
}
rec_list[0].pos.BYTE = step;
}
//停止中 Yard_Command
if (train[0].yard_state == START_REQ) {
if (step < 127) step++;
rec_list[step].yard.BIT.YARD = cont_panel[0].yard;
rec_list[step].yard.BIT.LINE = cont_panel[0].line;
rec_list[step].yard.BIT.ENABLE = 1;
rec_list[step].speed = train[0].mascon;
rec_list[0].pos.BYTE = step;
}
//Yard_Stop
if (train[0].yard_state == YARD_END) {
if (step < 127) step++;
rec_list[step].speed = 0xff;
rec_list[0].pos.BYTE = step;
}
break;
case 2:
//playmode
if (step > rec_list[0].pos.BYTE - 1) {
if (repeat) {
if (cont_panel[0].LED.YARD == 0) {//Yard Comp
count_dwn = stoppage_time(TR_COUNT, 20);
if (count_dwn == 0) {
step = 0; //PLAY START
step_stop = 0;
}
}
} else
rec_status = 0; //Play END
break;
}
if (step == step_stop) {
step++;
cont_panel[0].yard = rec_list[step].yard.BIT.YARD;
cont_panel[0].line = rec_list[step].yard.BIT.LINE;
train[0].mascon = rec_list[step].speed;
if (train[0].yard_state == YARD_NONE) {
cont_panel[0].LED.YARD = 1;
if (train[0].NOW.BYTE == 0x38)
train[0].yard_state = START_REQ; //登録なし
else
train[0].yard_state = Y_SW_ON; //走行中
step++;
}
} else {
if (rise_edge == 1) {//区間変化
rise_edge = 2;
if (rec_list[step].pos.BYTE == train[0].NOW.BYTE) {
train[0].mascon = rec_list[step].speed;
if (rec_list[step].yard.BIT.ENABLE) {//YardEnable
if (train[0].yard_state == YARD_NONE) {
cont_panel[0].LED.YARD = 1;
train[0].yard_state = YARD_REQ; //走行中
cont_panel[0].yard = rec_list[step].yard.BIT.YARD;
cont_panel[0].line = rec_list[step].yard.BIT.LINE;
}
}
//Point
if (rec_list[step].point.BIT.ENABLE) {
if (train[0].point_state == NONE) {
cont_panel[0].LED.POINT = 1;
train[0].point_state = SWITCH_REQ;
cont_panel[0].point_num = rec_list[step].point.BIT.POINT_NUM;
}
}
//Revers
if (rec_list[step].point.BIT.REVERS) {
if (train[0].point_state == NONE) {
cont_panel[0].LED.REVERS = 1;
train[0].STATUS.BIT.REV = 1;
}
}
if (step < 127) step++;
}
} else {
//---stop timer----
if (rec_list[step].speed == 0xff) {
if (cont_panel[0].LED.YARD == 0) {//Yard Comp
count_dwn = stoppage_time(TR_COUNT, 20);
if (count_dwn == 0) {
//step ++; //To Next Step
step_stop = step;
}
}
}
}
}
break;
}
}
void ClrRecList() {
unsigned char n;
for (n = 0; n < 128; n++) {
rec_list[n].pos.BYTE = 0;
rec_list[n].speed = 0;
rec_list[n].yard.BYTE = 0;
rec_list[n].point.BYTE = 0;
}
}
void SavePlayList(unsigned char prg) {
char bytes = sizeof rec_list[0];
unsigned char n, p;
unsigned char list_count = rec_list[0].pos.BYTE;
for (n = 0; n < list_count + 1; n++) {
p = n * bytes;
eep_data[p] = rec_list[n].pos.BYTE;
eep_data[p + 1] = rec_list[n].speed;
eep_data[p + 2] = rec_list[n].yard.BYTE;
eep_data[p + 3] = rec_list[n].point.BYTE;
}
//SAVE to EEP ROM
int start_adr = prg * 256;
for (p = 0; p < 8; p++) {//write 8 pages
for (n = 0; n < EEP_PAGE; n++) {
eep_page_data[n + 2] = eep_data[p * EEP_PAGE + n ];
}
EEP_Write(start_adr + p*EEP_PAGE, 1, 0xA0);
}
}
void LoadPlayList(unsigned char prg) {
char bytes = sizeof rec_list[0];
unsigned char n, p;
unsigned char list_count;
int start_adr = prg * 256;
list_count = EEP_Read(start_adr, 255, 0xA0);
for (n = 0; n < list_count + 1; n++) {
p = n * bytes;
rec_list[n].pos.BYTE = eep_data[p];
rec_list[n].speed = eep_data[p + 1];
rec_list[n].yard.BYTE = eep_data[p + 2];
rec_list[n].point.BYTE = eep_data[p + 3];
}
}
unsigned char ExistList(unsigned char prg) {
//PRGのステップ数を返す。
int start_adr = prg * 256;
unsigned char list_count = EEP_Read(start_adr, 1, 0xA0);
return list_count;
}
unsigned char NextList(unsigned char prg, char d) {
//登録済の次のPRGを返す。
unsigned char n = 0;
char p = prg;
for (n = 0; n < 10; n++) {
p += d;
if (p > 10) p = 0;
if (p < 0) p = 10;
if (ExistList(p) > 0) {
break;
}
}
return p;
}
void DelPlayList(unsigned char prg) {
//DELETE PRG リストの頭に0
eep_data[0] = 0;
int start_adr = prg * 256;
EEP_Write(start_adr, 0, 0xA0); //1BYTE WRITE
}
/*******************************************************************************
End of File
*/
system_interrrupt.cを編集 (SourceFiles➡app➡system_config➡default)
void __ISR(_TIMER_1_VECTOR, ipl7AUTO) IntHandlerDrvTmrInstance0(void)
{
PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_1);
timer_int_func();//追加
}
void __ISR(_TIMER_2_VECTOR, ipl6AUTO) IntHandlerDrvTmrInstance1(void)
{
PLIB_INT_SourceFlagClear(INT_ID_0,INT_SOURCE_TIMER_2);
timer_int_func_rs();//追加
}
/*******************************************************************************
End of File
*/














