Exemple #1
0
// function-thread (task), that serves requests from DMA1 iterrupt
//==============================================================================
void vSDTask( void* pvParameters )
{ 
  S_Sd_Param_t message;
  int state = 0; // sd card is off
   
  while( 1 )
  {
    // waiting for messages from ISR or another sources
    xQueueReceive( queu_to_sd, ( void* )&message, portMAX_DELAY );
    
    switch( message.type ) 
    {
      case SD_EVENT:
      {
        if( state )  // if sd card is on
        {
          state = 0;
          
          close_file();     
          de_init_TIM5();    
          //write_file();  //write close time
        
          lock_send_message_to_sd_thread = 1; // disallow to send message from DMA 1 ch1 ISR to sd_thread         
        }
        else         // if sd card is off
        {                
          if( init_sd() ) // if init of sd card is failed
          {
            de_init_TIM5();
            break;
          }
          
          state = 1;
          
          open_file();
          //write_file();  //write open time
          
          lock_send_message_to_sd_thread = 0; // allow to send message from DMA 1 ch1 ISR to sd_thread 
        }
      }
      break;      
      
      case SD_WRITE:
      {
        write_file( message.data, message.num );
      }
      break;
      
      default: break;
   }
  } // while( 1 )

  // destroy task, if exit from while was occured
  vTaskDelete( NULL );
 }
Exemple #2
0
void init_qubit_ctx()
{
#ifdef LUFFA_SSE2_BROKEN
        sph_luffa512_init(&qubit_ctx.luffa);
#else
        init_luffa(&qubit_ctx.luffa,512);
#endif
        cubehashInit(&qubit_ctx.cubehash,512,16,32);
        sph_shavite512_init(&qubit_ctx.shavite);
        init_sd(&qubit_ctx.simd,512);
#ifdef NO_AES_NI
        sph_echo512_init(&qubit_ctx.echo);
#else
        init_echo(&qubit_ctx.echo, 512);
#endif
};
Exemple #3
0
void init_x14_ctx()
{
#ifdef NO_AES_NI
        sph_groestl512_init(&x14_ctx.groestl);
        sph_echo512_init(&x14_ctx.echo);
#else
        init_echo(&x14_ctx.echo, 512);
        init_groestl(&x14_ctx.groestl);
#endif
        init_luffa(&x14_ctx.luffa,512);
        cubehashInit(&x14_ctx.cubehash,512,16,32);
        sph_shavite512_init(&x14_ctx.shavite);
        init_sd(&x14_ctx.simd,512);
        sph_hamsi512_init(&x14_ctx.hamsi);
        sph_fugue512_init(&x14_ctx.fugue);
        sph_shabal512_init(&x14_ctx.shabal);
};
void init_Xhash_contexts(){

	//---luffa---
	init_luffa(&base_contexts.luffa,512);
	//--ch sse2---
	cubehashInit(&base_contexts.cubehash,512,16,32);
	//-------
	sph_shavite512_init(&base_contexts.shavite1);
	//---echo sphlib or AESNI-----------
	#ifdef AES_NI
  	init_echo(&base_contexts.echo1, 512);
	#else
	sph_echo512_init(&base_contexts.echo1);
	#endif
	//---local simd var ---
	init_sd(&base_contexts.ctx_simd1,512);
}
Exemple #5
0
/*
 * sd_write : writes to a file from a loaded sd card
 *
 * @args sd_file : file name and content to be written
 */
void sd_write( struct sd_file *sd )
{
	if ( SD_CONNECTED == 0 ) {
		init_sd();
	}

	// file handle for file to be written
	short int fh;

	if ( alt_up_sd_card_is_Present() && alt_up_sd_card_is_FAT16() ) {
		fh = alt_up_sd_card_fopen( sd->name, false );

		if (fh == -1) {
			fh = alt_up_sd_card_fopen( sd->name, true );
		}

		if ( fh != -1 ) {
			SD_OPEN = 1;

			// write sd_file to sd card
			int i = 0;
			int length = strlen( sd->data );
			for ( i = 0; i < length; i ++ ) {
				if ( alt_up_sd_card_write( fh, sd->data[i] ) == false ) {
					printf( "ERROR! failure during write to %s. Failure @ char #%d of %d\n", sd->name, i, length );
					SD_ERROR = 1;
					return;
				}
			}

			// close file handle
			alt_up_sd_card_fclose( fh );
			SD_ERROR = 0;
			SD_OPEN = 1;
			printf( "SUCCESS! File written: %s\n", sd->name );
		} else {
			printf( "ERROR! could not write the file: %s\n", sd->name );
			SD_ERROR = 1;
		}
	} else {
		printf( "ERROR! SD card is either not present or is not FAT 16\n" );
		SD_ERROR = 1;
	}
}
Exemple #6
0
/*
 * sd_read : reads in a file from a loaded sd card
 *
 * @args file_name : file name relative to sd root folder
 */
char * sd_read( char *file_name )
{
	if ( SD_CONNECTED == 0 ) {
		init_sd();
	}

	// file handle for file being read
	short int fh;

	if ( alt_up_sd_card_is_Present() && alt_up_sd_card_is_FAT16() ) {
		fh = alt_up_sd_card_fopen( file_name, false );

		if (fh != -1) {
			SD_OPEN = 1;

			unsigned char *reading;  // data read
			char current;            // current char read
			int index = 0;			 // current position in file

			// read in all chars
			while ( ( current = alt_up_sd_card_read( fh ) ) >= 0 ) {
				reading[ index ] = malloc(1);
				reading[ index ] = current;
				++index;
			}

			// close file handle
			alt_up_sd_card_fclose( fh );

			// print out file contents
			return reading;
		} else {
			printf( "ERROR! can't open file: %s\n", file_name );
			SD_ERROR = 1;
			return "";
		}
	} else {
		printf( "ERROR! SD card is either not present or is not FAT 16\n" );
		SD_ERROR = 1;
		return "";
	}

}
Exemple #7
0
void mmcsd_detect(void *param)
{
	struct rt_mmcsd_host *host;
	rt_uint32_t  ocr;
	rt_int32_t  err;

	while (1) 
	{
		if (rt_mb_recv(&mmcsd_detect_mb, (rt_uint32_t*)&host, RT_WAITING_FOREVER) == RT_EOK)
		{
			if (host->card == RT_NULL)
			{
				mmcsd_host_lock(host);
				mmcsd_power_up(host);
				mmcsd_go_idle(host);

				mmcsd_send_if_cond(host, host->valid_ocr);

				err = sdio_io_send_op_cond(host, 0, &ocr);
				if (!err) {
					if (init_sdio(host, ocr))
						mmcsd_power_off(host);
					mmcsd_host_unlock(host);
					continue;
				}

				/*
				 * detect SD card
				 */
				err = mmcsd_send_app_op_cond(host, 0, &ocr);
				if (!err) 
				{
					if (init_sd(host, ocr))
						mmcsd_power_off(host);
					mmcsd_host_unlock(host);
					continue;
				}
				mmcsd_host_unlock(host);
			}
		}
	}
}
Exemple #8
0
/*----------------------------------------------------------------------------*/
u8 device_init(void)
{
    u8 sector_sizeof512 = 1;
    device_check();
    if (device_active & device_online)  ///<当前需要活动的设备在线
    {
        disp_port(MENU_SCAN_DISK);

        stop_decode();
//        deg_str("device init\n");
        fs_fun_init();

        if ((device_active & (~VIRTUAL_DEVICE)) == DEVICE_SDMMC0)
        {
            if (init_sd())                  ///<sd 卡鉴定
            {
                f_init(win_buffer, (u16)sdmmc_read, 1);//get_usb_device_pkt_size());    ///<鉴定成功后 初始化文件系统参数
            }
            else
            {
			return 0xff;                       ///<鉴定失败
            }

        }

        else if ((device_active & (~VIRTUAL_DEVICE)) == DEVICE_UDISK)
        {
            if (usb_host_emuerate_devcie(win_buffer))     ///<USB MASS STORAGE 枚举
            {
                sector_sizeof512 = get_usb_device_pkt_size();
                f_init(win_buffer, (u16)read_usb, sector_sizeof512);      ///<枚举成功后 初始化文件系统参数
            }
            else
            {
                return 0xff;             ///<枚举失败
            }
        }

    }
    else
    {
        return 0xff;
    }

//    deg_str("fat init\n");
    //if (!f_mount())                                      ///<文件系统初始化
    if (!f_mount_bsp(sector_sizeof512))
    {
        
        if((RECODE_INIT == encode_status))
        {
             if(0 == f_write_init(device_active & (~VIRTUAL_DEVICE)))  //初始化写设备的数据
             {
                 return 0xfd;
             }
             else
             {
                 return 0;
             }
        }
        fs_ext_setting(file_type);
        {
            u16 break_point;
            //get_rec_mem_info();
            if ((device_active & (~VIRTUAL_DEVICE)) == DEVICE_SDMMC0)
            {
                //break_point = disk_mus_point[0 + encode_cnt].id0;
			break_point = read_info(MEM_SD_PLAYPOINT_ID0);
			break_point=break_point<<8;
			break_point |= read_info(MEM_SD_PLAYPOINT_ID0+1);                
            }
            else if ((device_active & (~VIRTUAL_DEVICE) ) == DEVICE_UDISK)
            {
               // break_point = disk_mus_point[1 + encode_cnt].id0;
			break_point = read_info(MEM_USB_PLAYPOINT_ID0);
			break_point=break_point<<8;
			break_point |= read_info(MEM_USB_PLAYPOINT_ID0+1);                
		}
			
            	break_point_filenum = fs_scan_disk(break_point);
    		encode_fristfile = fs_msg_rec.firstfilenum;	  //录音文件总数
            	encode_filenum = fs_msg_rec.fileTotalInDir;	  //录音文件夹的第一个文件号

            //if (break_point_filenum)
            {
                //break_point_filenum = filenum_phy_logic(break_point_filenum);
            }
        }
		     




#if VIRTUAL_ENABLE
        logic_fileTotal = fs_msg.fileTotal - encode_filenum;          ///音乐文件总数

        if(device_active & VIRTUAL_DEVICE)
        {
            logic_fileTotal = encode_filenum;	//录音文件总数
        }
#else
        logic_fileTotal = fs_msg.fileTotal;
#endif
        
		
        if(0 == logic_fileTotal)//if (fs_msg.fileTotal == 0)
        {
            return 0xfe;
        }

        return 0;
    }
    else
    {
        return 0xff;	//无有效设备
    }
}
Exemple #9
0
int main()
{
	arr = (unsigned int**)malloc(4377 * sizeof(unsigned int));
	psController ps;
	int velocity = 0;
	int angle = 0;
	long ii = 0;
	int** collisionMatrix;
	int ee;
	int numfiles;
	char * filenames[MAXFILES];

	//init_VGA_Pixel();
	initVGA(); //pixel
	init_VGA_Char();
	av_config_setup();
	numfiles = init_sd(filenames);
	init_wav(arr);
	printf("timing audio\n");
	//time_of_sound = time_audio(arr);
	printf("looping audio\n");

	audio_isr_k = 0;
	alt_irq_register(AUDIO_IRQ, NULL, &audio_isr);
	alt_up_audio_enable_write_interrupt(audio);


	//====INITIALIZE AND DRAW TERRAIN USING BMP ===========================//
		short int fd;

		terrain background;
		fd = alt_up_sd_card_fopen("bg.bmp", false);
		initTerrain(fd, &background);
		drawBackground(background);
		alt_up_sd_card_fclose(fd);


		terrain terrain;
		fd = alt_up_sd_card_fopen("tr.bmp", false);
		initTerrain(fd, &terrain);
		drawTerrain(terrain);
		alt_up_sd_card_fclose(fd);

	//====INITIALIZE AND DRAW USER TANK USING BMP ===========================//
		fd = alt_up_sd_card_fopen("tank.bmp", false);
		tank user;
		initUserTank(&user, fd);
		drawTank(&user, background);
		alt_up_sd_card_fclose(fd);
	//====INITIALIZE AND DRAW ENEMY TANK USING BMP ===========================//
		tank enemy;
		fd = alt_up_sd_card_fopen("tk.bmp", false);
		initEnemyTank1(&enemy, fd);
		drawTank(&enemy,background);
		alt_up_sd_card_fclose(fd);
	//====SWAP BUFFERS =======================================================//
		updateVGA();
		drawBackground(background);
		drawTerrain(terrain);
		drawTank(&enemy, background);
		for(ee=0;ee < 20;ee++)
		{
			moveTank(&user, RIGHT, 1);
			drawTank(&user,background);
			updateVGA();
			drawTank(&user,background);
			//delay();
		}
	//for(ii = 0; ii < 300000; ii++);

	collisionMatrix = init_CollisionMatrix(XMAXSCREEN_RESOLUTION + 1, XMAXSCREEN_RESOLUTION + 1);

	//alt_up_pixel_buffer_dma_draw_box(pixel_buffer, 0, 120, 340, 240, 0x7E0 , 0); //draw terrain

	set_CollisionAtRectArea(collisionMatrix, 0 , 0, 340, 240, EMPTY);
	set_CollisionAtRectArea(collisionMatrix, 0 , 161, 340, 240, TERRAIN_COLOR);//set the rectangular area drawn by terrain to filled with terrain
	while(1){
		//angle = 0;
		velocity = 0;
		set_UserTank(&angle, &velocity, ps, &user, &enemy, background); //reads controller to set angle, power, and shoot
		shoot_Missile(angle, velocity,( user.x + user.t_VGA.width) - 1 , (240 - user.y + user.t_VGA.height) - 7, collisionMatrix, background);

	}
	clean_audio(arr);
	return 0;
}
Exemple #10
0
// main init function executed 1 time only at boot
void setup(){
	init_pins();
	init_sd();
	load_os_msgs_from_sd();
	load_drugs_from_sd();	
}
Exemple #11
0
/*----------------------------------------------------------------------------*/
u8 device_init(void)
{
		usb_sd_dev_toc=0;		

    device_online = get_device_online_status();
	if(playpoint_time.last_device != device_active)
	{
		write_playtime(&playpoint_time);
	}
    if (device_active & device_online)  ///<当前需要活动的设备在线
    {
		flush_all_msg();                ///<清空全部消息
        stop_decode();                  ///<停止解码
#if FILE_ENCRYPTION
         password_start(0);
#endif

#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif

        if (device_active == BIT(USB_DISK))
        {
			if (usb_host_emuerate_devcie(win_buffer))     ///<USB MASS STORAGE 枚举
            {
#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif            
				f_init(win_buffer, (u16)usb_otp_read, get_usb_device_pkt_size());      ///<枚举成功后 初始化文件系统参数
            }
            else
            {
				return 0xff;             ///<枚举失败
            }
        }
        else if (device_active == BIT(SDMMC))
        {
			if (init_sd())                  ///<sd 卡鉴定
            {
#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif
            
				f_init(win_buffer, (u16)sdmmc_otp_read, 1);//get_usb_device_pkt_size());    ///<鉴定成功后 初始化文件系统参数
            }
            else
            {
				return 0xff;                       ///<鉴定失败
            }
        }
    }
#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif
	
    if (!f_mount())                                      ///<文件系统初始化
    {

#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif
    
		fs_ext_setting(file_type);
#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif

		set_playpoint_info(read_playpoint_info(device_active));
#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif

		fs_scan_disk();
#ifdef SYS_GPIO_SEL_FUNC
	     	if( gpio_sel_func){				
			return 0xff;
		 }
#endif

		playpoint_filenum = get_scan_filenumber();				   //根据对应设备的起始簇找出有断点的文件号
		/**/

		usb_sd_dev_toc=1;		
#ifdef DISABLE_USB_SD_BP_PLAY
			playpoint_filenum=0;
#endif		
		if(0 == playpoint_filenum)
		{
		    if(given_file_number)
			    given_file_number = 1;
		}
        if (fs_msg.fileTotal == 0)
        {

			return 0xfe;
        }
#if ((USE_DEVICE == MEMORY_STYLE)&&(FAT_MEMORY))    
        check_reserve_sector(device_active);
#endif 
        return 0;
    }
    else
	{
                                                 //无有效设备
        return 0xff;
	}
}
Exemple #12
0
/*
 * Application entry point.
 */
int main(void) {
  /*
   * System initializations.
   * - HAL initialization, this also initializes the configured device drivers
   *   and performs the board-specific initializations.
   * - Kernel initialization, the main() function becomes a thread and the
   *   RTOS is active.
   */
  halInit();
  chSysInit();

  /*
   * Activates the serial driver 2 and SDC driver 1 using default
   * configuration.
   */
  sdStart(&SD6, NULL);

  BaseSequentialStream *chp = (BaseSequentialStream *)&SD6;
  chprintf(chp, "running main()\r\n");
  chThdSleepMilliseconds(50);

#if STM32_USB_USE_OTG2
  USBDriver *usb_driver = &USBD2;
#else
  USBDriver *usb_driver = &USBD1;
#endif

  /*
   * Activates the card insertion monitor.
   */
  init_sd();
  chprintf(chp, "done starting SDC\r\n");
  const bool_t sdcConnectStatus = sdcConnect(&SDCD1);
  if( sdcConnectStatus != CH_SUCCESS ) {
    chprintf(chp, "failed to connect to SD Card, sdcConnectStatus = %u\r\n", sdcConnectStatus);
    for(;;) {
      chThdSleepMilliseconds(3000);
    }
  }

  chprintf(chp, "setting up MSD\r\n");
  const usb_msd_driver_state_t msd_driver_state = msdInit(usb_driver, (BaseBlockDevice*)&SDCD1, &UMSD1, USB_MS_DATA_EP, USB_MSD_INTERFACE_NUMBER);
  if( msd_driver_state != USB_MSD_DRIVER_OK ) {
    chprintf(chp, "Error initing USB MSD, %d %s\r\n", msd_driver_state, usb_msd_driver_state_t_to_str(msd_driver_state));
  }
  UMSD1.chp = chp;

  chprintf(chp, "Initializing SDU1...\r\n");
  serusbcfg.usbp = usb_driver;
  sduObjectInit(&SDU1);

  /*Disconnect the USB Bus*/
  usbDisconnectBus(usb_driver);
  chThdSleepMilliseconds(200);

  /*Start the useful functions*/
  sduStart(&SDU1, &serusbcfg);
  msdStart(&UMSD1);
  usbStart(usb_driver, &msd_usb_config);

  /*Connect the USB Bus*/
  usbConnectBus(usb_driver);

  /*
   * Creates the blinker thread.
   */
  chprintf(chp, "starting blinker thread\r\n");
  chThdCreateStatic(waThread1, sizeof(waThread1), NORMALPRIO, Thread1, NULL);

  while (TRUE) {
    palTogglePad(GPIOC, GPIOC_LED);
    chThdSleepMilliseconds(500);
  }
}
Exemple #13
0
int gpt_find_boot_partition(uint8_t* dest, uint32_t size)
{
    int ret = init_sd();
    if (ret != 0) {
        print_uart("could not initialize sd... exiting\r\n");
        return -1;
    }

    print_uart("sd initialized!\r\n");

    // load LBA1
    size_t block_size = 512;
    uint8_t lba1_buf[block_size];

    int res = sd_copy(lba1_buf, 1, 1);

    if (res != 0)
    {
        print_uart("SD card failed!\r\n");
        print_uart("sd copy return value: ");
        print_uart_addr(res);
        print_uart("\r\n");
        return -2;
    }

    gpt_pth_t *lba1 = (gpt_pth_t *)lba1_buf;

    print_uart("gpt partition table header:");
    print_uart("\r\n\tsignature:\t");
    print_uart_addr(lba1->signature);
    print_uart("\r\n\trevision:\t");
    print_uart_int(lba1->revision);
    print_uart("\r\n\tsize:\t\t");
    print_uart_int(lba1->header_size);
    print_uart("\r\n\tcrc_header:\t");
    print_uart_int(lba1->crc_header);
    print_uart("\r\n\treserved:\t");
    print_uart_int(lba1->reserved);
    print_uart("\r\n\tcurrent lba:\t");
    print_uart_addr(lba1->current_lba);
    print_uart("\r\n\tbackup lda:\t");
    print_uart_addr(lba1->backup_lba);
    print_uart("\r\n\tpartition entries lba:   \t");
    print_uart_addr(lba1->partition_entries_lba);
    print_uart("\r\n\tnumber partition entries:\t");
    print_uart_int(lba1->nr_partition_entries);
    print_uart("\r\n\tsize partition entries:  \t");
    print_uart_int(lba1->size_partition_entry);
    print_uart("\r\n");

    uint8_t lba2_buf[block_size];

    res = sd_copy(lba2_buf, lba1->partition_entries_lba, 1);

    if (res != 0)
    {
        print_uart("SD card failed!\r\n");
        print_uart("sd copy return value: ");
        print_uart_addr(res);
        print_uart("\r\n");
        return -2;
    }

    for (int i = 0; i < 4; i++)
    {
        partition_entries_t *part_entry = (partition_entries_t *)(lba2_buf + (i * 128));
        print_uart("gpt partition entry ");
        print_uart_byte(i);
        print_uart("\r\n\tpartition type guid:\t");
        for (int j = 0; j < 16; j++)
            print_uart_byte(part_entry->partition_type_guid[j]);
        print_uart("\r\n\tpartition guid:     \t");
        for (int j = 0; j < 16; j++)
            print_uart_byte(part_entry->partition_guid[j]);
        print_uart("\r\n\tfirst lba:\t");
        print_uart_addr(part_entry->first_lba);
        print_uart("\r\n\tlast lba:\t");
        print_uart_addr(part_entry->last_lba);
        print_uart("\r\n\tattributes:\t");
        print_uart_addr(part_entry->attributes);
        print_uart("\r\n\tname:\t");
        for (int j = 0; j < 72; j++)
            print_uart_byte(part_entry->name[j]);
        print_uart("\r\n");
    }

    partition_entries_t *boot = (partition_entries_t *)(lba2_buf);
    print_uart("copying boot image ");
    print_uart("\r\n");
    res = sd_copy(dest, boot->first_lba, size);

    if (res != 0)
    {
        print_uart("SD card failed!\r\n");
        print_uart("sd copy return value: ");
        print_uart_addr(res);
        print_uart("\r\n");
        return -2;
    }

    print_uart(" done!\r\n");
    return 0;
}
Exemple #14
0
void mmcsd_detect(void *param)
{
    struct rt_mmcsd_host *host;
    rt_uint32_t  ocr;
    rt_int32_t  err;

    while (1) 
    {
        if (rt_mb_recv(&mmcsd_detect_mb, (rt_uint32_t*)&host, RT_WAITING_FOREVER) == RT_EOK)
        {
            if (host->card == RT_NULL)
            {
                mmcsd_host_lock(host);
                mmcsd_power_up(host);
                mmcsd_go_idle(host);

                mmcsd_send_if_cond(host, host->valid_ocr);

                err = sdio_io_send_op_cond(host, 0, &ocr);
                if (!err)
                {
                    if (init_sdio(host, ocr))
                        mmcsd_power_off(host);
                    mmcsd_host_unlock(host);
                    continue;
                }

                /*
                 * detect SD card
                 */
                err = mmcsd_send_app_op_cond(host, 0, &ocr);
                if (!err) 
                {
                    if (init_sd(host, ocr))
                        mmcsd_power_off(host);
                    mmcsd_host_unlock(host);
                    continue;
                }
                
                /*
                 * detect mmc card
                 */
                err = mmc_send_op_cond(host, 0, &ocr);
                if (!err) 
                {
                    if (init_mmc(host, ocr))
                        mmcsd_power_off(host);
                    mmcsd_host_unlock(host);
                    continue;
                }
                mmcsd_host_unlock(host);
            }
            else
            {
            	/* card removed */
            	mmcsd_host_lock(host);
            	if (host->card->sdio_function_num != 0)
            	{
            		rt_kprintf("unsupport sdio card plug out!\n");
            	}
            	else
            	{
            		rt_mmcsd_blk_remove(host->card);
            		rt_free(host->card);

            		host->card = RT_NULL;
            	}
            	mmcsd_host_unlock(host);
            }
        }
    }
}