記事一覧

日本の休日を取得する java 2021年版

2020年12月08日(火)00時27分

新型コロナの影響で東京オリンピックが延期されたことに伴い、2021年の休日も変更されています。

上記内容を反映したカレンダーに更新しました。
祝日の詳細は内閣府の下記サイトを参考にしてください。
https://www8.cao.go.jp/chosei/shukujitsu/gaiyou.html

/*
 * ファイル名: HolidayCalendar.java
 *
 * 処理概要:日本国祝日カレンダークラス
 * LastModify:2008 11/25
 * 群馬県太田市 ソフトウェア開発 Yamanaka
 * master@k1.wind.ne.jp
 *
 * Revised:2020/12/08
 * Tec Corp. Yumioka
 * te-kun@yumi-chan.com
 */


//#getIndexPointに使用
import java.awt.Point;

public class HolidayCalendar {


//初期不変値保存 年・月
private final int SET_YEAR;
private final int SET_MONTH;

//フィールド変数 年・月
private int m_Year;
private int m_Month;


/**
 * チェックする年・月で初期化。


 * 表示用年月値を定数とする為、コンストラクタはこれひとつだけにする
 *
 * @param  nYear   表示年
 * @param  nMonth  表示月
 */
public  HolidayCalendar(int nYear, int nMonth) throws  IllegalArgumentException {

if(nYear > 2150)               throw new IllegalArgumentException("年度指定は2150までです!");
if(nMonth < 1 || nMonth > 12) throw new IllegalArgumentException("月指定は1-12までです!!");

//☆表示用年月定数を有効にする
this.m_Year = SET_YEAR = nYear;
this.m_Month = SET_MONTH = nMonth;
}


/**
 * 先月にフィールドを設定する。

 * カレンダー表示の空白を埋めるのに一時使用メソッド
 */
public final void setLastMonthField() {

//先年取得
int pyear;
//先月取得
int pmon;

if(SET_MONTH==1) {
pyear = SET_YEAR - 1;
pmon = 12;
} else {
pyear = SET_YEAR;
pmon = SET_MONTH - 1;
}

this.m_Year = pyear;
this.m_Month = pmon;

}


/**
 * フィールドを初期値に戻す。

 * カレンダー表示の空白を埋めるのに一時使用したメソッドから、元に戻す為に使う
 *
 */
public final void reSetMonthField() {

this.m_Year = SET_YEAR;
this.m_Month = SET_MONTH;

}


/**
 * 来月にフィールドを設定する。

 * カレンダー表示の空白を埋めるのに一時使用メソッド
 *
 */
public final void setNextMonthField() {

//来年取得
int nyear;
//来月取得
int nmon;

if(SET_MONTH==12) {
nyear = SET_YEAR + 1;
nmon = 1;
} else {
nyear = SET_YEAR;
nmon = SET_MONTH + 1;
}

this.m_Year = nyear;
this.m_Month = nmon;

}

/**
 * 祝日チェック-> 名前取り出しメソッド。

 * 国民の祝日法は、1948年7月20日に施行される


 * 月ごとに処理を完結する

 *
 * @param nDay 検索日
 * @return 祝日名 or 無ければnull値
 */
public  final String  getHolidyName(int nDay) {
return getHolidyName(m_Year, m_Month, nDay);
}
public static final String  getHolidyName(int nYear, int nMonth, int nDay) {

int nSp, nAt;

switch(nMonth) {
/////1月  ●1/01元日(1949開始) ●1/15成人の日(1949)/第二月曜(2000開始)      □振替休日(1973.4/12開始)
case 1:

//1949年から開始される
if(nYear < 1949) break;

// 1/01元日
if(nDay==1) {

return "元日";

} else if(nDay==2) {

if(getWeekIndex(nYear, nMonth, 2)==1 && nYear >= 1974) return "振替休日";

//第二月曜日を成人の日とする
} else if(nYear >= 2000) {


//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==2) return "成人の日";

} else {

if(nDay==15) return "成人の日";
else if(nDay==16) {
if(getWeekIndex(nYear, nMonth, 16)==1 && nYear >= 1974) return "振替休日";
}
}

break;

/////2月  ●2/11建国記念の日(1967) 2/23天皇誕生日(2020.2/23開始)      □振替休日(1973.4/12開始)
case 2:

if(nYear < 1967) break;

//平成元年 1989.2/24 昭和天皇の大喪の礼
if(nYear == 1989 && nDay == 24) return "大喪の礼";

if(nDay==11) {

return "建国記念の日";

} else if(nDay==12) {

if(getWeekIndex(nYear, nMonth, 12)==1 && nYear >= 1974) return "振替休日";

}

if(nYear >= 2020) {

if (nDay == 23) {
return "天皇誕生日";

} else if(nDay==24) {

if(getWeekIndex(nYear, nMonth, 24)==1 && nYear >= 1973) return "振替休日";

}
}

break;

/////3月 ●春分の日(1949)                 □振替休日(1973.4/12開始)
case 3:

if(nYear < 1949) break;

nSp = koyomiSpring(nYear);

if(nDay == nSp) {

return "春分の日";

} else if(nDay==(nSp + 1)) {

if(getWeekIndex(nYear, nMonth, nDay)==1 && nYear >= 1974) return "振替休日";

}

break;

/////4月 ●4/29昭和天皇誕生日(1949-1988) /みどりの日(1989-2006) /昭和の日((2007-)  □振替休日(1973.4/12開始)
case 4:

if(nYear < 1949) break;

if(nDay==29) {

if(nYear >= 2007) {

return "昭和の日";

} else if(nYear >= 1989) {

return "みどりの日";

} else {

return "天皇誕生日";

}

} else if(nDay==30) {

if(getWeekIndex(nYear, nMonth, 30)==1 && nYear >= 1973) return "振替休日";

}

//昭和34年 1959.4/10 皇太子明仁親王の結婚の儀
if(nYear == 1959 && nDay == 10) return "結婚の儀";

//平成31年 2019.4/30 国民の休日
if(nYear == 2019 && nDay == 30) return "国民の休日";

break;

//5月 ●5/03憲法記念日(1949)  ●5/04国民の祝日(1986)みどりの日(2007)  ●5/05こどもの日(1949)  □振替休日(1973.4/12開始)
case 5:

if(nYear < 1949) break;

if(nDay==3) {

return "憲法記念日";

} else if(nDay==4) {

if(nYear>=2007) {

return "みどりの日";

} else if(nYear >= 1973) {

if(getWeekIndex(nYear, nMonth, 4)==1) {//憲法記念日の振替休日

return "振替休日";

} else if(getWeekIndex(nYear, nMonth, 4)!=0 && nYear>=1986) {//日曜日は、ただの日曜日

return "国民の休日";

}
}

} else if(nDay==5) {

return "こどもの日";

} else if(nDay==6) {

//曜日指数
int i_week = getWeekIndex(nYear, nMonth, 6);

if(i_week==1 && nYear >= 1973) { //5日の振替休日

return "振替休日";

} else if(nYear >= 2007) {  //駄目押し振替休日

if(i_week==2 || i_week==3) return "振替休日";

}

}
//令和元年年 2019.5/1 即位の日
if(nYear == 2019 && nDay == 1) return "即位の日";

//令和元年 2019.5/2 国民の休日
if(nYear == 2019 && nDay == 2) return "国民の休日";

//break;

/////6月
case 6:

//平成5年 1993.6/09 皇太子徳仁親王の結婚の儀
if(nYear == 1993 && nDay == 9) return "結婚の儀";

break;

/////7月 ●7/20海の日(1996開始) /第三月曜(2003開始)                 □振替休日(1973.4/12開始)
case 7:

if(nYear < 1996) break;

if(nYear >= 2003) {

if(nYear == 2020) {

/*2020年だけは「スポーツの日」が、オリンピック開会式の7月24日に移動します。
2020年は「海の日」が7月23日になります。 */

if(nDay==23) return "海の日";
if(nDay==24) return "スポーツの日";

} else if(nYear == 2021) {
/* 令和3年(2021年)に限り、「海の日」は7月22日に、「スポーツの日」は7月23日に、
 * 「山の日」は8月8日(※)になります。
 *(※)国民の祝日に関する法律(昭和23年法律第178号)第3条第2項の規定に基づき、8月9日は休日となります。
 */if(nDay==22) return "海の日";
if(nDay==23) return "スポーツの日";

} else {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==3)  return "海の日";
}

} else {

if(nDay==20)  return "海の日";
if(nDay==21 && getWeekIndex(nYear, nMonth, 21)==1) return "振替休日";

}

break;

/////8月 ●8/11山の日(2016開始)                 □振替休日(1973.4/12開始)
case 8:

if(nYear < 2016) break;

if(nYear == 2020) {

//2020年(令和2年)は東京五輪・パラリンピック特措法により、東京オリンピックの閉会式の翌日に当たる8月10日(月曜日)に変更される
if(nDay==10)  return "山の日";

} else if(nYear == 2021) {
/* 令和3年(2021年)に限り、「海の日」は7月22日に、「スポーツの日」は7月23日に、
 * 「山の日」は8月8日(※)になります。
 *(※)国民の祝日に関する法律(昭和23年法律第178号)第3条第2項の規定に基づき、8月9日は休日となります。
 */
if(nDay==8)  return "山の日";
if(nDay==9 && getWeekIndex(nYear, nMonth, 9)==1) return "振替休日";

} else {

if(nDay==11)  return "山の日";
if(nDay==12 && getWeekIndex(nYear, nMonth, 12)==1) return "振替休日";

}

break;

/////9月 ●9/15敬老の日(1966開始) /第三月曜(2003開始) ●秋分の日(1948開始)     □振替休日(1973.4/12開始)
case 9:

if(nYear < 1948) break;

nAt = koyomiAutumn(nYear);

if(nDay == nAt) {

return "秋分の日";

} else if(nDay==(nAt + 1)) {

if(getWeekIndex(nYear, nMonth, nDay)==1 && nYear >= 1973) return "振替休日";


} else if(nYear >= 2003) {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==3)  return "敬老の日";

//秋分の日の前日 (火曜で前日が敬老の日なら国民の休日になる)
if(nDay==(nAt-1) && getWeekIndex(nYear, nMonth, nDay)==2) {

//前日検査(秋分の日の二日前)
p = getIndexPoint(nYear, nMonth, nDay-1);
if(p.getX()==1 && p.getY()==3) return "国民の休日";

}

} else if(nYear >= 1966) {

if(nDay==15)  return "敬老の日";
if(nDay==16) {
if(getWeekIndex(nYear, nMonth, 16)==1 && nYear >= 1973) return "振替休日";
}

}

break;

/////10月 ●体育の日(1966開始) /第二月曜(2000開始-2019)               □振替休日(1973.4/12開始)
case 10:

if(nYear < 1966) break;

if(nYear >= 2000 && nYear <= 2019) {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==2) return "体育の日";

} else if (nYear == 2020 || nYear == 2021) {
//2020年以降、「体育の日」の名称は「スポーツの日」に改められます。
//また、2020年は「スポーツの日」が、オリンピック開会式の7月24日に移動します。
/* 令和3年(2021年)に限り、「海の日」は7月22日に、「スポーツの日」は7月23日に、
 * 「山の日」は8月8日(※)になります。
 *(※)国民の祝日に関する法律(昭和23年法律第178号)第3条第2項の規定に基づき、8月9日は休日となります。
 */
} else if (nYear >= 2022) {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==2) return "スポーツの日";

} else {

if(nDay==10)  return "体育の日";
if(nDay==11) {
if(getWeekIndex(nYear, nMonth, 11)==1 && nYear >= 1973) return "振替休日";
}
}

//令和元年 2019.10/22 即位礼正殿の儀
if(nYear == 2019 && nDay == 22)return "即位礼正殿の儀";

break;

/////11月 ●11/03文化の日(1948)  ●11/23勤労感謝の日(1948)                 □振替休日(1973.4/12開始)
case 11:

if(nYear < 1948) break;

if(nDay == 3) {

return "文化の日";

} else if(nDay == 4) {

if(getWeekIndex(nYear, nMonth, 4)==1 && nYear >= 1973) return "振替休日";

} else if(nDay == 23) {

return "勤労感謝の日";

} else if(nDay == 24) {

if(getWeekIndex(nYear, nMonth, 24)==1 && nYear >= 1973) return "振替休日";

}

//平成2年 1990.11/12 即位礼正殿の儀
if(nYear == 1990 && nDay == 12)return "即位礼正殿の儀";

break;

/////12月 ●12/23天皇誕生日(1989-2018)               □振替休日(1973.4/12開始)
case 12:

if(nYear < 1989) break;

if(nYear <= 2018) {

if(nDay == 23) return "天皇誕生日";
if(nDay == 24) {
if(getWeekIndex(nYear, nMonth, 24)==1) return "振替休日";
}
}

break;

}// end switch(1月~12月検索)


return null;

}// end method  getHolidyName(int nYear, int nMonth, int nDay)




/**
 * 春分の日取得
 * @return 春分の日
 */
public final int koyomiSpring () {
return koyomiSpringAutumn (m_Year, 3);
}

/**
 * 春分の日取得
 * @param nYear 検索年度
 * @return 春分の日
 */
public static final int koyomiSpring (int nYear) {
return koyomiSpringAutumn (nYear, 3);
}

/**
 * 秋分の日取得
 * @return 秋分の日
 */
public final int koyomiAutumn () {
return koyomiSpringAutumn (m_Year, 9);
}

/**
 * 秋分の日取得
 * @param nYear 検索年度
 * @return 秋分の日
 */
public static final int koyomiAutumn (int nYear) {
return koyomiSpringAutumn (nYear, 9);
}

/**
 * 処理:春分の日,秋分の日の計算 関数。

 * @param nYear   年
 * @param nMonth  月
 * @return 取得日(1851-2150年 && 3||9月以外は, 0を出力)
 */
public static final int koyomiSpringAutumn (int nYear, int nMonth)  {

if(nMonth!=3 && nMonth!=9) return 0;

float[] Spring = {19.8277f, 20.8357f, 20.8431f, 21.8510f};
float[] Autumn = {22.2588f, 23.2588f, 23.2488f, 24.2488f};

int pt=0, baseY=0;

if (nYear >= 1851 && nYear < 1900) { pt = 0; baseY = 1983;}
else if (nYear >= 1900 && nYear < 1980) { pt = 1; baseY = 1983;}
else if (nYear >= 1980 && nYear < 2100) { pt = 2; baseY = 1980;}
else if (nYear >= 2100 && nYear <= 2150){ pt = 3; baseY = 1980;}
else {
return 0;
}

int divide = (nYear - baseY) / 4;

int getday=0;

if (nMonth == 3) {
  getday = (int)(Spring[pt] + 0.242194 * (nYear - 1980) - divide);
} else if (nMonth == 9) {
  getday = (int)(Autumn[pt] + 0.242194 * (nYear - 1980) - divide);
}

return getday;

} // koyomiSpringAutume()







/**
 * 処理1: 月末日を取得。

 * @return 月末日
 */
public final int getMonthEnd_Day() {
return getMonthEnd_Day(m_Year, m_Month);
}

/**
 * 処理2: 月末日を取得。

 * @param  nYear 年
 * @param  nMon  月
 * @return  月末日
 */
public static final int getMonthEnd_Day(int nYear, int nMon) {

int[] MonthEnd = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

if( ((nYear % 4 == 0 ) && (nYear % 100 != 0)) || (nYear % 400 == 0) ){
MonthEnd[2] = 29;
}

return MonthEnd[nMon];

}






/**
 * 指定した日の曜日指数と、その月で何回目か出力する。

 * 成人の日や敬老の日などに使う

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nDay 指定日
 * @return 指定日の曜日指数(X)と、その曜日の回数(Y)
 */
public final Point getIndexPoint(int nDay) {
return getIndexPoint(m_Year, m_Month, nDay);
}

/**
 * 指定した日の曜日指数と、その月で何回目か出力する。
 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nYear  年
 * @param nMon   月
 * @param nDay   日
 * @return 指定日の曜日指数(X)と、その曜日の回数(Y)
 */
public static final Point getIndexPoint(int nYear, int nMon, int nDay) {

int x = getWeekIndex(nYear, nMon, nDay);
int y = (nDay-1) / 7  + 1;

return new Point(x, y);

}






/**
 * 検索日の曜日指数を出力する。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nDay 指定日
 * @return 曜日指数
 */
public final int getWeekIndex(int nDay) {
return getWeekIndex(m_Year, m_Month, nDay);
}


/**
 * 検索日の曜日指数を出力する。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nYear 指定年
 * @param nMon  月
 * @param nDay  日
 * @return 曜日指数
 */
public static final int getWeekIndex(int nYear, int nMon, int nDay) {

//1月または2月の場合は前年の13月および14月とみなす
if(nMon <= 2) {
nYear--;
nMon += 12;
}

int set1 = nYear / 4;
int set2 = nYear / 100;
int set3 = nYear / 400;
int set4 = (13 * nMon + 8) / 5;

return (nYear + set1 - set2 + set3 + set4 + nDay) % 7;

}




/**
 * 検索日の曜日指数を出す(年月に関係なしに算数計算)。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param SET_DAY     日付
 * @param SET_WEEK    日付の曜日指数
 * @param search_Day  検索日
 * @return 曜日指数
 */
public static final int getWeekChoice(int SET_DAY, int SET_WEEK, int search_Day) {

int n = (search_Day - SET_DAY) * -1;
return SET_WEEK - (n % 7);

}

/**
 * 検索日の曜日指数を出す(年月に関係なしに算数計算)。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param START_WEEK   一日の曜日指数
 * @param search_Day   検索日
 * @return 曜日指数
 */
public static final int getWeekChoice(int START_WEEK, int search_Day) {

return (START_WEEK + search_Day - 1) % 7;

}




/**
 * 総行数を算出。

 *
 * @return 総行数 (4|5|6)
 */
public  final int getRowCount(){
return getRowCount(m_Year, m_Month);
}

/**
 * 総行数を算出。

 *
 * @param nYear  年
 * @param nMon   月
 * @return 総行数 (4|5|6)
 */
public  static final int getRowCount(int nYear, int nMon){

int st_week = getWeekIndex(nYear, nMon, 1);
int endDay = getMonthEnd_Day(nYear, nMon);


int result = 5;

switch(st_week) {

 case 0:
if(endDay < 29) result = 4;

break;
 case 5:
if(endDay > 30) result =  6;

break;
 case 6:
if(endDay > 29) result =  6;

}//end switch

return result;

}


} //end class

日本の休日を取得する java

2019年11月11日(月)20時39分

カレンダーやスケジュールの作成で、結構困るのが、休日データの取得です。

元旦や建国記念の日といった固定した日であれば、困ることは少ないですが、第何月曜日とか、年によって日付が変わったりとか。

最近調べていて、みどりの日は面倒極まりないですね。

内閣府のサイトには、1955年から2020年までの休日データが公開されています。*1
https://www8.cao.go.jp/chosei/shukujitsu/syukujitsu.csv

ネットを探していたところ、HolidayCalendar.java を見つけました。
作者:Yamanaka様のサイトは下記です。
http://www6.wind.ne.jp/mode/SeikyuPlus.htm

作者様に了解いただいたので、2020年まで対応用に変更しました。*2
Yamanaka様 ありがとうございます。(^o^)

/*
 * ファイル名: HolidayCalendar.java
 *
 * 処理概要:日本国祝日カレンダークラス
 * LastModify:2008 11/25
 * 群馬県太田市 ソフトウェア開発 Yamanaka
 * master@k1.wind.ne.jp
 *
 * Revised:2019/11/10
 * Tec Corp. Yumioka
 * te-kun@yumi-chan.com
 */

//#getIndexPointに使用
import java.awt.Point;

public class HolidayCalendar {


//初期不変値保存 年・月
private final int SET_YEAR;
private final int SET_MONTH;

//フィールド変数 年・月
private int m_Year;
private int m_Month;


/**
 * チェックする年・月で初期化。


 * 表示用年月値を定数とする為、コンストラクタはこれひとつだけにする
 *
 * @param  nYear   表示年
 * @param  nMonth  表示月
 */
public  HolidayCalendar(int nYear, int nMonth) throws  IllegalArgumentException {

if(nYear > 2150)               throw new IllegalArgumentException("年度指定は2150までです!");
if(nMonth < 1 || nMonth > 12) throw new IllegalArgumentException("月指定は1-12までです!!");

//☆表示用年月定数を有効にする
this.m_Year = SET_YEAR = nYear;
this.m_Month = SET_MONTH = nMonth;
}


/**
 * 先月にフィールドを設定する。

 * カレンダー表示の空白を埋めるのに一時使用メソッド
 */
public final void setLastMonthField() {

//先年取得
int pyear;
//先月取得
int pmon;

if(SET_MONTH==1) {
pyear = SET_YEAR - 1;
pmon = 12;
} else {
pyear = SET_YEAR;
pmon = SET_MONTH - 1;
}

this.m_Year = pyear;
this.m_Month = pmon;

}


/**
 * フィールドを初期値に戻す。

 * カレンダー表示の空白を埋めるのに一時使用したメソッドから、元に戻す為に使う
 *
 */
public final void reSetMonthField() {

this.m_Year = SET_YEAR;
this.m_Month = SET_MONTH;

}


/**
 * 来月にフィールドを設定する。

 * カレンダー表示の空白を埋めるのに一時使用メソッド
 *
 */
public final void setNextMonthField() {

//来年取得
int nyear;
//来月取得
int nmon;

if(SET_MONTH==12) {
nyear = SET_YEAR + 1;
nmon = 1;
} else {
nyear = SET_YEAR;
nmon = SET_MONTH + 1;
}

this.m_Year = nyear;
this.m_Month = nmon;

}

/**
 * 祝日チェック-> 名前取り出しメソッド。

 * 国民の祝日法は、1948年7月20日に施行される


 * 月ごとに処理を完結する

 *
 * @param nDay 検索日
 * @return 祝日名 or 無ければnull値
 */
public  final String  getHolidyName(int nDay) {
return getHolidyName(m_Year, m_Month, nDay);
}
public static final String  getHolidyName(int nYear, int nMonth, int nDay) {

int nSp, nAt;

switch(nMonth) {
/////1月  ●1/01元日(1949開始) ●1/15成人の日(1949)/第二月曜(2000開始)      □振替休日(1973.4/12開始)
case 1:

//1949年から開始される
if(nYear < 1949) break;

// 1/01元日
if(nDay==1) {

return "元日";

} else if(nDay==2) {

if(getWeekIndex(nYear, nMonth, 2)==1 && nYear >= 1974) return "振替休日";

//第二月曜日を成人の日とする
} else if(nYear >= 2000) {


//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==2) return "成人の日";

} else {

if(nDay==15) return "成人の日";
else if(nDay==16) {
if(getWeekIndex(nYear, nMonth, 16)==1 && nYear >= 1974) return "振替休日";
}
}

break;

/////2月  ●2/11建国記念の日(1967) 2/23天皇誕生日(2020.2/23開始)      □振替休日(1973.4/12開始)
case 2:

if(nYear < 1967) break;

//平成元年 1989.2/24 昭和天皇の大喪の礼
if(nYear == 1989 && nDay == 24) return "大喪の礼";

if(nDay==11) {

return "建国記念の日";

} else if(nDay==12) {

if(getWeekIndex(nYear, nMonth, 12)==1 && nYear >= 1974) return "振替休日";

}

if(nYear >= 2020) {

if (nDay == 23) {
return "天皇誕生日";

} else if(nDay==24) {

if(getWeekIndex(nYear, nMonth, 24)==1 && nYear >= 1973) return "振替休日";

}
}

break;

/////3月 ●春分の日(1949)                 □振替休日(1973.4/12開始)
case 3:

if(nYear < 1949) break;

nSp = koyomiSpring(nYear);

if(nDay == nSp) {

return "春分の日";

} else if(nDay==(nSp + 1)) {

if(getWeekIndex(nYear, nMonth, nDay)==1 && nYear >= 1974) return "振替休日";

}

break;

/////4月 ●4/29昭和天皇誕生日(1949-1988) /みどりの日(1989-2006) /昭和の日((2007-)  □振替休日(1973.4/12開始)
case 4:

if(nYear < 1949) break;

if(nDay==29) {

if(nYear >= 2007) {

return "昭和の日";

} else if(nYear >= 1989) {

return "みどりの日";

} else {

return "天皇誕生日";

}

} else if(nDay==30) {

if(getWeekIndex(nYear, nMonth, 30)==1 && nYear >= 1973) return "振替休日";

}

//昭和34年 1959.4/10 皇太子明仁親王の結婚の儀
if(nYear == 1959 && nDay == 10) return "結婚の儀";

//平成31年 2019.4/30 国民の休日
if(nYear == 2019 && nDay == 30) return "国民の休日";

break;

//5月 ●5/03憲法記念日(1949)  ●5/04国民の祝日(1986)みどりの日(2007)  ●5/05こどもの日(1949)  □振替休日(1973.4/12開始)
case 5:

if(nYear < 1949) break;

if(nDay==3) {

return "憲法記念日";

} else if(nDay==4) {

if(nYear>=2007) {

return "みどりの日";

} else if(nYear >= 1973) {

if(getWeekIndex(nYear, nMonth, 4)==1) {//憲法記念日の振替休日

return "振替休日";

} else if(getWeekIndex(nYear, nMonth, 4)!=0 && nYear>=1986) {//日曜日は、ただの日曜日

return "国民の休日";

}
}

} else if(nDay==5) {

return "こどもの日";

} else if(nDay==6) {

//曜日指数
int i_week = getWeekIndex(nYear, nMonth, 6);

if(i_week==1 && nYear >= 1973) { //5日の振替休日

return "振替休日";

} else if(nYear >= 2007) {  //駄目押し振替休日

if(i_week==2 || i_week==3) return "振替休日";

}

}
//令和元年年 2019.5/1 即位の日
if(nYear == 2019 && nDay == 1) return "即位の日";

//令和元年 2019.5/2 国民の休日
if(nYear == 2019 && nDay == 2) return "国民の休日";

//break;

/////6月
case 6:

//平成5年 1993.6/09 皇太子徳仁親王の結婚の儀
if(nYear == 1993 && nDay == 9) return "結婚の儀";

break;

/////7月 ●7/20海の日(1996開始) /第三月曜(2003開始)                 □振替休日(1973.4/12開始)
case 7:

if(nYear < 1996) break;

if(nYear >= 2003) {

if(nYear == 2020) {

/*2020年だけは「スポーツの日」が、オリンピック開会式の7月24日に移動します。
2020年は「海の日」が7月23日になります。 */

if(nDay==23) return "海の日";
if(nDay==24) return "スポーツの日";

} else {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==3)  return "海の日";
}

} else {

if(nDay==20)  return "海の日";
if(nDay==21 && getWeekIndex(nYear, nMonth, 21)==1) return "振替休日";

}

break;

/////8月 ●8/11山の日(2016開始)                 □振替休日(1973.4/12開始)
case 8:

if(nYear < 2016) break;

if(nYear == 2020) {

//2020年(令和2年)は東京五輪・パラリンピック特措法により、東京オリンピックの閉会式の翌日に当たる8月10日(月曜日)に変更される
if(nDay==10)  return "山の日";

} else {

if(nDay==11)  return "山の日";
if(nDay==12 && getWeekIndex(nYear, nMonth, 12)==1) return "振替休日";

}

break;

/////9月 ●9/15敬老の日(1966開始) /第三月曜(2003開始) ●秋分の日(1948開始)     □振替休日(1973.4/12開始)
case 9:

if(nYear < 1948) break;

nAt = koyomiAutumn(nYear);

if(nDay == nAt) {

return "秋分の日";

} else if(nDay==(nAt + 1)) {

if(getWeekIndex(nYear, nMonth, nDay)==1 && nYear >= 1973) return "振替休日";


} else if(nYear >= 2003) {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==3)  return "敬老の日";

//秋分の日の前日 (火曜で前日が敬老の日なら国民の休日になる)
if(nDay==(nAt-1) && getWeekIndex(nYear, nMonth, nDay)==2) {

//前日検査(秋分の日の二日前)
p = getIndexPoint(nYear, nMonth, nDay-1);
if(p.getX()==1 && p.getY()==3) return "国民の休日";

}

} else if(nYear >= 1966) {

if(nDay==15)  return "敬老の日";
if(nDay==16) {
if(getWeekIndex(nYear, nMonth, 16)==1 && nYear >= 1973) return "振替休日";
}

}

break;

/////10月 ●体育の日(1966開始) /第二月曜(2000開始-2019)               □振替休日(1973.4/12開始)
case 10:

if(nYear < 1966) break;

if(nYear >= 2000 && nYear <= 2019) {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==2) return "体育の日";

} else if (nYear == 2020) {
//2020年以降、「体育の日」の名称は「スポーツの日」に改められます。
//また、2020年だけは「スポーツの日」が、オリンピック開会式の7月24日に移動します。

} else if (nYear >= 2021) {

//指定日の曜日指数(X)と、その曜日の回数(Y)
Point p = getIndexPoint(nYear, nMonth, nDay);
if(p.getX()==1 && p.getY()==2) return "スポーツの日";

} else {

if(nDay==10)  return "体育の日";
if(nDay==11) {
if(getWeekIndex(nYear, nMonth, 11)==1 && nYear >= 1973) return "振替休日";
}
}

//令和元年 2019.10/22 即位礼正殿の儀
if(nYear == 2019 && nDay == 22)return "即位礼正殿の儀";

break;

/////11月 ●11/03文化の日(1948)  ●11/23勤労感謝の日(1948)                 □振替休日(1973.4/12開始)
case 11:

if(nYear < 1948) break;

if(nDay == 3) {

return "文化の日";

} else if(nDay == 4) {

if(getWeekIndex(nYear, nMonth, 4)==1 && nYear >= 1973) return "振替休日";

} else if(nDay == 23) {

return "勤労感謝の日";

} else if(nDay == 24) {

if(getWeekIndex(nYear, nMonth, 24)==1 && nYear >= 1973) return "振替休日";

}

//平成2年 1990.11/12 即位礼正殿の儀
if(nYear == 1990 && nDay == 12)return "即位礼正殿の儀";

break;

/////12月 ●12/23天皇誕生日(1989-2018)               □振替休日(1973.4/12開始)
case 12:

if(nYear < 1989) break;

if(nYear <= 2018) {

if(nDay == 23) return "天皇誕生日";
if(nDay == 24) {
if(getWeekIndex(nYear, nMonth, 24)==1) return "振替休日";
}
}

break;

}// end switch(1月~12月検索)


return null;

}// end method  getHolidyName(int nYear, int nMonth, int nDay)




/**
 * 春分の日取得
 * @return 春分の日
 */
public final int koyomiSpring () {
return koyomiSpringAutumn (m_Year, 3);
}

/**
 * 春分の日取得
 * @param nYear 検索年度
 * @return 春分の日
 */
public static final int koyomiSpring (int nYear) {
return koyomiSpringAutumn (nYear, 3);
}

/**
 * 秋分の日取得
 * @return 秋分の日
 */
public final int koyomiAutumn () {
return koyomiSpringAutumn (m_Year, 9);
}

/**
 * 秋分の日取得
 * @param nYear 検索年度
 * @return 秋分の日
 */
public static final int koyomiAutumn (int nYear) {
return koyomiSpringAutumn (nYear, 9);
}

/**
 * 処理:春分の日,秋分の日の計算 関数。

 * @param nYear   年
 * @param nMonth  月
 * @return 取得日(1851-2150年 && 3||9月以外は, 0を出力)
 */
public static final int koyomiSpringAutumn (int nYear, int nMonth)  {

if(nMonth!=3 && nMonth!=9) return 0;

float[] Spring = {19.8277f, 20.8357f, 20.8431f, 21.8510f};
float[] Autumn = {22.2588f, 23.2588f, 23.2488f, 24.2488f};

int pt=0, baseY=0;

if (nYear >= 1851 && nYear < 1900) { pt = 0; baseY = 1983;}
else if (nYear >= 1900 && nYear < 1980) { pt = 1; baseY = 1983;}
else if (nYear >= 1980 && nYear < 2100) { pt = 2; baseY = 1980;}
else if (nYear >= 2100 && nYear <= 2150){ pt = 3; baseY = 1980;}
else {
return 0;
}

int divide = (nYear - baseY) / 4;

int getday=0;

if (nMonth == 3) {
  getday = (int)(Spring[pt] + 0.242194 * (nYear - 1980) - divide);
} else if (nMonth == 9) {
  getday = (int)(Autumn[pt] + 0.242194 * (nYear - 1980) - divide);
}

return getday;

} // koyomiSpringAutume()







/**
 * 処理1: 月末日を取得。

 * @return 月末日
 */
public final int getMonthEnd_Day() {
return getMonthEnd_Day(m_Year, m_Month);
}

/**
 * 処理2: 月末日を取得。

 * @param  nYear 年
 * @param  nMon  月
 * @return  月末日
 */
public static final int getMonthEnd_Day(int nYear, int nMon) {

int[] MonthEnd = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

if( ((nYear % 4 == 0 ) && (nYear % 100 != 0)) || (nYear % 400 == 0) ){
MonthEnd[2] = 29;
}

return MonthEnd[nMon];

}






/**
 * 指定した日の曜日指数と、その月で何回目か出力する。

 * 成人の日や敬老の日などに使う

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nDay 指定日
 * @return 指定日の曜日指数(X)と、その曜日の回数(Y)
 */
public final Point getIndexPoint(int nDay) {
return getIndexPoint(m_Year, m_Month, nDay);
}

/**
 * 指定した日の曜日指数と、その月で何回目か出力する。
 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nYear  年
 * @param nMon   月
 * @param nDay   日
 * @return 指定日の曜日指数(X)と、その曜日の回数(Y)
 */
public static final Point getIndexPoint(int nYear, int nMon, int nDay) {

int x = getWeekIndex(nYear, nMon, nDay);
int y = (nDay-1) / 7  + 1;

return new Point(x, y);

}






/**
 * 検索日の曜日指数を出力する。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nDay 指定日
 * @return 曜日指数
 */
public final int getWeekIndex(int nDay) {
return getWeekIndex(m_Year, m_Month, nDay);
}


/**
 * 検索日の曜日指数を出力する。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param nYear 指定年
 * @param nMon  月
 * @param nDay  日
 * @return 曜日指数
 */
public static final int getWeekIndex(int nYear, int nMon, int nDay) {

//1月または2月の場合は前年の13月および14月とみなす
if(nMon <= 2) {
nYear--;
nMon += 12;
}

int set1 = nYear / 4;
int set2 = nYear / 100;
int set3 = nYear / 400;
int set4 = (13 * nMon + 8) / 5;

return (nYear + set1 - set2 + set3 + set4 + nDay) % 7;

}




/**
 * 検索日の曜日指数を出す(年月に関係なしに算数計算)。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param SET_DAY     日付
 * @param SET_WEEK    日付の曜日指数
 * @param search_Day  検索日
 * @return 曜日指数
 */
public static final int getWeekChoice(int SET_DAY, int SET_WEEK, int search_Day) {

int n = (search_Day - SET_DAY) * -1;
return SET_WEEK - (n % 7);

}

/**
 * 検索日の曜日指数を出す(年月に関係なしに算数計算)。

 *  ※曜日指数  0日曜日 ~ 6土曜日

 *
 * @param START_WEEK   一日の曜日指数
 * @param search_Day   検索日
 * @return 曜日指数
 */
public static final int getWeekChoice(int START_WEEK, int search_Day) {

return (START_WEEK + search_Day - 1) % 7;

}




/**
 * 総行数を算出。

 *
 * @return 総行数 (4|5|6)
 */
public  final int getRowCount(){
return getRowCount(m_Year, m_Month);
}

/**
 * 総行数を算出。

 *
 * @param nYear  年
 * @param nMon   月
 * @return 総行数 (4|5|6)
 */
public  static final int getRowCount(int nYear, int nMon){

int st_week = getWeekIndex(nYear, nMon, 1);
int endDay = getMonthEnd_Day(nYear, nMon);


int result = 5;

switch(st_week) {

 case 0:
if(endDay < 29) result = 4;

break;
 case 5:
if(endDay > 30) result =  6;

break;
 case 6:
if(endDay > 29) result =  6;

}//end switch

return result;

}

} //end class

*1:公開当初はひどい内容だったらしくダメ出しされたようです。
*2:2年以上先の休日は決まっていないようです。

野球ゲームをつくる ~ 12.野球ゲームの完成

2015年06月16日(火)22時32分

野球ゲームをつくる ~ 12.野球ゲームの完成

これまで、モジュールを作成してきましたが、つなぎあわして野球ゲームを完成させます。

まず、ボードのInput/Outputをおさらいします。
野球ゲームをつくる ~ 1.仕様の作成 にある仕様を元にボードの配置は下図のとおりです。

ファイル 107-1.jpg

ピン配置は下図です。

ファイル 107-2.jpg

回路図(RTL)は下図です。

ファイル 107-3.jpg

baseball_game.vhd

-- BASEBALL GAME TOP Entity
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity BASEBALL_GAME is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        STARTSTOP_SW: in  std_logic;
        INING_SW    : in  std_logic;
        MODE_SW     : in  std_logic;
        LED_TEAM1   : out std_logic;
        LED_TEAM2   : out std_logic;
        LED_ASSIST  : out std_logic;
        LED_MODE    : out std_logic;
        LED_BASE    : out std_logic_vector(2 downto 0);
        LED_OUT     : out std_logic_vector(1 downto 0);
        LED_SCORE1  : out std_logic_vector(7 downto 1);
        LED_SCORE2  : out std_logic_vector(7 downto 1);
        LED_BATTING_OR_INING    : out std_logic_vector(7 downto 1)
    );
end BASEBALL_GAME;

architecture RTL of BASEBALL_GAME is
    
component DIVIDER
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;    
        DIV_CLK_2HZ : out std_logic;
        DIV_CLK_8Hz : out std_logic;
        DIV_CLK_16Hz: out std_logic;        
        DIV_CLK_32HZ: out std_logic
    );
end component;

component CHATTERING_CUT
    port(
        SW   : in  std_logic;
        CLK  : in  std_logic;
        RESET: in  std_logic;
        COUT : out std_logic
    );
end component;

component TOGLE
    port(
        TIN     : in  std_logic;
        RESET   : in  std_logic;
        TOUT    : out std_logic
    );
end component;

component BATTING_ROULLET
    port(
        CLK      : in  std_logic;
        RESET    : in  std_logic;
        STARTSTOP: in  std_logic;
        MODE     : in  std_logic;
        BATTING  : out std_logic_vector(2 downto 0);
        ASSIST   : out std_logic
    );
end component;

component BASE
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        SELECTOR: in  std_logic;
        CHANGE  : in  std_logic;
        BATTING : in  std_logic_vector(2 downto 0);
        RUNNER  : out std_logic_vector(2 downto 0);
        SCORE1  : out std_logic_vector(3 downto 0);
        SCORE2  : out std_logic_vector(3 downto 0);
        TEAM1   : out std_logic;
        TEAM2   : out std_logic;
        BLINK   : out std_logic
    );
end component;

component BLINK 
    port(
        CLK   : in  std_logic;
        ENABLE: in  std_logic;
        BLINK : out  std_logic
    );
end component;

component OUT_COUNTER
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        BATTING : in  std_logic_vector(2 downto 0);
        OUT_LED : out std_logic_vector(1 downto 0);
        CHANGE  : out std_logic
    );
end component;

component INING_COUNTER
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        COUNT   : out std_logic_vector(3 downto 0)
    );
end component;

component LUCKY7
    port(
        RESET       : in  std_logic;
        INING_COUNT : in std_logic_vector(3 downto 0);
        LED_ASSIST  : out std_logic
    );
end component;

component BATTING_DECODER
    port(
        RESET       : in  std_logic;
        COUNTER     : in  std_logic_vector(2 downto 0);
        LED         : out std_logic_vector(7 downto 1)
    );
end component;

component SCORE_DECODER
    port(
        DIV_CLK : in  std_logic;
        ENABLE  : in  std_logic;
        RESET   : in  std_logic;
        COUNTER : in  std_logic_vector(3 downto 0);
        LED     : out std_logic_vector(7 downto 1)
    );
end component;

component INING_DECODER
    port(
        RESET       : in  std_logic;
        COUNTER     : in  std_logic_vector(3 downto 0);
        LED         : out std_logic_vector(7 downto 1)
    );
end component;

signal CLK2HZ           : std_logic;
signal CLK8HZ           : std_logic;
signal CLK16HZ          : std_logic;
signal CLK32HZ          : std_logic;
signal STARTSTOP_CUT    : std_logic;
signal MODE_CUT         : std_logic;
signal STARTSTOP_TMP    : std_logic;
signal MODE_TMP         : std_logic;
signal BATTING_TMP      : std_logic_vector(2 downto 0);
signal SCORE1_TMP       : std_logic_vector(3 downto 0);
signal SCORE2_TMP       : std_logic_vector(3 downto 0);
signal CHANGE_TMP       : std_logic;
signal TOGLE_TEAM_TMP   : std_logic;
signal RESET_OR_CHANGE  : std_logic;
signal SELECT1_TMP      : std_logic;
signal SELECT2_TMP      : std_logic;
signal INING_COUNT_TMP  : std_logic_vector(3 downto 0);
signal INING_LED_OUT    : std_logic_vector(7 downto 1);
signal BATTING_LED_OUT  : std_logic_vector(7 downto 1);
signal BATTING_ASSIST   : std_logic;
signal LUCKY7_ASSIST    : std_logic;
signal BLINK_CLK        : std_logic;
signal BLINK_ENABLE     : std_logic;
signal BLINK_TMP        : std_logic;

begin
    
    RESET_OR_CHANGE <= RESET and CHANGE_TMP;
    SELECT1_TMP <= not TOGLE_TEAM_TMP;
    SELECT2_TMP <= TOGLE_TEAM_TMP;
    BLINK_ENABLE <= BLINK_TMP and not STARTSTOP_TMP;
    LED_ASSIST <= not (BATTING_ASSIST and LUCKY7_ASSIST);

    process(INING_SW,INING_LED_OUT,BATTING_LED_OUT)
    begin
        if (INING_SW = '0') then
            LED_BATTING_OR_INING <= INING_LED_OUT;
        else
            LED_BATTING_OR_INING <= BATTING_LED_OUT;
        end if;
    end process;
        
    process(RESET,MODE_TMP)
    begin
        if (RESET = '0') then
            LED_MODE <= '1';
        elsif (MODE_TMP = '1') then
            LED_MODE <= '0';
        else
            LED_MODE <= '1';
        end if;
    end process;
    
    CLK_DIVIDER :DIVIDER            port map (CLK,RESET,open,CLK8HZ,open,CLK32HZ);
    STARTSTOP_CT:CHATTERING_CUT     port map (STARTSTOP_SW,CLK,RESET,STARTSTOP_CUT);
    MODE_CT     :CHATTERING_CUT     port map (MODE_SW,CLK,RESET,MODE_CUT);  
    STARTSTOP_T :TOGLE              port map (STARTSTOP_CUT,RESET,STARTSTOP_TMP);
    MODE_T      :TOGLE              port map (MODE_CUT,RESET,MODE_TMP); 
    INING_T     :TOGLE              port map (CHANGE_TMP,RESET,TOGLE_TEAM_TMP);
    ROULLET_UNIT:BATTING_ROULLET    port map (CLK32HZ,RESET_OR_CHANGE,STARTSTOP_TMP,MODE_TMP,BATTING_TMP,BATTING_ASSIST);
    BASE_UNIT   :BASE               port map (STARTSTOP_TMP,RESET,TOGLE_TEAM_TMP,CHANGE_TMP,BATTING_TMP,LED_BASE,SCORE1_TMP,SCORE2_TMP,LED_TEAM1,LED_TEAM2,BLINK_TMP);
    BLINK_UNIT  :BLINK              port map (CLK8Hz,BLINK_ENABLE,BLINK_CLK);
    LUCKY7_UNIT :LUCKY7             port map (RESET,INING_COUNT_TMP,LUCKY7_ASSIST);
    COUNTER1    :OUT_COUNTER        port map (STARTSTOP_TMP,RESET_OR_CHANGE,BATTING_TMP,LED_OUT,CHANGE_TMP);
    COUNTER2    :INING_COUNTER      port map (TOGLE_TEAM_TMP,RESET,INING_COUNT_TMP);
    DECORDER1   :BATTING_DECODER    port map (RESET,BATTING_TMP,BATTING_LED_OUT); 
    DECORDER2   :SCORE_DECODER      port map (BLINK_CLK,SELECT1_TMP,RESET,SCORE1_TMP,LED_SCORE1);
    DECORDER3   :SCORE_DECODER      port map (BLINK_CLK,SELECT2_TMP,RESET,SCORE2_TMP,LED_SCORE2);
    DECORDER4   :INING_DECODER      port map (RESET,INING_COUNT_TMP,INING_LED_OUT);
end RTL;

野球ゲームをつくる ~ 11.ラッキー7の攻撃

2015年06月10日(水)21時22分

ラッキー7の攻撃の時には、ホームランのタイミングでアシスト用のLEDが点滅するようにしてみます。*1

lucky7.vhd

-- Lucky7
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity LUCKY7 is
    port(
        RESET       : in  std_logic;
        INING_COUNT : in std_logic_vector(3 downto 0);
        LED_ASSIST  : out std_logic
    );
end LUCKY7;

architecture RTL of LUCKY7 is

begin

    process(RESET,INING_COUNT)
    begin
        if (RESET = '0') then
            LED_ASSIST <= '0';
        elsif (INING_COUNT = "0111") then
            LED_ASSIST <= '1';
        else
            LED_ASSIST <= '0';
        end if;
    end process;
    
end RTL;

*1:ズルと言えばそれまでですが、ルーレットは早いので、目押しはまず無理です。

野球ゲームをつくる ~ 10.進塁ベース・得点追加の作成

2015年06月03日(水)21時15分

ヒット、フォアボール、ホームランによる塁の状態の変化と得点の追加を作成します。

この野球ゲームの中で、重要なパーツの1つです。

項目が多いので、入力信号・出力信号と分けて考察します。

まず、入力信号です。

1.打者の結果:BATTING
打者の結果によって、塁の状態と得点は変化します。
例えば、ランナー2塁で1塁打が出れば、ランナー1、3塁となり、
2塁打がでれば、ランナー2塁となり1点追加になります。
ということで、状態遷移(ステートマシン)を使用します。
全ての塁の状態と打者の結果の組合せがあるので、組合せのもれがないようにしないといけません。

アウトカウントは 野球ゲームをつくる ~ 6.アウトカウントとチェンジ
でカウントしています。

2.イニングの表裏:SELECTOR
先攻・後攻どちらの攻撃なのか、得点時に必要となります。
得点が相手チームに追加されては困りますよね。

3.チェンジ:CHANGE
チェンジになれば、ランナーはいなくなり、イニングが進みます。
リセットととは違います。

次に出力信号です。

1.塁の状態:RUNNER
2.先攻・後攻の各得点:SCORE1 SCORE2
の2つで充分ですが、

7SegLEDの小数点を
3.どちらの攻撃:TEAM1 TEAM2
かの表示に使用します。

また、得点が入った時にわかりやすいように
4.得点時に点滅用信号:BLINK
を出力します。

野球ゲームをつくる ~ 9.得点表示の点滅 が点滅用モジュールです。

base.vhd

-- BASE
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity BASE is
    port(
        CLK     : in  std_logic;
        RESET   : in  std_logic;
        SELECTOR: in  std_logic;
        CHANGE  : in  std_logic;
        BATTING : in  std_logic_vector(2 downto 0);
        RUNNER  : out std_logic_vector(2 downto 0);
        SCORE1  : out std_logic_vector(3 downto 0);
        SCORE2  : out std_logic_vector(3 downto 0);
        TEAM1   : out std_logic;
        TEAM2   : out std_logic;
        BLINK   : out std_logic
    );
end BASE;

architecture RTL of BASE is
type STATE_TYPE is (S0,S1,S2,S3,S12,S13,S23,S123);
signal STATE    : STATE_TYPE;
signal SCORE1_TMP   : std_logic_vector(3 downto 0);
signal SCORE2_TMP   : std_logic_vector(3 downto 0);
signal RUNNER_TMP   : std_logic_vector(2 downto 0);

begin
    process (CLK,RESET,CHANGE)
    begin
        if (RESET = '0') then
            STATE <= S0;
            SCORE1_TMP <= "0000";
            SCORE2_TMP <= "0000";
        elsif (CHANGE = '0') then    --- 0:3OUTChange
            STATE <= S0;
        elsif (CLK'event and CLK = '0') then
            case (STATE) is
                when S0 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S1;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S2;
                            BLINK <= '0';
                        when "011" =>
                            STATE <= S3;
                            BLINK <= '0';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S1;
                            BLINK <= '0';
                        when others =>
                            STATE <= S0;
                            BLINK <= '0';
                    end case;
                when S1 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S12;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S23;
                            BLINK <= '0';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S12;
                            BLINK <= '0';
                        when others =>
                            STATE <= S1;
                            BLINK <= '0';
                    end case;
                when S2 =>
                    case (BATTING) is
                        when "001" => 
                            STATE <= S13;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S2;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S12;
                            BLINK <= '0';
                        when others =>
                            STATE <= S2;
                            BLINK <= '0';
                    end case;
                when S3 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S1;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S2;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S13;
                            BLINK <= '0';
                        when others =>
                            STATE <= S3;
                            BLINK <= '0';
                    end case;
                when S12 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when "010" =>
                            STATE <= S23;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when others =>
                            STATE <= S12;
                            BLINK <= '0';
                    end case;
                when S13 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S12;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S23;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when others =>
                            STATE <= S13;
                            BLINK <= '0';
                    end case;
                when S23 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S13;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S2;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            BLINK <= '0';
                        when others =>
                            STATE <= S23;
                            BLINK <= '0';
                    end case;
                when S123 =>
                    case (BATTING) is
                        when "001" =>
                            STATE <= S123;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when "010" =>
                            STATE <= S23;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 2;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 2;
                            end if;
                            BLINK <= '1';
                        when "011" =>
                            STATE <= S3;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 3;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 3;
                            end if;
                            BLINK <= '1';
                        when "100" =>
                            STATE <= S0;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 4;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 4;
                            end if;
                            BLINK <= '1';
                        when "101" =>
                            STATE <= S123;
                            if (SELECTOR = '0') then
                                SCORE1_TMP <= SCORE1_TMP + 1;
                            else
                                SCORE2_TMP <= SCORE2_TMP + 1;
                            end if;
                            BLINK <= '1';
                        when others =>
                            STATE <= S123;
                            BLINK <= '0';
                    end case;
                when others =>
                    STATE <= S0;
                    BLINK <= '0';
            end case;
        else
        null;
        end if;
    end process;
        
    SCORE1 <= SCORE1_TMP;
    SCORE2 <= SCORE2_TMP;
        
    process(STATE)
    begin
        case (STATE) is
            when S0   => RUNNER_TMP <= "000";
            when S1   => RUNNER_TMP <= "001";
            when S2   => RUNNER_TMP <= "010";
            when S3   => RUNNER_TMP <= "100";
            when S12  => RUNNER_TMP <= "011";
            when S13  => RUNNER_TMP <= "101";
            when S23  => RUNNER_TMP <= "110";
            when S123 => RUNNER_TMP <= "111";
            when others => RUNNER_TMP <= "000";
        end case;
    end process;
    
    RUNNER <= not RUNNER_TMP

    process(RESET,SELECTOR)
    begin
        if (RESET = '0') then
            TEAM1 <= '1';
            TEAM2 <= '1';
        elsif (SELECTOR = '0') then
            TEAM1 <= '0';
            TEAM2 <= '1';
        else
            TEAM1 <= '1';
            TEAM2 <= '0';
        end if;
    end process;
    
    end RTL;

補足説明ですが、

type STATE_TYPE is (S0,S1,S2,S3,S12,S13,S23,S123);

が塁の状態で、
S0:ランナーなし
S1:ランナー1塁
S2:ランナー2塁
・・・・・・
S123:ランナー満塁
です。
省略したものは何になるか想像できますよね。

で、出力信号は下記にしています。
負論理なので、0:点灯 1:消灯です。*1
最上位ビットから3塁、2塁、1塁です。

    process(STATE)
    begin
        case (STATE) is
            when S0   => RUNNER_TMP <= "000";
            when S1   => RUNNER_TMP <= "001";
            when S2   => RUNNER_TMP <= "010";
            when S3   => RUNNER_TMP <= "100";
            when S12  => RUNNER_TMP <= "011";
            when S13  => RUNNER_TMP <= "101";
            when S23  => RUNNER_TMP <= "110";
            when S123 => RUNNER_TMP <= "111";
            when others => RUNNER_TMP <= "000";
        end case;
    end process;
    
    RUNNER <= not RUNNER_TMP

また、

        elsif (CHANGE = '0') then    --- 0:3OUTChange
            STATE <= S0;

チェンジの出力信号は、リセット同様負論理にしています。
野球ゲームをつくる ~ 6.アウトカウントとチェンジ と関連しています。

*1:しつこいですが、電子回路では重要です。

野球ゲームをつくる ~ 9.得点表示の点滅

2015年06月03日(水)20時35分

得点が入った時に得点表示を点滅させてみます。
ただ、ずっと点滅し続けるとうっとうしいので、
5回点滅させることにします。*1

また、点滅させるかどうかの入力信号が必要なので、
ENABLEを入れています。

blink.vhd

-- Blink
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity BLINK is
    port(
        CLK     : in  std_logic;
        ENABLE  : in  std_logic;
        BLINK       : out  std_logic
    );
end BLINK;

architecture RTL of BLINK is

signal BLINK_CNT    : std_logic_vector(2 downto 0);
signal BLINK_TMP    : std_logic;

begin

    process(CLK,ENABLE)
    begin
        if (ENABLE = '1') then
            if (CLK'event and CLK = '0') then   
                if (BLINK_CNT = "101") then
                    BLINK_TMP <= '1';
                else
                    BLINK_CNT <= BLINK_CNT + 1;
                    BLINK_TMP <= not BLINK_TMP;
                end if;
            end if;
        else
            BLINK_TMP <= '1';
            BLINK_CNT <= (others => '0');
        end if;
    end process;
    
    BLINK <= BLINK_TMP;
    
end RTL;

*1:クロックが早いとあっという間かもしれません。

野球ゲームをつくる ~ 8.イニングの表示

2015年06月03日(水)20時10分

イニングは通常9回で終了ですが、7SegLEDは16進を表現できるので、
15(F)まで表示します。

ining_decoder.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity INING_DECODER is
    port(
        RESET   : in  std_logic;
        COUNTER : in  std_logic_vector(3 downto 0);
        LED     : out std_logic_vector(7 downto 1)
    );
end INING_DECODER;

architecture RTL of INING_DECODER is
begin

    process (RESET,COUNTER)
    begin
        if (RESET = '0') then
            LED <= "1111111";
        else
            case COUNTER is
                when "0000" => LED <= "0000001"; -- 0
                when "0001" => LED <= "1001111"; -- 1
                when "0010" => LED <= "0010010"; -- 2
                when "0011" => LED <= "0000110"; -- 3
                when "0100" => LED <= "1001100"; -- 4
                when "0101" => LED <= "0100100"; -- 5
                when "0110" => LED <= "0100000"; -- 6
                when "0111" => LED <= "0001101"; -- 7
                when "1000" => LED <= "0000000"; -- 8
                when "1001" => LED <= "0000100"; -- 9
                when "1010" => LED <= "0001000"; -- A
                when "1011" => LED <= "1100000"; -- b
                when "1100" => LED <= "0110001"; -- C
                when "1101" => LED <= "1000010"; -- d
                when "1110" => LED <= "0110000"; -- E
                when "1111" => LED <= "0111000"; -- F
                when others => LED <= "1111110"; -- '-'
            end case;
        end if;
    end process;

end RTL;

野球ゲームをつくる ~ 7.イニングカウンターの作成

2015年06月03日(水)19時56分

イニングカウンターは単純に10進数のカウンターです。

ining_counter.vhd

-- INING Counter
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
--use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity INING_COUNTER is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        COUNT       : out std_logic_vector(3 downto 0)
    );
end INING_COUNTER;

architecture RTL of INING_COUNTER is
signal COUNT_TMP    : std_logic_vector(3 downto 0);

begin

    process (CLK,RESET)
    begin
        if (RESET = '0') then
            COUNT_TMP <= "0001";
        elsif (CLK'event and CLK = '0') then
            COUNT_TMP <= COUNT_TMP + 1;
        end if;
    end process;

    COUNT <= COUNT_TMP;
        
end RTL;

野球ゲームをつくる ~ 6.アウトカウントとチェンジ

2015年06月02日(火)22時48分

打撃結果がアウトの場合、
アウトカウントはひとつづつ増え、
スリーアウトでチェンジします。

out_counter.vhd

-- OUT Counter
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity OUT_COUNTER is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        BATTING     : in  std_logic_vector(2 downto 0);
        OUT_LED     : out std_logic_vector(1 downto 0);
        CHANGE      : out std_logic
    );
end OUT_COUNTER;

architecture RTL of OUT_COUNTER is
signal OUT_COUNT_TMP    : std_logic_vector(1 downto 0);
signal OUT_LED_TMP      : std_logic_vector(1 downto 0);

begin
    process (CLK,RESET)
    begin
        if (RESET = '0') then
            OUT_COUNT_TMP <= "00";
        elsif (CLK'event and CLK = '0') then
            if (BATTING = "000") then
                OUT_COUNT_TMP <= OUT_COUNT_TMP + 1;
            end if;
        end if;
    end process;
    
    process(OUT_COUNT_TMP)
    begin
        case (OUT_COUNT_TMP) is
            when "00" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '1';
            when "01" =>
                OUT_LED_TMP <= "01";
                CHANGE <= '1';
            when "10" =>
                OUT_LED_TMP <= "11";
                CHANGE <= '1';
            when "11" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '0';
            when others =>
                OUT_LED_TMP <= null;
                CHANGE <= null;
        end case;
    end process;

    OUT_LED <= OUT_LED_TMP;

end RTL;

ここで、

            when "11" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '0';

アウトカウントが3の時のCHANGE信号は負論理にしています。
通常、信号を送出する場合、1を出力しますが、CHANGEはリセットと同じような効果を与えるので、RESETと論理を同じにして、0を出力しています。

また、

            when "11" =>
                OUT_LED_TMP <= "00";
                CHANGE <= '0';

の OUT_LED_TMP <= "00"; を忘れていました。*1
3アウトチェンジでアウトカウントはリセットされるので、動作上は影響ないのですが、全ての場合を網羅しないと、ラッチ回路が作成されてしまいます。*2

*1:2015.06.10 修正
*2:実は、Warningで気づきました。

野球ゲームをつくる ~ 5.バッティングルーレットの作成

2013年07月06日(土)20時38分

バッティングルーレットを作ります。

数字が0から9に回るのなら簡単ですが、
野球ゲーム用のルーレットなので、
単純にアウト、ヒット、ホームランの出目を循環させるわけにはいきません。
なぜなら、ヒットの確率が高くなり、ゲーム性が失われてしまいます。

そこで、下図*1のようなルーレットをつくります。

ファイル 100-1.jpg

このようにすれば、ヒットの確率を調整することができます。

では、これをどのようにプログラムするのかというと、
クロックのタイミング*2で、アウト→フォアボール→アウト→アウト→アウト...
と状態を変化させ、ストップがかかったタイミングで出目を確定させればよいのです。

この状態を変化させるには、ステートマシンを使用します。

今回、ノーマルモード*3とチャレンジモード*4用にステートマシンを2つ作って、ヒットの確率を変えてみます。

また、目押し用*5にホームランのタイミングで信号(ASSIST<= '1')が出るようにします。

batting_roullet.vhd

-- Batting Roullet
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity BATTING_ROULLET is
    port(
        CLK         : in  std_logic;
        RESET       : in  std_logic;
        STARTSTOP   : in  std_logic;
        MODE        : in  std_logic;
        BATTING     : out std_logic_vector(2 downto 0);
        ASSIST      : out std_logic
    );
end BATTING_ROULLET;

architecture RTL of BATTING_ROULLET is

type STATE_TYPE is (
    ONEBASE0,ONEBASE1,ONEBASE2,ONEBASE3,ONEBASE4,
    TWOBASE0,TWOBASE1,
    THREEBASE0,THREEBASE1,
    HOMERUN0,HOMERUN1,HOMERUN2,
    FOUR0,FOUR1,FOUR2,FOUR3,FOUR4,
    OUT0,OUT1,OUT2,OUT3,OUT4,OUT5,OUT6,OUT7,OUT8,OUT9,
    OUT10,OUT11,OUT12,OUT13,OUT14,OUT15,OUT16,OUT17,OUT18,OUT19,
    OUT20,OUT21,OUT22,OUT23,
    CHANGE
    );

signal STATE    : STATE_TYPE;

begin
    
    process(CLK,RESET)
    begin
        if (RESET = '0') then
            STATE <= CHANGE;
        elsif(CLK'event and CLK = '0') then
            if (STARTSTOP = '1') then
                if (MODE = '0') then
                    case(STATE) is        -- Normal MODE
                        when CHANGE      => STATE <= OUT0;
                        when OUT0        => STATE <= FOUR0;
                        when FOUR0       => STATE <= OUT1;
                        when OUT1        => STATE <= TWOBASE0;
                        when TWOBASE0    => STATE <= OUT2;
                        when OUT2        => STATE <= OUT3;
                        when OUT3        => STATE <= OUT4;
                        when OUT4        => STATE <= THREEBASE0;
                        when THREEBASE0  => STATE <= OUT5;
                        when OUT5        => STATE <= ONEBASE0;
                        when ONEBASE0    => STATE <= OUT6;
                        when OUT6        => STATE <= FOUR1;
                        when FOUR1       => STATE <= OUT7;
                        when OUT7        => STATE <= ONEBASE1;
                        when ONEBASE1    => STATE <= OUT8;
                        when OUT8        => STATE <= FOUR2;
                        when FOUR2       => STATE <= OUT9;
                        when OUT9        => STATE <= ONEBASE2;
                        when ONEBASE2    => STATE <= OUT10;
                        when OUT10       => STATE <= TWOBASE1;
                        when TWOBASE1    => STATE <= OUT11;
                        when OUT11       => STATE <= OUT12;
                        when OUT12       => STATE <= OUT13;
                        when OUT13       => STATE <= HOMERUN0;
                        when HOMERUN0    => STATE <= OUT14;
                        when OUT14       => STATE <= FOUR3;
                        when FOUR3       => STATE <= OUT15;
                        when OUT15       => STATE <= ONEBASE3;
                        when ONEBASE3    => STATE <= OUT16;
                        when OUT16       => STATE <= FOUR4;
                        when FOUR4       => STATE <= OUT17;
                        when OUT17       => STATE <= ONEBASE4;
                        when ONEBASE4    => STATE <= OUT0;
                        when others      => STATE <= CHANGE;
                    end case;
                else
                    case(STATE) is        -- Challenge MODE
                        when CHANGE      => STATE <= OUT0;
                        when OUT0        => STATE <= OUT1;
                        when OUT1        => STATE <= OUT2;
                        when OUT2        => STATE <= HOMERUN0;
                        when HOMERUN0    => STATE <= OUT3;
                        when OUT3        => STATE <= OUT4;
                        when OUT4        => STATE <= ONEBASE0;
                        when ONEBASE0    => STATE <= OUT5;
                        when OUT5        => STATE <= OUT6;
                        when OUT6        => STATE <= TWOBASE0;
                        when TWOBASE0    => STATE <= OUT7;
                        when OUT7        => STATE <= OUT8;
                        when OUT8        => STATE <= OUT9;
                        when OUT9        => STATE <= THREEBASE0;
                        when THREEBASE0  => STATE <= OUT10;
                        when OUT10       => STATE <= OUT11;
                        when OUT11       => STATE <= OUT12;
                        when OUT12       => STATE <= OUT13;
                        when OUT13       => STATE <= OUT14;
                        when OUT14       => STATE <= HOMERUN1;
                        when HOMERUN1    => STATE <= OUT15;
                        when OUT15       => STATE <= OUT16;
                        when OUT16       => STATE <= FOUR0;
                        when FOUR0       => STATE <= OUT17;
                        when OUT17       => STATE <= OUT18;
                        when OUT18       => STATE <= HOMERUN2;
                        when HOMERUN2    => STATE <= OUT19;
                        when OUT19       => STATE <= OUT20;
                        when OUT20       => STATE <= OUT21;                                                when OUT21       => STATE <= THREEBASE1;
                        when THREEBASE1  => STATE <= OUT22;                                                when OUT22       => STATE <= OUT23;                                                when OUT23       => STATE <= OUT0;
                        when others      => STATE <= CHANGE;
                    end case;
                end if;
            end if;
        end if;
    end process;
    
    process(STATE)
    begin
        case(STATE) is
            when CHANGE        =>
                BATTING <= "110";
                ASSIST <= '0';
            when OUT0        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT1        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT2        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT3        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT4        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT5        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT6        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT7        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT8        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT9        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT10        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT11        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT12        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT13        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT14        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT15        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT16         =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT17        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT18        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT19        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT20        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT21        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT22        =>
                BATTING <= "000";
                ASSIST <= '0';
            when OUT23        =>
                BATTING <= "000";
                ASSIST <= '0';
            when ONEBASE0    =>
                BATTING <= "001";
                ASSIST <= '0';
            when ONEBASE1    =>
                BATTING <= "001";
                ASSIST <= '0';
            when ONEBASE2    =>
                BATTING <= "001";
                ASSIST <= '0';
            when ONEBASE3    =>
                BATTING <= "001";
                ASSIST <= '0';
            when ONEBASE4    =>
                BATTING <= "001";
                ASSIST <= '0';
            when TWOBASE0    =>
                BATTING <= "010";
                ASSIST <= '0';
            when TWOBASE1    =>
                BATTING <= "010";
                ASSIST <= '0';
            when THREEBASE0 =>
                BATTING <= "011";
                ASSIST <= '0';
            when THREEBASE1    =>
                BATTING <= "011";
                ASSIST <= '0';
            when HOMERUN0    =>
                BATTING <= "100";
                ASSIST <= '1';
            when HOMERUN1    =>
                BATTING <= "100";
                ASSIST <= '1';
            when HOMERUN2    =>
                BATTING <= "100";
                ASSIST <= '1';
            when FOUR0        =>
                BATTING <= "101";
                ASSIST <= '0';
            when FOUR1        => 
                BATTING <= "101";
                ASSIST <= '0';
            when FOUR2        =>
                BATTING <= "101";
                ASSIST <= '0';
            when FOUR3        =>
                BATTING <= "101";
                ASSIST <= '0';
            when FOUR4        =>
                BATTING <= "101";
                ASSIST <= '0';
            when others        =>
                BATTING <= "000";
                ASSIST <= '0';
        end case;
    end process;
    
end RTL;

*1:何で作図したらよいかわからなかったので、大げさにもCADで作図しました。
*2:ということは、クロックの速度を変えれば、ルーレットが回る速度が変わります。
*3:ヒットの確率は高いが、シングルヒットが多い
*4:ヒットの確率は低いが、出れば長打になる
*5:ズル用とも

ページ移動