diff --git a/main_fw/atmel_start_prj/config/hpl_adc_config.h b/main_fw/atmel_start_prj/config/hpl_adc_config.h
index 1b19a73c5fea68ebb87150100bcf4d56efcf5bd5..d10a5abed86a30fc45656b8e9e61f48edb660826 100644
--- a/main_fw/atmel_start_prj/config/hpl_adc_config.h
+++ b/main_fw/atmel_start_prj/config/hpl_adc_config.h
@@ -243,8 +243,12 @@
 // <i>This register gives the number of input sources included in pin scan. The number of input sources included is INPUTSCAN + 1. 0 disables the input scan feature. (INPUTSCAN)
 // <id> adc_arch_inputscan
 #ifndef CONF_ADC_0_INPUTSCAN
+#ifdef MMRTSB
+#define CONF_ADC_0_INPUTSCAN 18
+#else
 #define CONF_ADC_0_INPUTSCAN 11
 #endif
+#endif
 
 // <o> Positive Mux Setting Offset <0-15>
 // <i>When inputscan is enabled this value define the pin offset, which means that the actual input pin sampled is the muxpos pin + input offset.   (INPUTOFFSET)
diff --git a/main_fw/build/Makefile b/main_fw/build/Makefile
index 1935d2e8a195068176bfc2a7281146e664588013..ca074562b95911c101cf593034e4928299ba4486 100644
--- a/main_fw/build/Makefile
+++ b/main_fw/build/Makefile
@@ -2,6 +2,9 @@
 # Adapted from automatically-generated file. Careful to update when necessary.
 ################################################################################
 
+# The legal values for VER are "RTSB", "FANT", and "RATO".
+VER = RTSB
+
 USE_CLANG = true
 USE_CLANG_OPT = true
 USE_CLANG_COAST = true
@@ -15,7 +18,19 @@ USB_ENABLE =
 # CLANG_COAST_PATH=~/Downloads/build/coast-master/build/lib/
 CLANG_NEWLIB_PATH=/usr/armv6m-none-eabi
 
-CFLAGS=-mcpu=cortex-m0plus -DDEBUG -D__SAMD21G18A__ -Wall -c -std=gnu99 -ffunction-sections -mlong-calls -fomit-frame-pointer --sysroot=/usr/arm-none-eabi
+ifeq ($(VER),RTSB)
+MMVER=-DMMRTSB
+else ifeq ($(VER),FANT)
+MMVER=-DMMFANT
+else ifeq ($(VER),RATO)
+MMVER=-DMMRATO
+else ifeq ($(VER),PROT)
+MMVER=-DMMPROT
+else
+$(error need to provide a legal value for VER)
+endif
+
+CFLAGS=-mcpu=cortex-m0plus -DDEBUG -D__SAMD21G18A__ $(MMVER) -Wall -c -std=gnu99 -ffunction-sections -mlong-calls -fomit-frame-pointer --sysroot=/usr/arm-none-eabi
 GCC_CFLAGS=-march=armv6-m -mcpu=cortex-m0plus -mthumb -Os -g3
 CLANG_CFLAGS=-DUSE_CLANG -I$(CLANG_NEWLIB_PATH)/include/ -flto -Os -fshort-enums -ffreestanding --target=arm-none-eabi -march=thumbv6m -g
 EXTRA_OPT_ARGS=
diff --git a/main_fw/src/i2c_impl.c b/main_fw/src/i2c_impl.c
index 48f5e055bf236300aa7ef605dce97834bc3c53db..1f7d2fbf9a1b26f3aaaabdb664e34eebecf04012 100644
--- a/main_fw/src/i2c_impl.c
+++ b/main_fw/src/i2c_impl.c
@@ -9,7 +9,17 @@
 
 const char MFR_ID[] = "CERN (BE/CO)";
 const char MFR_MDL[] = "DI/OT MoniMod";
-const char MFR_REV[] = "0.2p";
+#if defined MMRTSB
+const char MFR_REV[] = "0.2p-RTSB";
+#elif defined MMFANT
+const char MFR_REV[] = "0.2p-FANT";
+#elif defined MMRATO
+const char MFR_REV[] = "0.2p-RATO";
+#elif defined MMPROT
+const char MFR_REV[] = "0.2p-PROT";
+#else
+#error Exactly one of MMRTSB, MMFANT, MMRATO or MMPROT has to be defined
+#endif
 const char MFR_LOC[] = "Geneva";
 const char MFR_DAT[] = "200629";
 const char MFR_SER[] = "123456789";
@@ -183,8 +193,13 @@ void boot_new_fw()
 
 void __xMR page_chk()
 {
-        if (page_tmp > 2)
-                page = 2;
+#ifdef MMRTSB
+#define MAX_PAGE 3
+#else
+#define MAX_PAGE 2
+#endif
+        if (page_tmp > MAX_PAGE)
+                page = MAX_PAGE;
         else
                 page = page_tmp;
 }
@@ -218,6 +233,13 @@ void query_prp()
 }
 
 
+void __xMR set_pec()
+{
+        use_pec = use_pec_tmp;
+}
+
+#if defined(MMFANT) || defined(MMPROT)
+
 void __xMR fan_config()
 {
         fan_installed[0] = (fan_config_1_2 >> 7) & 0x1;
@@ -242,12 +264,6 @@ void __xMR set_frpms()
 }
 
 
-void __xMR set_pec()
-{
-        use_pec = use_pec_tmp;
-}
-
-
 void __xMR set_tc_curve()
 {
         uint8_t fan_n = temp_curve_points_data[0];
@@ -271,3 +287,27 @@ void __xMR set_tc_onoff()
 {
         temp_control_on = tc_on;
 }
+
+#else
+
+void fan_config()
+{
+}
+
+void set_frpms()
+{
+}
+
+void set_tc_curve()
+{
+}
+
+void set_tc_matrix()
+{
+}
+
+void set_tc_onoff()
+{
+}
+
+#endif
diff --git a/main_fw/src/main.c b/main_fw/src/main.c
index af32d0c583cb922cad423ef37159fd61fbc0831d..e93471878916124490865c5a78a11027ef859f92 100644
--- a/main_fw/src/main.c
+++ b/main_fw/src/main.c
@@ -19,10 +19,16 @@ extern cmd_space_t cmds;
 //! Our custom commmands structure
 extern cmd_space_t ext_cmds;
 
+#ifdef MMRTSB
+#define MAX_PAGE 3
+#else
+#define MAX_PAGE 2
+#endif
+
+uint16_t volts_lin[MAX_PAGE+1];
+uint16_t currs_lin[MAX_PAGE+1];
+uint16_t powrs_lin[MAX_PAGE+1];
 uint16_t temps_lin[3];
-uint16_t volts_lin[3];
-uint16_t currs_lin[3];
-uint16_t powrs_lin[3];
 uint16_t frpms_lin[3];
 
 #define TOTAL_PWM_CLOCKS 255
@@ -38,18 +44,25 @@ int16_t goal_pwm_duty1000_2 = FAN_RAMPUP;
 int16_t goal_pwm_duty1000_3 = FAN_RAMPUP;
 
 static uint16_t iter __xMR;
+
+#if defined(MMFANT) || defined(MMPROT)
 static uint16_t fan_ramp_up_count __xMR = 0;
+#endif
 
 uint16_t tacho_cnt[3];
 uint16_t tacho_rpm[3];
 
 // when fan_cmdrpm is 0, setfrpms and temp_curve_points_y represent
 // duty cycle (0 to 1000)
-uint16_t fan_installed[3] __xMR = {1, 1, 0};
+#if defined(MMFANT) || defined(MMPROT)
+uint16_t fan_installed[3] __xMR = {1, 1, 1};
+#else
+uint16_t fan_installed[3] __xMR = {0, 0, 0};
+#endif
 uint16_t fan_cmdrpm[3] __xMR = {0, 0, 0};
 uint16_t fan_ppr[3] __xMR = {1, 1, 1}; // a 1 here means 2 pulses per revolution
 
-uint16_t setfrpms[3] __xMR = {600, 600, 0};
+uint16_t setfrpms[3] __xMR = {600, 600, 600};
 
 pid_cntrl_t PID1 __xMR;
 pid_cntrl_t PID2 __xMR;
@@ -71,15 +84,48 @@ float currs[3];
 #define ADC_MAX 65535.0
 
 // V[V] = V_adc * scaling_coeff
-const float volt_scaling_coeff[3] = {(10.0+2.0)/2.0, (18.0+10.0)/10.0, (10.0+10.0)/10.0};
-const float curr_scaling_coeff[3] = {1000.0*(1.0/10)*(1.0/0.1), 1000.0*(1.0/10)*(1.0/10), 1000*(1.0/10)*(1.0/10)};
-
+// I[mA] = V_adc * scaling_coeff
 // T[degC] = (V_adc + a) * b
+#if defined MMRTSB
+#define ADC_CH_MAX 19
+// Voltages: P12V, P1V2, P3V3, PPERIPH
+const float volt_scaling_coeff[4] = {(10.0+2.0)/2.0, 1.0/(1.0+(1.0/1.0)), (4.7+10.0)/10.0, (4.7+2.0)/2.0};
+// Current: P12V
+const float curr_scaling_coeff[3] = {1000.0*(1.0/10)/0.05, 0, 0};
+// Temperatures: ambient, 2.5V LDO, FPGA
+const float temp_coeff_a[3] = {0, 0, 0};
+const float temp_coeff_b[3] = {100.0/(1.0+10.0/10.0), 100.0/(1.0+10.0/10.0), 100.0/(1.0+10.0/10.0)};
+#elif defined MMFANT
+#define ADC_CH_MAX 12
+const float volt_scaling_coeff[3] = {0, 0, 0}; // TODO: fill those when the schematics are fixed
+const float curr_scaling_coeff[3] = {0, 0, 0};
+const float temp_coeff_a[3] = {0, 0, 0};
+const float temp_coeff_b[3] = {0, 0, 0};
+#elif defined MMRATO
+#define ADC_CH_MAX 12
+// Voltages: P12V, P5V
+const float volt_scaling_coeff[3] = {(10.0+2.0)/2.0, (16.0+10.0)/10.0, 0.0};
+// Currents: P12V, P5V
+const float curr_scaling_coeff[3] = {1000.0*((16.0+10.0)/10.0), 1000.0*((16.0+10.0)/10.0), 0.0};
+// Temperatures: ambient
+const float temp_coeff_a[3] = {0, 0, 0};
+const float temp_coeff_b[3] = {100.0/(1.0+10.0/10.0), 0, 0};
+#elif defined MMPROT
+#define ADC_CH_MAX 12
+// Voltages: P12V, P5V, P5V
+const float volt_scaling_coeff[3] = {(10.0+2.0)/2.0, (18.0+10.0)/10.0, (10.0+10.0)/10.0};
+// Currents: P12V, P5V, P5V
+const float curr_scaling_coeff[3] = {1000.0*(1.0/10)/0.1, 1000.0*(1.0/10)/10.0, 1000*(1.0/10)/10.0};
 const float temp_coeff_a[3] = {0, -1e-3*100.0*19.0, -1e-3*100.0*19.0};
 const float temp_coeff_b[3] = {100.0, 100.0/(1e-3*19.0*(138.5-100.0)), 100.0/(1e-3*19.0*(138.5-100.0))};
+#else
+#error Exactly one of MMRTSB, MMFANT or MMRATO has to be defined
+#endif
 
 uint16_t trig_adc_next_second __xMR = 0;
 
+#if defined(MMFANT) || defined(MMPROT)
+
 int16_t sign(int16_t x)
 {
         if (x < 0)
@@ -161,6 +207,8 @@ void update_pwm()
         pwm_set_parameters(&PWM_2, TOTAL_PWM_CLOCKS, (target_duty_3 < 255)?(target_duty_3):(254));
 }
 
+#endif
+
 void __xMR adc_cb(const struct adc_async_descriptor *const descr, const uint8_t channel)
 {
         adc_async_read_channel(&ADC_0, 0, (uint8_t *)&(adc_vals[adc_ch]), 2);
@@ -267,8 +315,12 @@ void __xMR adc_cb(const struct adc_async_descriptor *const descr, const uint8_t
 #endif
                 powrs_lin[2] = float_to_linear(volts[2] * currs[2]);
                 break;
+#ifdef MMRTSB
+        case 18:
+                break;
+#endif
         }
-        if (++adc_ch == 12) {
+        if (++adc_ch == ADC_CH_MAX) {
                 adc_ch = 0;
                 trig_adc_next_second = 1;
         } else
@@ -277,10 +329,12 @@ void __xMR adc_cb(const struct adc_async_descriptor *const descr, const uint8_t
 
 static void __xMR mytimercallback(const struct timer_task *const timer_task)
 {
+#if defined(MMFANT) || defined(MMPROT)
         update_pwm();
-
+#endif
         if (iter == 99) {
                 iter = 0;
+#if defined(MMFANT) || defined(MMPROT)
                 update_rpm();
                 if (temp_control_on) {
                         PID1.setpoint = compute_rpm(0);
@@ -320,7 +374,7 @@ static void __xMR mytimercallback(const struct timer_task *const timer_task)
                         else
                                 goal_pwm_duty1000_3 = PID3.setpoint;
                 }
-
+#endif
                 if (trig_adc_next_second) {
                         trig_adc_next_second = 0;
                         adc_async_start_conversion(&ADC_0);
@@ -331,6 +385,8 @@ static void __xMR mytimercallback(const struct timer_task *const timer_task)
         wdt_feed(&WDT_0);
 }
 
+#if defined(MMFANT) || defined(MMPROT)
+
 static void inc_tacho1(void)
 {
         ++tacho_cnt[0];
@@ -346,6 +402,8 @@ static void inc_tacho3(void)
         ++tacho_cnt[2];
 }
 
+#endif
+
 struct timer_task mytask;
 
 static void __attribute__((used)) __attribute__((noinline))
@@ -362,6 +420,7 @@ int main(void)
 	/* Initializes MCU, drivers and middleware */
 	atmel_start_init();
 
+#if defined(MMFANT) || defined(MMPROT)
         ext_irq_register(PIN_PA16, inc_tacho1);
         ext_irq_register(PIN_PA13, inc_tacho2);
         ext_irq_register(PIN_PB10, inc_tacho3);
@@ -373,7 +432,11 @@ int main(void)
 	pwm_enable(&PWM_0);
 	pwm_enable(&PWM_1);
 	pwm_enable(&PWM_2);
-
+#else
+        frpms_lin[0] = float_to_linear(0);
+        frpms_lin[1] = float_to_linear(0);
+        frpms_lin[2] = float_to_linear(0);
+#endif
         adc_async_register_callback(&ADC_0, 0, ADC_ASYNC_CONVERT_CB, &adc_cb);
 	adc_async_enable_channel(&ADC_0, 0);
         adc_async_start_conversion(&ADC_0);