Compare commits
8 Commits
157c0cb9e6
...
master
Author | SHA1 | Date | |
---|---|---|---|
26ffa93592 | |||
6d15a75902 | |||
e9abc3d690 | |||
20a97fec11 | |||
cd62b41e0b | |||
0c70783f64 | |||
929a95504f | |||
66c69f4e0f |
@@ -5,10 +5,11 @@
|
|||||||
* нельзя отключить сразу все зоны цинкования или травления
|
* нельзя отключить сразу все зоны цинкования или травления
|
||||||
* коррекцию нужно описать так, чтобы не произошло ничего страшного
|
* коррекцию нужно описать так, чтобы не произошло ничего страшного
|
||||||
* время скапывания нельзя поставить больше 200 секунд (в текущей реализации можно до 8К секунд)
|
* время скапывания нельзя поставить больше 200 секунд (в текущей реализации можно до 8К секунд)
|
||||||
* время каждого процесса не больше чем 32К секунд (можно уменьшить до 8К для упрощения логики)
|
* время каждого процесса не больше чем 8К секунд
|
||||||
* устанавливать режим работы роботов (один робот/второй робот/два робота) можно только в ручном режиме
|
* устанавливать режим работы роботов (первый робот/второй робот/два робота) можно только в ручном режиме
|
||||||
|
|
||||||
## Известные баги
|
## Известные баги
|
||||||
|
|
||||||
|
* ночные барабаны в конце складываются в промывки через зону обмена, таким образом можно загрузить на линию все 10 ночных барабанов
|
||||||
* не работают регистры добавления/удаления барабанов с панели
|
* не работают регистры добавления/удаления барабанов с панели
|
||||||
|
|
||||||
|
31
emulator.cpp
31
emulator.cpp
@@ -10,7 +10,7 @@
|
|||||||
#include "robot.h"
|
#include "robot.h"
|
||||||
|
|
||||||
|
|
||||||
// закомментить когда надо будет отключить
|
// закомментируй когда надо будет отключить
|
||||||
//#define DEBUG_CORRECTION
|
//#define DEBUG_CORRECTION
|
||||||
|
|
||||||
|
|
||||||
@@ -56,6 +56,7 @@ char scheduler_en = 1;
|
|||||||
char scheduler_start_signal = 1;
|
char scheduler_start_signal = 1;
|
||||||
char auto_mode_pause = 0;
|
char auto_mode_pause = 0;
|
||||||
char hla_night_mode = 0;
|
char hla_night_mode = 0;
|
||||||
|
char hla_zinc_again = 0;
|
||||||
|
|
||||||
short hla_exchange_zone = ZONE_GALVANIZING_2;
|
short hla_exchange_zone = ZONE_GALVANIZING_2;
|
||||||
|
|
||||||
@@ -206,7 +207,7 @@ static void collectBarrelsStatistic() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (barrels[i].flags.robot == 0 && barrels[i].software_timer < 0) {
|
if (barrels[i].flags.robot == 0 && barrels[i].software_timer < 0) {
|
||||||
// время отрицательное, вычитаем его чтобы убрать минус
|
// время отрицательное, вычитаем его, чтобы убрать минус
|
||||||
barrels_time -= barrels[i].software_timer;
|
barrels_time -= barrels[i].software_timer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,15 +229,15 @@ static void showAll() {
|
|||||||
image_init();
|
image_init();
|
||||||
image_draw_borders();
|
image_draw_borders();
|
||||||
char tmp[64];
|
char tmp[64];
|
||||||
sprintf(tmp, "Lock2=%2d Lock1=%2d FNZ=%d", robot2_lock_zone, robot1_lock_zone, get_first_night_zone());
|
sprintf(tmp, "Lock2=%2d Lock1=%2d FNZ=%2d", robot2_lock_zone, robot1_lock_zone, get_first_night_zone());
|
||||||
image_insert_sprite(0, 2, tmp);
|
image_insert_sprite(0, 2, tmp);
|
||||||
|
|
||||||
collectBarrelsStatistic();
|
collectBarrelsStatistic();
|
||||||
sprintf(tmp, "barrels=%2d time=%d max_time=%d", barrels_count, barrels_time, max_time);
|
sprintf(tmp, "barrels=%02d time=%d max_time=%d", barrels_count, barrels_time, max_time);
|
||||||
image_insert_sprite(0, 30, tmp);
|
image_insert_sprite(0, 30, tmp);
|
||||||
|
|
||||||
sprintf(tmp, "MODE: night=%d pause=%d", hla_night_mode, auto_mode_pause);
|
sprintf(tmp, "MODE: night=%d pause=%d zinc_again=%d", hla_night_mode, auto_mode_pause, hla_zinc_again);
|
||||||
image_insert_sprite(0, 70, tmp);
|
image_insert_sprite(0, 66, tmp);
|
||||||
|
|
||||||
// рисование бочек
|
// рисование бочек
|
||||||
for (int i = 0; i < BARRELS_COUNT; i++) {
|
for (int i = 0; i < BARRELS_COUNT; i++) {
|
||||||
@@ -339,12 +340,14 @@ int main() {
|
|||||||
// подсчитаем статистику
|
// подсчитаем статистику
|
||||||
collectBarrelsStatistic();
|
collectBarrelsStatistic();
|
||||||
|
|
||||||
// грузим не больше 5 барабанов
|
// грузим не больше 8 барабанов
|
||||||
// if (barrels_count < 5) {
|
// if (barrels_count < 8) {
|
||||||
// button_load = 1;
|
// button_load = 1;
|
||||||
// }
|
// }
|
||||||
|
// button_unload = 1;
|
||||||
|
// button_unload_end = 1;
|
||||||
|
|
||||||
// ======= БЛОК КОДА bittons_logic =======
|
// ======= БЛОК КОДА buttons_logic =======
|
||||||
|
|
||||||
// авто сброс кнопок на выгрузке, если там нет барабана
|
// авто сброс кнопок на выгрузке, если там нет барабана
|
||||||
if (!zone_is_busy(ZONE_UNLOAD)) {
|
if (!zone_is_busy(ZONE_UNLOAD)) {
|
||||||
@@ -428,10 +431,6 @@ int main() {
|
|||||||
if (robot2_code.PC >= 0)
|
if (robot2_code.PC >= 0)
|
||||||
debug_print_robot_code(&robot2_code, 2, sock_fd);
|
debug_print_robot_code(&robot2_code, 2, sock_fd);
|
||||||
|
|
||||||
#ifdef DEBUG_CORRECTION
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
send_str("cmd >> ");
|
send_str("cmd >> ");
|
||||||
std::string in;
|
std::string in;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -471,8 +470,12 @@ int main() {
|
|||||||
} else if (in == "p") {
|
} else if (in == "p") {
|
||||||
auto_mode_pause = !auto_mode_pause;
|
auto_mode_pause = !auto_mode_pause;
|
||||||
message = "Переключен режим паузы";
|
message = "Переключен режим паузы";
|
||||||
|
} else if (in == "z") {
|
||||||
|
hla_zinc_again = !hla_zinc_again;
|
||||||
|
message = "Переключен флаг повторного цинкования";
|
||||||
} else {
|
} else {
|
||||||
message = "Неизвестная команда. q - выход, u - выгрузка, 1 - загрузка 1, 2 - загрузка 2";
|
message = "Неизвестная команда. q - выход, u - выгрузка, 1 - загрузка 1, 2 - загрузка 2,\n"
|
||||||
|
" n - ночной режим, p - пауза, z - повторное цинкование";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
current_tic++;
|
current_tic++;
|
||||||
|
46
scheduler.c
46
scheduler.c
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
|
|
||||||
struct scheduler_task {
|
struct scheduler_task {
|
||||||
short start_zone; // стартовая зона
|
|
||||||
short dest_zone; // конечная зона
|
short dest_zone; // конечная зона
|
||||||
short priority; // приоритет, чем больше тем выше, по умолчанию 0
|
short priority; // приоритет, чем больше тем выше, по умолчанию 0
|
||||||
};
|
};
|
||||||
@@ -28,7 +27,7 @@ short scheduler_find_task(const struct scheduler_task* tasks, const short curr_p
|
|||||||
// ищем первый барабан слева, и ближайший справа
|
// ищем первый барабан слева, и ближайший справа
|
||||||
short left = -1, right = -1;
|
short left = -1, right = -1;
|
||||||
for (short i = 0; i < BARRELS_COUNT; i++) {
|
for (short i = 0; i < BARRELS_COUNT; i++) {
|
||||||
short target = tasks[i].start_zone; // фактическая зона откуда тащить барабан
|
short target = barrels[i].zone; // фактическая зона откуда тащить барабан
|
||||||
if (tasks[i].dest_zone < 0) {
|
if (tasks[i].dest_zone < 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -86,8 +85,6 @@ void schedule_one_robot(const short robot_id) {
|
|||||||
struct scheduler_task tasks[BARRELS_COUNT];
|
struct scheduler_task tasks[BARRELS_COUNT];
|
||||||
|
|
||||||
for (short i = 0; i < BARRELS_COUNT; i++) {
|
for (short i = 0; i < BARRELS_COUNT; i++) {
|
||||||
// для каждой задачи:
|
|
||||||
tasks[i].start_zone = barrels[i].zone;
|
|
||||||
// определяем можно ли ее выполнить и что вообще нужно выполнить
|
// определяем можно ли ее выполнить и что вообще нужно выполнить
|
||||||
tasks[i].dest_zone = can_move(barrels + i, robot_id);
|
tasks[i].dest_zone = can_move(barrels + i, robot_id);
|
||||||
if (tasks[i].dest_zone >= 0) {
|
if (tasks[i].dest_zone >= 0) {
|
||||||
@@ -108,11 +105,9 @@ void schedule_one_robot(const short robot_id) {
|
|||||||
|
|
||||||
if (target_task >= 0) {
|
if (target_task >= 0) {
|
||||||
if (robot_id == ROBOT_1) {
|
if (robot_id == ROBOT_1) {
|
||||||
create_operation(&robot1_code, target_task, tasks[target_task].start_zone, tasks[target_task].dest_zone,
|
create_operation(target_task, barrels[target_task].zone, tasks[target_task].dest_zone, robot_id);
|
||||||
current_zone, robot_id);
|
|
||||||
} else {
|
} else {
|
||||||
create_operation(&robot2_code, target_task, tasks[target_task].start_zone, tasks[target_task].dest_zone,
|
create_operation(target_task, barrels[target_task].zone, tasks[target_task].dest_zone, robot_id);
|
||||||
current_zone, robot_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -126,6 +121,11 @@ void scheduler_main()
|
|||||||
robot1_code.PC = -1;
|
robot1_code.PC = -1;
|
||||||
robot2_code.PC = -1;
|
robot2_code.PC = -1;
|
||||||
|
|
||||||
|
scheduler_start_signal = 0;
|
||||||
|
scheduler_stage = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!scheduler_en) {
|
||||||
for (short i = 0; i < BARRELS_COUNT; i++) {
|
for (short i = 0; i < BARRELS_COUNT; i++) {
|
||||||
// после рестарта планировщика надо всем барабаном убрать робота,
|
// после рестарта планировщика надо всем барабаном убрать робота,
|
||||||
// всех кто сверху удалить
|
// всех кто сверху удалить
|
||||||
@@ -135,8 +135,6 @@ void scheduler_main()
|
|||||||
barrels[i].flags.is_exist = 0;
|
barrels[i].flags.is_exist = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
scheduler_start_signal = 0;
|
|
||||||
scheduler_stage = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// программный таймер, применяется ко всем существующим барабанам во всех режимах
|
// программный таймер, применяется ко всем существующим барабанам во всех режимах
|
||||||
@@ -341,21 +339,29 @@ void scheduler_main()
|
|||||||
|
|
||||||
// сначала выдаем команды первому роботу
|
// сначала выдаем команды первому роботу
|
||||||
if (robot1_code.PC < 0) {
|
if (robot1_code.PC < 0) {
|
||||||
schedule_one_robot(ROBOT_1);
|
if (robot1.dx.current_zone < ZONE_PASSIVATION) {
|
||||||
|
robot2_lock_zone = -1;
|
||||||
|
robot1_lock_zone = ZONE_PASSIVATION;
|
||||||
|
robot1_code.barrel_id = -1;
|
||||||
|
robot1_code.code[0] = ROBOT_CMD_DOWN();
|
||||||
|
robot1_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_PASSIVATION);
|
||||||
|
robot1_code.code[2] = ROBOT_CMD_END();
|
||||||
|
robot1_code.PC = 0;
|
||||||
|
} else {
|
||||||
|
schedule_one_robot(ROBOT_1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// потом второму
|
// потом второму
|
||||||
if (robot2_code.PC < 0) {
|
if (robot2_code.PC < 0) {
|
||||||
if (robot2.dx.current_zone < ZONE_WASHING_1A) {
|
if (robot2.dx.current_zone < ZONE_WASHING_1A || robot2.dx.current_zone > ZONE_ETCHING_2) {
|
||||||
// то же самое что и во второй стадии, только без инкремента стадии
|
// то же самое что и во второй стадии, только без инкремента стадии
|
||||||
if (robot2_code.PC < 0) {
|
robot2_lock_zone = ZONE_ETCHING_2;
|
||||||
robot2_lock_zone = ZONE_ETCHING_2;
|
robot2_code.barrel_id = -1;
|
||||||
robot2_code.barrel_id = -1;
|
robot2_code.code[0] = ROBOT_CMD_DOWN();
|
||||||
robot2_code.code[0] = ROBOT_CMD_DOWN();
|
robot2_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_1A);
|
||||||
robot2_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_1A);
|
robot2_code.code[2] = ROBOT_CMD_END();
|
||||||
robot2_code.code[2] = ROBOT_CMD_END();
|
robot2_code.PC = 0;
|
||||||
robot2_code.PC = 0;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
schedule_one_robot(ROBOT_2);
|
schedule_one_robot(ROBOT_2);
|
||||||
}
|
}
|
||||||
|
83
utils.c
83
utils.c
@@ -24,7 +24,7 @@ const short NIGHT_ZONES[9] = {
|
|||||||
|
|
||||||
char zone_is_busy(short zone) {
|
char zone_is_busy(short zone) {
|
||||||
for (short i = 0; i < BARRELS_COUNT; i++) {
|
for (short i = 0; i < BARRELS_COUNT; i++) {
|
||||||
if (barrels[i].flags.is_exist && barrels[i].zone == zone) {
|
if (barrels[i].flags.is_exist && barrels[i].zone == zone && !barrels[i].flags.is_up) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,7 +33,17 @@ char zone_is_busy(short zone) {
|
|||||||
|
|
||||||
|
|
||||||
short get_first_night_zone() {
|
short get_first_night_zone() {
|
||||||
// TODO сделать корректное вычисление ночной зоны
|
short min_normal_barrel = -1;
|
||||||
|
for (short i = 0; i < BARRELS_COUNT; i++) {
|
||||||
|
// ищем все не ночные, не пустые, и которые внизу барабаны
|
||||||
|
if (barrels[i].flags.is_exist && !barrels[i].flags.is_empty && !barrels[i].flags.is_night && !barrels[i].flags.is_up) {
|
||||||
|
// нужен барабан, у которого нет
|
||||||
|
if (min_normal_barrel < 0 || barrels[i].zone < min_normal_barrel) {
|
||||||
|
min_normal_barrel = barrels[i].zone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// всего зон, куда можно сныкать барабаны (всего 9 мест: загрузка 1 и 8 промывок)
|
// всего зон, куда можно сныкать барабаны (всего 9 мест: загрузка 1 и 8 промывок)
|
||||||
for (short nz = 0; nz < 9; nz++) {
|
for (short nz = 0; nz < 9; nz++) {
|
||||||
char found = 0;
|
char found = 0;
|
||||||
@@ -47,7 +57,11 @@ short get_first_night_zone() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (found == 0) {
|
if (found == 0) {
|
||||||
return NIGHT_ZONES[nz];
|
if (min_normal_barrel < 0 || NIGHT_ZONES[nz] < min_normal_barrel) {
|
||||||
|
return NIGHT_ZONES[nz];
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,13 +81,15 @@ short _get_dest_zone(struct barrel *bar, char robot_id) {
|
|||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (robot_id == ROBOT_2) {
|
||||||
// робот 2 всегда кидает барабаны в загрузку 1, но только дальше зоны обмена он не имеет права брать
|
// робот 2 всегда кидает барабаны в загрузку 1, но только дальше зоны обмена он не имеет права брать
|
||||||
if (bar->zone <= hla_exchange_zone) {
|
if (bar->zone <= hla_exchange_zone) {
|
||||||
return ZONE_LOAD_1;
|
return ZONE_LOAD_1;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return ZONE_LOAD_1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,8 +106,17 @@ short _get_dest_zone(struct barrel *bar, char robot_id) {
|
|||||||
|
|
||||||
switch (bar->zone) {
|
switch (bar->zone) {
|
||||||
case ZONE_LOAD_2:
|
case ZONE_LOAD_2:
|
||||||
// загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание
|
// загрузка 2, только в нее можно грузить новые барабаны, по умолчанию следующая зона - обезжиривание
|
||||||
return ZONE_DEGREASING;
|
// при повторном цинковании это кислота
|
||||||
|
if (hla_zinc_again) {
|
||||||
|
if (etching_zone < 0) {
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
return (short)(ZONE_ETCHING_1 + etching_zone);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ZONE_DEGREASING;
|
||||||
|
}
|
||||||
|
|
||||||
case ZONE_DEGREASING:
|
case ZONE_DEGREASING:
|
||||||
// обезжиривание, нужна промывка 1А
|
// обезжиривание, нужна промывка 1А
|
||||||
@@ -177,14 +202,14 @@ short _get_dest_zone(struct barrel *bar, char robot_id) {
|
|||||||
if (button_unload) {
|
if (button_unload) {
|
||||||
if (hla_night_mode) {
|
if (hla_night_mode) {
|
||||||
short nz = get_first_night_zone();
|
short nz = get_first_night_zone();
|
||||||
if (one_robot_mode) {
|
if (nz < hla_exchange_zone) {
|
||||||
return nz;
|
if (one_robot_mode && nz >= 0) {
|
||||||
} else {
|
|
||||||
if (nz < hla_exchange_zone) {
|
|
||||||
return hla_exchange_zone;
|
|
||||||
} else {
|
|
||||||
return nz;
|
return nz;
|
||||||
|
} else {
|
||||||
|
return hla_exchange_zone;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
return nz;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (one_robot_mode) {
|
if (one_robot_mode) {
|
||||||
@@ -200,9 +225,7 @@ short _get_dest_zone(struct barrel *bar, char robot_id) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// вернет можно ли ехать и главное куда ехать, если можно (нельзя если вернулось значение < 0)
|
|
||||||
// robot_id - 1 или 2 для роботов или -1 без привязки к конкретному роботу
|
|
||||||
// -1 вернет что перемещать нельзя
|
|
||||||
short can_move(struct barrel *bar, char robot_id) {
|
short can_move(struct barrel *bar, char robot_id) {
|
||||||
if (robot_id != ROBOT_NONE && robot_id != ROBOT_1 && robot_id != ROBOT_2) {
|
if (robot_id != ROBOT_NONE && robot_id != ROBOT_1 && robot_id != ROBOT_2) {
|
||||||
return -3;
|
return -3;
|
||||||
@@ -240,9 +263,9 @@ short can_move(struct barrel *bar, char robot_id) {
|
|||||||
|
|
||||||
#ifndef EMULATOR
|
#ifndef EMULATOR
|
||||||
if (approximate_time > 1) {
|
if (approximate_time > 1) {
|
||||||
approximate_time = ((approximate_time - 1) * 3) + 6;
|
approximate_time = ((approximate_time - 1) * 3) + 4;
|
||||||
} else if (approximate_time == 1) {
|
} else if (approximate_time == 1) {
|
||||||
approximate_time = 8;
|
approximate_time = 5;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -261,7 +284,7 @@ short can_move(struct barrel *bar, char robot_id) {
|
|||||||
// учитывать границы только в режиме двух роботов и с привязкой к роботу
|
// учитывать границы только в режиме двух роботов и с привязкой к роботу
|
||||||
if (!one_robot_mode && dest_zone >= 0 && robot_id != ROBOT_NONE) {
|
if (!one_robot_mode && dest_zone >= 0 && robot_id != ROBOT_NONE) {
|
||||||
if (robot_id == 1) {
|
if (robot_id == 1) {
|
||||||
// если робот 1, то это старый, который ближе к концу линнии.
|
// если робот 1, то это старый, который ближе к концу линии.
|
||||||
// Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон
|
// Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон
|
||||||
short border = robot2.dx.current_zone;
|
short border = robot2.dx.current_zone;
|
||||||
if (border < robot2_lock_zone) {
|
if (border < robot2_lock_zone) {
|
||||||
@@ -277,7 +300,7 @@ short can_move(struct barrel *bar, char robot_id) {
|
|||||||
dest_zone = -6;
|
dest_zone = -6;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// если робот 2, то это новый, который ближе к началу линнии.
|
// если робот 2, то это новый, который ближе к началу линии.
|
||||||
// Ему нельзя ехать если хоть одна из зон >= max(r2_pos, r2_lock) - кол-во пограничных зон
|
// Ему нельзя ехать если хоть одна из зон >= max(r2_pos, r2_lock) - кол-во пограничных зон
|
||||||
short border = robot1.dx.current_zone;
|
short border = robot1.dx.current_zone;
|
||||||
if (border > robot1_lock_zone) {
|
if (border > robot1_lock_zone) {
|
||||||
@@ -299,7 +322,6 @@ short can_move(struct barrel *bar, char robot_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// выставляет приоритет операции, предполагается что ее можно выполнить
|
|
||||||
short get_operation_priority(short barrel_id) {
|
short get_operation_priority(short barrel_id) {
|
||||||
// если барабан пустой и не в ночном режиме, приоритет ему 2
|
// если барабан пустой и не в ночном режиме, приоритет ему 2
|
||||||
if (barrels[barrel_id].flags.is_empty && !barrels[barrel_id].flags.is_night) {
|
if (barrels[barrel_id].flags.is_empty && !barrels[barrel_id].flags.is_night) {
|
||||||
@@ -404,7 +426,6 @@ char remove_barrel_from_zone(short zone) {
|
|||||||
|
|
||||||
#ifdef EMULATOR
|
#ifdef EMULATOR
|
||||||
void debug_print_robot_code(const struct robot_code *code, const short robot_id, int fd) {
|
void debug_print_robot_code(const struct robot_code *code, const short robot_id, int fd) {
|
||||||
// dprintf(fd, "INFO: code length is %d\n", cmd_index);
|
|
||||||
dprintf(fd, "Code for R%d, B%d:\n", robot_id, code->barrel_id);
|
dprintf(fd, "Code for R%d, B%d:\n", robot_id, code->barrel_id);
|
||||||
for (int i = 0; i < 16; i++) {
|
for (int i = 0; i < 16; i++) {
|
||||||
const short cmd_arg = (short)(code->code[i] & (short)(~ROBOT_CMD_MASK));
|
const short cmd_arg = (short)(code->code[i] & (short)(~ROBOT_CMD_MASK));
|
||||||
@@ -487,8 +508,19 @@ void debug_print_robot_code(const struct robot_code *code, const short robot_id,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void create_operation(struct robot_code *code, short barrel_id, const short start_zone, const short dest_zone,
|
void create_operation(short barrel_id, const short start_zone, const short dest_zone, const short robot_id) {
|
||||||
const short current_zone, const short robot_id) {
|
short current_zone;
|
||||||
|
struct robot_code *code;
|
||||||
|
if (robot_id == ROBOT_1) {
|
||||||
|
current_zone = robot1.dx.current_zone;
|
||||||
|
code = &robot1_code;
|
||||||
|
} else if (robot_id == ROBOT_2) {
|
||||||
|
current_zone = robot2.dx.current_zone;
|
||||||
|
code = &robot2_code;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// создаем код транзакции, пока обычный
|
// создаем код транзакции, пока обычный
|
||||||
if (barrel_id >= BARRELS_COUNT) {
|
if (barrel_id >= BARRELS_COUNT) {
|
||||||
barrel_id = -1;
|
barrel_id = -1;
|
||||||
@@ -500,6 +532,11 @@ void create_operation(struct robot_code *code, short barrel_id, const short star
|
|||||||
if (hla_night_mode && barrels[barrel_id].flags.is_empty && dest_zone == get_first_night_zone()) {
|
if (hla_night_mode && barrels[barrel_id].flags.is_empty && dest_zone == get_first_night_zone()) {
|
||||||
barrels[barrel_id].flags.is_night = -1;
|
barrels[barrel_id].flags.is_night = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// сброс флага повторного цинкования во время создания задания
|
||||||
|
if (start_zone == ZONE_LOAD_2) {
|
||||||
|
hla_zinc_again = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
short cmd_index = 0;
|
short cmd_index = 0;
|
||||||
|
75
utils.h
75
utils.h
@@ -30,7 +30,7 @@ enum Zones {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define BARRELS_COUNT 10
|
#define BARRELS_COUNT 12
|
||||||
|
|
||||||
union barrel_flags {
|
union barrel_flags {
|
||||||
short raw_word;
|
short raw_word;
|
||||||
@@ -130,24 +130,9 @@ struct robot_regs {
|
|||||||
|
|
||||||
// NOTE первой командой на любую транзакцию должна стоять команда опустить траверсу (в 22 зоне по идее никогда не закончим)
|
// NOTE первой командой на любую транзакцию должна стоять команда опустить траверсу (в 22 зоне по идее никогда не закончим)
|
||||||
struct robot_code {
|
struct robot_code {
|
||||||
short barrel_id; // нужен ID барабана, если
|
short barrel_id; // если требуются операции с барабаном, то для корректного исполнения нужно указать значение >= 0
|
||||||
short PC; // когда -1, код не выполняется
|
short PC; // когда -1, код не выполняется
|
||||||
|
|
||||||
/*
|
|
||||||
* система команд, которая нужна: (квадратные скобки - аргумент это младшие 14 бит)
|
|
||||||
* 0 (смещение: да () ? нет): установить смещение (да - встанет в смещенную позицию, нет - в точную)
|
|
||||||
* 1 (опция с барабаном) [поднять (1) | опустить]: поднять/опустить траверсу (перед поднятием ожидать если таймер барабана не истек)
|
|
||||||
* 2 (опция с барабаном) [зона]: съебаться в зону
|
|
||||||
* 3 [сек]: пауза на нужное количество секунд
|
|
||||||
* 4 [время]: установить таймер барабану
|
|
||||||
* 5 (ETCH(1) | GAL (2)) [зона]: установить зону блокировки, умеет использовать автоинкримент зоны гальваники или обезжиривания
|
|
||||||
* 6 [X(1) | Y(2)]: скорректировать ось
|
|
||||||
* 15: конец
|
|
||||||
*
|
|
||||||
* формат команды: (команда, старший байт) [младший байт, аргумент команды (если есть)] [слово, аргумент если команда требует]
|
|
||||||
*/
|
|
||||||
unsigned short code[16]; // формат кода: [команды] <команда 0>
|
unsigned short code[16]; // формат кода: [команды] <команда 0>
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -197,6 +182,7 @@ extern char auto_mode_pause;
|
|||||||
// Кнопки с панели
|
// Кнопки с панели
|
||||||
extern char hla_night_mode;
|
extern char hla_night_mode;
|
||||||
extern char hla_correct_command;
|
extern char hla_correct_command;
|
||||||
|
extern char hla_zinc_again;
|
||||||
|
|
||||||
// разрешение на работу планировщика
|
// разрешение на работу планировщика
|
||||||
extern char scheduler_en;
|
extern char scheduler_en;
|
||||||
@@ -241,6 +227,7 @@ extern short scheduler_stage;
|
|||||||
|
|
||||||
#define auto_mode_pause _c_auto_mode_pause
|
#define auto_mode_pause _c_auto_mode_pause
|
||||||
#define hla_night_mode _c_hla_night_mode
|
#define hla_night_mode _c_hla_night_mode
|
||||||
|
#define hla_zinc_again _c_hla_zinc_again
|
||||||
#define hla_correct_command _c_hla_correct_command
|
#define hla_correct_command _c_hla_correct_command
|
||||||
|
|
||||||
#define scheduler_stage _c_scheduler_stage
|
#define scheduler_stage _c_scheduler_stage
|
||||||
@@ -250,6 +237,8 @@ extern short scheduler_stage;
|
|||||||
extern const short NIGHT_ZONES[9];
|
extern const short NIGHT_ZONES[9];
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================== ROBOT CODE ======================== */
|
||||||
|
|
||||||
#define ROBOT_CMD_MASK 0xF000U
|
#define ROBOT_CMD_MASK 0xF000U
|
||||||
#define ROBOT_CMD_END_code 0x0000U
|
#define ROBOT_CMD_END_code 0x0000U
|
||||||
#define ROBOT_CMD_MOVE_TO_ZONE_code 0x1000U
|
#define ROBOT_CMD_MOVE_TO_ZONE_code 0x1000U
|
||||||
@@ -300,7 +289,7 @@ extern const short NIGHT_ZONES[9];
|
|||||||
#define ROBOT_CMD_INC_ZONE(arg) (ROBOT_CMD_INC_ZONE_code | (unsigned short)(arg))
|
#define ROBOT_CMD_INC_ZONE(arg) (ROBOT_CMD_INC_ZONE_code | (unsigned short)(arg))
|
||||||
|
|
||||||
|
|
||||||
/* ======================== DISABLED ZONES DEFS ======================== */
|
/* ======================== DISABLED ZONES ======================== */
|
||||||
|
|
||||||
#define DISABLED_ETCH_1 0x0001
|
#define DISABLED_ETCH_1 0x0001
|
||||||
#define DISABLED_ETCH_2 0x0002
|
#define DISABLED_ETCH_2 0x0002
|
||||||
@@ -316,7 +305,8 @@ extern const short NIGHT_ZONES[9];
|
|||||||
#define DISABLED_GAL_8 0x0200
|
#define DISABLED_GAL_8 0x0200
|
||||||
#define DISABLED_GAL 0x03FC
|
#define DISABLED_GAL 0x03FC
|
||||||
|
|
||||||
/* ======================== IO DEFS ======================== */
|
|
||||||
|
/* ======================== IO ======================== */
|
||||||
|
|
||||||
#define ROBOT1_X 1
|
#define ROBOT1_X 1
|
||||||
#define ROBOT1_Z 2
|
#define ROBOT1_Z 2
|
||||||
@@ -327,8 +317,6 @@ extern const short NIGHT_ZONES[9];
|
|||||||
#define VFD_REG_D0_ADDR 4096
|
#define VFD_REG_D0_ADDR 4096
|
||||||
#define VFD_REG_M0_ADDR 2048
|
#define VFD_REG_M0_ADDR 2048
|
||||||
|
|
||||||
/* ======================== ROBOT DEFS ======================== */
|
|
||||||
|
|
||||||
#define MB_CMD_WRITE_FLAG 5
|
#define MB_CMD_WRITE_FLAG 5
|
||||||
#define MB_CMD_WRITE_REG 6
|
#define MB_CMD_WRITE_REG 6
|
||||||
|
|
||||||
@@ -374,6 +362,13 @@ extern const short NIGHT_ZONES[9];
|
|||||||
#define ROBOT_X_TARGET_ZONE_ADDR (VFD_REG_D0_ADDR + ROBOT_X_TARGET_ZONE_OFFSET)
|
#define ROBOT_X_TARGET_ZONE_ADDR (VFD_REG_D0_ADDR + ROBOT_X_TARGET_ZONE_OFFSET)
|
||||||
|
|
||||||
|
|
||||||
|
/* ======================== UTILS FUNCTIONS ======================== */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Занята ли зона. Учитываются только барабаны, которые внизу
|
||||||
|
* @param zone зона для обнаружения
|
||||||
|
* @return true если занята, в противном случае false
|
||||||
|
*/
|
||||||
char zone_is_busy(short zone);
|
char zone_is_busy(short zone);
|
||||||
|
|
||||||
|
|
||||||
@@ -381,14 +376,38 @@ char zone_is_busy(short zone);
|
|||||||
#define ROBOT_2 2
|
#define ROBOT_2 2
|
||||||
#define ROBOT_NONE -1
|
#define ROBOT_NONE -1
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Функция, определяющая можно ли переместить барабан и куда его нужно переместить.
|
||||||
|
* @param bar указатель на барабан
|
||||||
|
* @param robot_id ID робота, нужно передавать всегда, в режиме одного робота учитывается время, в режиме двух роботов
|
||||||
|
* учитываются рабочие границы роботов. Для отключения учета времени и границ следует передать <code>ROBOT_NONE</code>.
|
||||||
|
* @return Зону, куда нужно переместить барабан. Если значение < 0, то барабан переместить в данный момент невозможно.
|
||||||
|
*/
|
||||||
short can_move(struct barrel *bar, char robot_id);
|
short can_move(struct barrel *bar, char robot_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получить приоритет для операции перемещения барабана. Учитывает взаимное положение барабанов на линии и аттрибуты барабана
|
||||||
|
* @note Вызывать следует только если барабан подлежит перемещению (<code>can_move</code> вернул значение >= 0)
|
||||||
|
* @param barrel_id номер барабана, для которого нужно вычислить приоритет.
|
||||||
|
* @return Приоритет операции. Чем больше число тем выше приоритет.
|
||||||
|
*/
|
||||||
short get_operation_priority(short barrel_id);
|
short get_operation_priority(short barrel_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Удаление барабана из зоны, учитывает блокировку барабана роботом и положение барабана (нельзя удалить висящий барабан).
|
||||||
|
* @param zone Зона, из которой требуется удалить барабана.
|
||||||
|
* @return true, если барабан был удален, в противном случае false.
|
||||||
|
*/
|
||||||
char remove_barrel_from_zone(short zone);
|
char remove_barrel_from_zone(short zone);
|
||||||
|
|
||||||
void create_operation(struct robot_code *code, const short barrel_id, const short start_zone, const short dest_zone,
|
/**
|
||||||
const short current_zone, const short robot_id);
|
* Создание операции на перемещение барабана.
|
||||||
|
* @param barrel_id индекс барабана в структуре барабана, функцией напрямую не учитывается, но копируется в структуру кода робота
|
||||||
|
* @param start_zone зона, откуда нужно переместить барабан
|
||||||
|
* @param dest_zone зона, куда нужно переместить барабан (если ZONE_PASSIVATION то фактически после операции барабан окажется в зоне промывки 4а)
|
||||||
|
* @param robot_id ID робота, который должен выполнить операцию
|
||||||
|
*/
|
||||||
|
void create_operation(short barrel_id, const short start_zone, const short dest_zone, const short robot_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Активна ли зона цинкования или травления
|
* Активна ли зона цинкования или травления
|
||||||
@@ -404,9 +423,19 @@ char is_accessible_zone(short zone);
|
|||||||
*/
|
*/
|
||||||
char increment_zone(short zone);
|
char increment_zone(short zone);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Получение первой ночной зоны, то есть зоны куда нужно ложить ночной барабан
|
||||||
|
* @return номер зоны, либо -1 если зона занята или еще нужна для обслуживания других барабанов
|
||||||
|
*/
|
||||||
short get_first_night_zone();
|
short get_first_night_zone();
|
||||||
|
|
||||||
#ifdef EMULATOR
|
#ifdef EMULATOR
|
||||||
|
/**
|
||||||
|
* Вывод структуры кода робота, работает только в эмуляторе.
|
||||||
|
* @param code структура кода робота, именно ее и будет выводить функция
|
||||||
|
* @param robot_id ID робота (1 или 2), нужно для вывода отладочной информации
|
||||||
|
* @param fd file descriptor, устройство куда нужно записать весь вывод
|
||||||
|
*/
|
||||||
void debug_print_robot_code(const struct robot_code *code, const short robot_id, int fd);
|
void debug_print_robot_code(const struct robot_code *code, const short robot_id, int fd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user